How to use override WndProc messages to detect usb attach/detach - c#

I'm using this(link) library to detect attach and detach events of USB devices. After detecting the right device attached(identified with specific VID/PID combination) I open a serial port connection and similarly when the device is detached I close the serial port connection.
My attach event works great and at the end I get a serial port that I can use but I'm having problems inside the detach event. The detach event fires correctly but when code execution reaches closeCOM(serialPort1) point it jumps to wndProc override loop and prevents execution of closeCOM() and whatever follows.
The library needs WndProc messages to detect the events and my code is implemented like this:
//Catch Windows messages and pass them to the USBClass class
protected override void WndProc(ref Message m)
{
USBPort.ProcessWindowsMessage(ref m);
base.WndProc(ref m);
}
Then I have a detach event which executes the following code:
if (!USBClass.GetUSBDevice(VID, PID, ref USBDeviceProperties, false) && USBDeviceConnected)
{
//Device is removed
USBDeviceConnected = false;
//Close COM port just in case we forgot to disconnect
closeCOM(serialPort1);
//update status strip
strip_device_status.Text = "Disconnected";
}
and here is the closeCOM function:
//This function handles COM port closing.
private void closeCOM(SerialPort port)
{
// If a serial port is open, disconnect it
if (port.IsOpen)
{
// close the serial port
port.Close();
}
//update com port status flag
COMConnected = false;
//update status strip
strip_COM_status.Text = "Disconnected";
}
It is closeCOM() in particular that's causing this "conflict" because if I comment out that line everything works, except I'm left with an open serial port possibly causing errors later on. What am I doing wrong that's causing the code to jump to WndProc override instead of normal execution? I would like to be able to do the port closing in the detach event.

Related

How to check if a Serial port is disconnected in c#

I want to check if a Serial port is disconnected or not after clicking a button in C# WinForms.
Eg:
private void btn_Click()
{
if("code to check device disconnected")
{
Do this;
}
else
{
Do this;
}}
PS: Is there any way to check that the device is disconnected when the application is running.
SerialPinchanged, ErrorRecieved, DataRecieved don't help.
Thank you in advance
It depends on the specifications of the target device connected to the COM port.
For example, if RTS/CTS or DTR/DSR are cross-connected, or if the device equivalent to a modem has a DCD or RI valid signal line, and the CTS/DSR/DCD/RI signal line shows valid connection information. , There may be a case where there is a command/response specification for health check or keep alive.
As an alternative, if the COM port is a USB Serial converter, you can check whether or not the device with the corresponding VID and PID exists, but make sure that the device is actually connected at the end of the converter. There is no guarantee.
It is simple logic that whenever SerialPort is disconnected, serialPort.IsOpen turns to false.
private void btn_Click()
{
if(!SerialPort.IsOpen)//If SerialPort is not open
{
Do this;
}
else//Else if SerialPort is open
{
Do this;
}
}

UWP maintaining barcode scanner D75e - problem

I initialazed DeviceWatcher ... works fine, I add Honeywell Ring Scanner it raises event deviceWatcher. When I remove Honeywell USB Ring Scanner it raises event DeviceWatcher_Removed where I null ClaimedBarcodeScanner and BarcodeScanner object and DeviceWatcher_Updated where return status was STOP
After I connect Ring Scanner nothing happened in App. If I restart the app it's work until I disconnect and connect Ring Scanner.
I need to release BrcodeScanner from app.
I try on Honeywell D75e Win 10 iot and Honeywell Ring Scanner 8620903
I also try free memory ...
GC.Collect();
GC.WaitForPendingFinalizers();
I try to do Dispose of ClaimedBarcodeScanner
When you disconnect the device, it will raise the device removed event, but all pending operations need to be canceled properly, and all of the resources need to clean up. Please refer to following code in EventHandlerForDevice. The callback in the code is used to close the device explicitly is to clean up resources, to properly handle errors,and stop talking to the disconnected device.
private async void CloseCurrentlyConnectedDevice()
{
if (device != null)
{
// Notify callback that we're about to close the device
if (deviceCloseCallback != null)
{
deviceCloseCallback(this, deviceInformation);
}
// This closes the handle to the device
device.Dispose();
device = null;
}
}

how to detect whether a device is connected to serial port or not in c#

I've developed a simple windows form application in c# which is used to send and receive data using serial ports. but when I click my READ button while there is no device connected, the whole application stops working an I have to close it with force! so I need a method to recognize whether a device is connected or not before I click on READ button. please help me get through it.
private void button2_Click(object sender, EventArgs e)
{
try
{
textBox2.Text = serialPort1.ReadLine();
}
catch (TimeoutException)
{
textBox2.Text = "Timeout Exception";
}
}
In this case I found my way out of it! I just Changed ReadLine to ReadExisting in try block and application didn't stop working even with no device connected! But still no way to find whether a device is connected!

WM_INPUT messages blocked by Device Manager

I have an application which monitors touchscreen messages in a Windows tablet. I want to wake up some hardware when the user touches the touchscreen. I have used the approach from Using Raw Input from C# to handle multiple keyboards.
I call RegisterRawInputDevices() to register to receive touchscreen messages:
var rid = new RawInputDevice[1];
rid[0].UsagePage = 13; // HidUsagePage.Digitizer
rid[0].Usage = 4; // HidUsage.TouchScreen
rid[0].Flags = 0x00000100; // RawInputDeviceFlags.InputSink
rid[0].Target = this.Handle;
if (!RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0])))
{
// report error
}
I then receive WM_INPUT messages in my message pump:
protected override void WndProc(ref Message message)
{
switch (message.Msg)
{
case WmInput:
// handle touch messages
break;
}
base.WndProc(ref message);
}
This works fine most of the time. I can touch anywhere on the screen and my application gets a WM_INPUT message. But if I run Windows Device Manager, I do not get touch messages when I touch inside the Device Manager.
I have tested this with the Microsoft Digiinfo tool, and it has the same behaviour.
I also see the same behaviour with the Computer Management application.
Is there a class of applications that can block WM_INPUT messages? Is there some way around this problem? I may just have to accept this behaviour, but I would still like to understand it.

C# waiting for the data on serial port

i am trying to get data from fingerprint scanner through c# application, but before the fingerprint can send, a my whole code executes.
I tried using delay function and System.Threading.Thread.Sleep(1000), so it can get data before the next step executes, but it all seems futile.
Could any one please provide any other option?
I am using "SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)" to get data.
This code works perfectly for me:
port = new SerialPort(port, 9600, Parity.None, 8, StopBits.One);
port.Open();
port.DiscardOutBuffer();
port.DiscardInBuffer();
port.DataReceived += OnScan;
void OnScan(object sender, SerialDataReceivedEventArgs args)
{
SerialPort port = sender as SerialPort;
string line = port.ReadExisting();
// etc
}
Unfortunately waiting for a serial port data in C# is tricky, there is nothing like poll().
There is SerialPort.DataReceived which takes functions to be called on incoming data. So you assign there a function to trigger an arbitrary event. Your another function — the one to actually wait — should wait for this event.
Below is a simple example, it is commented, but in short: the TestFunc initializes and opens a serial port (in particular assigns the DataReceived). The Proxy() is a function that will be called every time a data arrived, it triggers an event. And WaitForAData() indeed waits for the event that will be triggered by Proxy() when a data appears. Note the lock(){}s, without them surrounding Monitor's functions it won't work properly.
It's just an example, you would probably want to remake WaitForAData() function to trigger an exception in case of timeout. And to add a boolean variable in case if the Proxy() was triggered before you began waiting, then serial port already have data. But I tested it (cause I need such a function now ☺), and it works.
namespace MyNamespace
{
class MySerial
{
///A condition variable that signals when serial has a data
private System.Object SerialIncoming;
public MySerial()
{
SerialIncoming = new Object();
}
/**
* A proxy function that will be called every time a data arrived
*/
private void Proxy(Object unused1, SerialDataReceivedEventArgs unused2)
{
Console.WriteLine("Data arrived!");
lock (SerialIncoming)
{
Monitor.Pulse(SerialIncoming);
}
}
/**
* Waits for a data for the time interval Timeout
* \param Timeout a timeout in milliseconds to wait for a data
* \returns true in if a data did arrived, and false else
*/
public bool WaitForAData(int Timeout)
{
lock (SerialIncoming)//waits N seconds for a condition variable
{
if (!Monitor.Wait(SerialIncoming, Timeout))
{//if timeout
Console.WriteLine("Time out");
return false;
}
return true;
}
}
/* Just a test function: opens a serial with speed, and waits
* for a data for the «Timeout» milliseconds.
*/
public void TestFunc(string serial, int speed, int Timeout)
{
SerialPort ser = new SerialPort(serial);
ser.BaudRate = speed;
ser.DataReceived += Proxy;
ser.Open();
if (WaitForAData(Timeout))
Console.WriteLine("Okay in TestFunc");
else
Console.WriteLine("Time out in TestFunc");
}
}
}
UPDATE: the problem wasted ½ of my day, so I hope I will save someone's time: the code above won't work in mono (but works in MS implementation) because serial port events are not supported as of writing these words.
If this is a Console application, you can use things like Console.ReadLine() etc. after calling the appropriate function of the COM Port component to start listening asynchronously. If this is a WinForms application. The message loop will of course keep showing your current form. In that case you can call asynchronous listening function in the Form_Load event or behind a button click.
The key point here is that you should call the asynchronous version of the listener function. There is no need to use delays or timers in that case.
Why not make a global marker (bool), that marks if you received anything and make a while(!marker) {} loop and you change the marker in the SerialPort_datareceived subrutine?
The thread.sleep might make you miss the SerialPort data sending?
The serial port is working in a separate thread. Therefore the serialPort_DataReceived event is fired from this thread.
So if your program only starts the serial port and then your main exits, you never receive the event. This is true if you have a console application.
When using a forms application, it keeps the form and the main thread alive until the user closes it.

Categories

Resources