Autoconnect with Microsoft Display Adapter using Windows.Devices.WiFiDirect - c#

First, I have extensively read through Autoconnect to MS Wireless display on Windows 10 and tried basically every solution. (I did technically get the AutoHotKey solution working, and in fact did that before even researching. But, I feel like that's kind of unprofessional and surely there is some API that can connect to this thing.) After going through all of this, I just started reading through the different namespaces. Finally, I found Windows.Devices.WiFiDirect. This gave me the most progress I've been able to get, which is, it begins to connect and says so on screen, then an exception stating that the device is unreachable occurs. Very infuriating.
Can anyone explain exactly what is happening here? It seems like this should be the proper way to connect my screen to this device, but it is just not working. Code below, it's pretty short and straightforward.
Edit:
Based on Roy Li's suggestion, I attempted to use a different overload of the socket.ConnectAsync method. This actually did have an effect but I am still receiving an exception, although a different one. The method now attempts to connect for longer but still fails out, this time with a "connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond" exception. Could this mean there is some sort of secret handshake that Window's OS is using when connecting to this device? If so, this might be a dead end. The code has been updated below.
static async Task Main()
{
string id = null;
string prefix = "MicrosoftDisplayAdapter";
WiFiDirectDevice device;
StreamSocket socket = new StreamSocket();
try
{
DeviceInformationCollection devInfoCollection = await DeviceInformation.FindAllAsync(WiFiDirectDevice.GetDeviceSelector());
foreach (DeviceInformation devInfo in devInfoCollection)
{
if (devInfo.Name.StartsWith(prefix))
{
id = devInfo.Id;
}
}
device = await WiFiDirectDevice.FromIdAsync(id);
var endpointPairCollection = device.GetConnectionEndpointPairs();
await socket.ConnectAsync(endpointPairCollection[0].RemoteHostName, "50001"); //This line begins connecting to the display but ultimately fails
}
catch (Exception e)
{
//device unreachable exception
}
}

I finally found something along the lines of what I need. I came across https://social.msdn.microsoft.com/Forums/en-US/7608d127-d864-436a-802e-472fd55cc02c/use-projectionmanager-from-net-framework?forum=csharpgeneral, which gave me a way to cast/project to the Microsoft Display Adapter. As the link states, I do get a "Catastrophic Error" but it does make the connection and keep it, anyway. What my code ended up looking like is below:
static async Task Main()
{
string prefix = "MicrosoftDisplayAdapter";
DeviceInformation displayAdapter = null;
try
{
//Get projection devices
DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(ProjectionManager.GetDeviceSelector());
foreach (DeviceInformation device in devices)
{
if (device.Name.StartsWith(prefix))
{
displayAdapter = device;
}
}
//Start projection. This throws an error but works without issue.
await ProjectionManager.StartProjectingAsync(0, 0, displayAdapter);
}
catch (Exception e)
{
//Ignore this error
if (e.Message.StartsWith("Catastrophic"))
{
//Change display to use secondary only
Process proc = new Process();
proc.StartInfo.UseShellExecute = true;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.FileName = #"C:\Windows\Sysnative\DisplaySwitch.exe";
proc.StartInfo.Arguments = "/external";
proc.Start();
proc.WaitForExit();
}
else
{
Console.WriteLine(e);
}
}
}

Related

Can Raspberry Pi running Win10 IoT uses both Wifi and Bluetooth communication at the same time?

I'm still a beginner to programming. I have met some problem of my problem, where the pi couldnt use the wifi and bluetooth at the same time. This is because initially the code without the bluetooth element, it works fine. But when i added the bluetooth code into the program, it just went weird. It couldnt retrieve any data from the Firebase through Wifi. Is it really that they couldnt work together at the same time or it is wrong with the code. Is it because of the socketstream something like this? Really thanks for the help.
Link to the code as it is too long.
I have tested with your code. The app will get an exception as "Access is denied. ", it will cause the app crash. So you need to add try catch in the function DeviceWatcher_Added to ensure the app won't dump when the Bluetooth could not connect.
private async void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
{
try
{
var device = await BluetoothDevice.FromIdAsync(args.Id);
var services = await device.GetRfcommServicesAsync();
if (services.Services.Count > 0)
{
var service = services.Services[0];
stream = new StreamSocket();
await stream.ConnectAsync(service.ConnectionHostName, service.ConnectionServiceName);
rx = new DataReader(stream.InputStream);
tx = new DataWriter(stream.OutputStream);
await this.Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.Normal,
() => { Device_9.IsEnabled = true; });
deviceWatcher.Stop();
}
}
catch(Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
BTW, you may refer to the sample mentioned in my first comment, it shows how to connect the RfcommService to communicate with Bluetooth. Please note that, in the sample the server creates the RfcommServiceProvider by guid, and the client connects the server with RfcommService from this guid as uuid.
var rfcommServices = await bluetoothDevice.GetRfcommServicesForIdAsync(
RfcommServiceId.FromUuid(Constants.RfcommChatServiceUuid), BluetoothCacheMode.Uncached);

Cannot read STDOut from Process that is running in background

So, under Linux I have to connect to a bluetooth device via the command rfcomm connect hci0 xx:xx:xx:xx:xx:xx, which starts a bluetooth connection, but has to remain running in order to stay connected.
I have to write everything as an .NET Core Program
Running the command outputs the following lines after a few seconds:
Connected /dev/rfcomm0 to xx:xx:xx:xx:xx:xx on channel 1
Press CTRL-C for hangup
From that Output I have to get the /dev/rfcomm0 part, so I can read it with a SerialPortReader, and if something goes wrong, like, let's say there is no more data incoming, I have to kill the process and start anew, until I have a good connection.
Now my logic is something like this:
while(!Terminate)
{
string port = Connect();
ReadData(port);
BTProcess.Kill();
}
Don't bother with the ReadData(port); function, as my program never even comes near that.
The Connect() looks something like this:
while (!Connected)
{
Console.WriteLine("Configuring Process");
BTProcess = new Process();
BTProcess.StartInfo.FileName = "rfcomm";
BTProcess.StartInfo.Arguments = "connect hci0 xx:xx:xx:xx:xx:xx"
BTProcess.StartInfo.RedirectStandardOutput = true;
BTProcess.StartInfo.UseShellExecute = false;
Console.WriteLine("Starting Process");
BTProcess.Start();
StreamReader reader = _BTProcess.StandardOutput;
bool done = false;
Console.WriteLine("Reading STDOUT now.");
while (!done) // EDIT: If I do the while with !reader.EndOfStream then it won't even enter into the loop
{
Console.Write("-");
int c = reader.Read(); // Program stops in this line
if(c != -1)
{
port += (char)c;
}
Console.Write(c);
if (c == 0)
{
port = "";
done = true;
_BTProcess.Kill();
}
if (/* String Contains Logic blabla */)
{
port = /* The /dev/rfcomm0 stuff */
Connected = true;
done = true;
}
}
reader.Close();
}
return port;
I did check already if the Output isn't redirected to like STDErr or something, but no, it is 100% written in STDOut.
I have already tried a logic with like an EventHandler that handles StandardOutput Events, and a logic where I read it asynchronously, but both with no success. All had the same problem, they all block at the Read(); function. My guess is that maybe the internal buffer doesn't get flushed correctly.
Maybe someone here knows an answer to my problem.
P.S.: I know my code isn't the best or most optimized, but it should nevertheless work, as I have tried it already with another blocking command under Windows and it worked.
Thanks in advance for every help I get.
I've solved the problem by simply not running the command directly, because that throws buffer problems, so I now don't run the command rfcomm connect hci0 xx:xx:xx:xx:xx:xx, instead I run stdbuf -o0 rfcomm connect hci0 xx:xx:xx:xx:xx:xx, to avoid buffering problems.

Windows UWP StreamSocket ReOpen

Hey, I have a Problem with the Windows 10 UWP API.
I'm developing a Windows 10 UWP App and need to connect to a Chromecast. I'm using SharpCaster for this. But when I open a connection to a Chromecast and close it again later on, it is not possible to connect to a Chromecast again. The socket to the Chromecast opens again, but when trying to write to it, I get the following exception:
A method was called at an unexpected time. (Exception from HRESULT: 0x8000000E)
This even happens when I turn the Chromecast off while disconnected. I disconnect the Chromecast with this Method:
public void Disconnect()
{
_running = false;
_socket.InputStream.Dispose();
_socket.OutputStream.Dispose();
_socket.Dispose();
}
The method is not found in the Library, I have written it myself. Setting _running to false stops all the loops for pinging, etc...
The socket is created with this code:
_socket = new StreamSocket().ConfigureForChromecast();
await _socket.ConnectAsync(new HostName(uri.Host), ChromecastPort, SocketProtectionLevel.Tls10);
The extension ConfigureForChromecast() looks like this:
public static StreamSocket ConfigureForChromecast(this StreamSocket socket)
{
//Chromecast is not using trusted certificate so ignoring errors caused by that
socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
socket.Control.OutboundBufferSizeInBytes = 2048;
socket.Control.KeepAlive = true;
socket.Control.QualityOfService = SocketQualityOfService.LowLatency;
return socket;
}
Finally, the messages are written to the socket with
internal async Task Write(byte[] bytes)
{
try
{
var buffer = CryptographicBuffer.CreateFromByteArray(bytes);
await _socket.OutputStream.WriteAsync(buffer);
}
catch (Exception e)
{
Debugger.Break();
}
}
And that is the point where the exception occurs. When connecting the first time, it works perfectly, but to connect a second time, I have to restart the whole app. Any ideas why?

C# Modbus/tcp - hanging connection

I have written Windows service, which perform Modbus WriteMultipleRegisters function call over TCP using NModbus library to 3-party devices every 10 minutes (ticks of System.Threading.Timer).
Occasionally this connection hang up open usually during network problems. As the device accepts only one Modbus connection at time and others are refused, connection during all next ticks fail with SocketException - ConnectionRefused.
But the device automatically closes connections which don't respond after short time. Something must keep connection open at my side even for two days. What's more when my Service is restarted, everything is fine again. So there is definitely some forgotten open connection. But I didn't manage to reproduce this bug in dev, so I don't where/when.. connection hang up. I only know that next connection is refused.
I do the modbus function call with this part of code:
using (TcpClient client = new TcpClient(device.ip, 502))
{
using (Modbus.Device.ModbusIpMaster master = Modbus.Device.ModbusIpMaster.CreateIp(client))
{
master.WriteMultipleRegisters(500, new ushort[] { 0xFF80 });
}
}
device.ip is string containing IP address of device - it's correct, confirmed from SocketException details.
As I'm using using statement dispose is called on both objects.
I have looked trough NModbus source code and everything is disposed correctly.
Any idea how its possible that with this code connection is not closed?
I agree with nemec. If you review the documentation for TcpClient.Dispose if does not specifically mention closing the connection. It frees managed and unmanaged resources by default, but it may not correctly tear down the connection.
Try changing your code to:
using (TcpClient client = new TcpClient(device.ip, 502))
{
try
{
using (Modbus.Device.ModbusIpMaster master = Modbus.Device.ModbusIpMaster.CreateIp(client))
{
master.WriteMultipleRegisters(500, new ushort[] { 0xFF80 });
}
}
catch(Exception e)
{
// Log exception
}
finally
{
client.Close();
}
}
That way you are doing a clean close before dispose and it should clean up even if the Modbus protocol throws some kind of exception.
did you play with TcpClient.LingerState Property
defualt setting could cause problems with resetting winsock
check it out
http://msdn.microsoft.com/pl-pl/library/system.net.sockets.tcpclient.lingerstate%28v=vs.110%29.aspx
This is not an answer, but a comment with code. We have this same issue on some of our installed computers, but not all of them. The issue itself is also very intermittent, sometimes going months without happening. I am hoping someone can find an answer. Here is our brute force destroy / reconnect code that does not work:
try
{
try
{
try
{
// Close the stream
var stream = _tcpClient.GetStream();
if (stream != null)
stream.Close();
}
catch { }
try
{
// Close the socket
if (_tcpClient.Client != null)
_tcpClient.Client.Close();
}
catch { }
// Close the client
_tcpClient.Close();
_tcpClient = null;
}
catch { }
if (_device != null)
{
_device.Dispose();
_device = null;
}
}
catch { }
System.Threading.Thread.Sleep(1000);

Apparent IO.Ports.SerialPort Flaw in C# or Possible Hardware Flaw

Please forgive me as this is going to be quite a long post. I'm currently using the SerialPort class in C# to write an application to communicate with a device called a Fluke 5500A. I've, in the past, had many problems as the amount of time the device takes to issue a command and return whatever it outputs in unpredictable at best. I asked a question yesterday here: System.Timers.Timer Usage The answer to the question is wonderful and most of the time appears to work perfectly. As an example my the class I use to connect to a SerialPort now looks like this:
public class SerialPortConnection
{
private SerialPort serialPort;
private string ping;
double failOut;
bool isReceiving;
public SerialPortConnection(string comPort = "Com1", int baud = 9600, System.IO.Ports.Parity parity = System.IO.Ports.Parity.None, int dataBits = 8, System.IO.Ports.StopBits stopBits = System.IO.Ports.StopBits.One, string ping = "*IDN?", double failOut = 2)
{
this.ping = ping;
this.failOut = failOut * 1000;
try
{
serialPort = new SerialPort(comPort, baud, parity, dataBits, stopBits);
serialPort.NewLine = ">";
serialPort.ReadTimeout = 1000;
}
catch (Exception e)
{
serialPort = null;
}
}
//Open Serial Connection. Returns False If Unable To Open.
public bool OpenSerialConnection()
{
//Opens Initial Connection:
try
{
serialPort.Open();
serialPort.Write("REMOTE\r");
}
catch (Exception e)
{
return false;
}
serialPort.Write(ping + "\r");
var testReceived = "";
try
{
testReceived += serialPort.ReadLine();
return true;
}
catch
{
return false;
}
}
public string WriteSerialConnection(string SerialCommand)
{
serialPort.Write(String.Format(SerialCommand + "\r"));
var received = "";
try
{
received += serialPort.ReadLine();
return received;
}
catch
{
received = "Error: No Data Received From Device";
return received;
}
}
public bool CloseSerialConnection()
{
try
{
serialPort.Write("LOCAL\r");
serialPort.Close();
return true;
}
catch (Exception e)
{
return false;
}
}
}
As you can see, when I open the a connection to, in this case, Com1 I test the connection by writing a command *IDN? to the SerialPort. The return for this command looks like so:
FLUKE,5500A,8030005,2.61+1.3+2.0+*
66>
In the class I've set ">" as the NewLine property so that SerialPort.ReadLine() doesn't finish till it finds that token. I've never once had the class itself throw an exception but I've noticed while debugging that sometimes testReceived won't catch that returned data properly, despite the fact that no exceptions are thrown and the code continues executing properly, and instead received will catch the returned string:
FLUKE,5500A,8030005,2.61+1.3+2.0+*
66>
whenever I pass my first command via SerialPort.Write(); Something important to know is that commands can be executed without that data being fully returned. My concern is that the initial ReadLine() appears to be skipping past that occasionally without catching the entire return. My thought is that there's an inherent flaw in the device I'm communicating with causing this but I'd prefer to be entirely sure before continuing.
My command order looks like so:
First I submit a command on startup:
REMOTE
This disables interaction with the device's manual interface and allows me to submit commands via the Serial Port.
Then I issue *IDN?, in this case, to check that the device is connected:
*IDN?
If nothing is return, the application is set to display an error in a message box and then FailFast. If all goes well a command can be submitted like so:
STBY
OUT 30MV,60HZ
OPER
The only command submitted here manually is OUT 30,MV,60HZ. STBY and OPER are set in the app.config as they only add an unnecessary step to the usage of the application. The STBY command puts the machine in standby for safety reasons. The OPER command puts it in operating mode and the device begins operating under the set parameters.
The application then waits for a technician to enter a result into a textbox and submit it. The content of these results aren't particularly pertinent but upon hitting the result button the machine is put back in standby:
STBY
Finally, two more commands are submitted when the application is closed:
*RST
LOCAL
First *RST resets the machine to ensure that it's in the same state as when it was powered on (I.E. It's not operating and no parameters are set). Then LOCAL sets the re-enables the manual interface for user interaction and disables access via the Serial Port till REMOTE is issued once more.
As you can see, a command is issued after *IDN? and before the first manual command that's sent (In this case we assume the command is OUT 30MV,60HZ). The problem is, sometimes I receive the output of *IDN whenever I check what the output of OUT 30MV,60HZ is yet I can see no problems within my code or the procedure I'm using to operate the machine. Is there any reason this could be happening?
As I've said, the error is extremely hard to reproduce (I've seen it twice in maybe forty runs). Even so, any error at all of this type is not acceptable in a production environment and the error needs to be fixed before I can begin testing my application in its entirety. I'll keep trying to reproduce the error so I can provide an example and hopefully provide further clarification as to what the problem might be.
EDIT:
I'd also like to clarify that I'm fairly certain the bug is not located somewhere within my application itself as the code is somewhat simplistic in nature:
public string SubmitCommand()
{
if (_command_Input != "No further commands to input.")
{
string received;
serialPort.WriteSerialConnection("STBY");
received = serialPort.WriteSerialConnection(_command_Input);
serialPort.WriteSerialConnection("OPER");
//Controls Enabled:
_input_IsEnabled = false;
_user_Input_IsEnabled = true;
_results_Input_IsEnabled = false;
RaisePropertyChanged("Input_IsEnabled");
RaisePropertyChanged("User_Input_IsEnabled");
RaisePropertyChanged("Results_Input_IsEnabled");
return received;
}
else
return "";
}
received is then manipulated like so:
public bool SetOutput()
{
string inter1 = SubmitCommand();
try
{
string[] lines = inter1.Split(Environment.NewLine.ToCharArray()).ToArray();
_results_Changed = lines[2];
RaisePropertyChanged("Results_Changed");
}
catch
{
_results_Changed = inter1;
RaisePropertyChanged("Results_Changed");
}
return true;
}
I can provide further code if need be but I can't currently see any other code that might be pertinent to the question at hand.
You made this hard to diagnose, the response you don't like looks exactly like the one you do like.
In general, you need to ensure that your program is in sync with the device. A possible failure mode is when the driver still has unread data in the receive buffer from a previous connection. Stale data could also exist in the device's transmit buffer. When you start back up, you'll read that stale data and assume it was a response to your command. It wasn't. You'll now be permanently out of sync, always reading stale data that was the response to the previous command.
It is also rather odd that this works without taking care of handshaking, device normally do pay attention to that.
To avoid accidents, initialize your program like this:
Call the Open() method to open the port
Set the RtsEnable and DtrEnable properties to true so that the device always sees a good signal that allows it to transmit data
Sleep for about 100 msec to allow the device to send any data that it still had buffered from the previous connection but could not send because the handshake was off
Call DiscardInBuffer() to throw away any stale response bytes.
You have now a reasonable guarantee you'll be in sync.

Categories

Resources