C# DLL doesn't work without MessageBox - c#

I have a somewhat weird problem. I have a couple of DLLs that I need to use in order to write and read with an NFC reader.
This works:
LV3_InitializeSystem(5);
setAuthCode();
MessageBox.Show(""); // I immediately click and close the box
short ret = LV3_CheckIssuer();
Console.WriteLine(ret); // 0 - Success
This doesn't work:
LV3_InitializeSystem(5);
setAuthCode();
short ret = LV3_CheckIssuer();
Console.WriteLine(ret); // 90 - Card reader can not be detected.
This also doesn't work:
LV3_InitializeSystem(5);
setAuthCode();
Thread.Sleep(5000);
short ret = LV3_CheckIssuer();
Console.WriteLine(ret); // 90 - Card reader can not be detected.
I have no idea what might be the problem. I tried using threads running the initialize part with no success. How does showing a MessageBox enable the initialization to complete but Thread.Sleep() doesn't?

The DLL is apparently posting some required messages on the Windows message queue. In order for the messages to be processed, the message queue must be emptied.
One way of ensuring these messages are processed is to use Application.DoEvents(). Generally Application.DoEvents() is frowned upon - see https://blog.codinghorror.com/is-doevents-evil/ for reasons why this is.
There are other ways to solve this without using Application.DoEvents(), but it would probably require restructuring your code - for example using async/await with a Task.Delay.

Related

ObjectDisposedException: Safe handle has been closed

So this is a rather small question with a big explanation. As is noted by the title I am getting an unhandled exception telling me my Safe handle has been closed. What I'll probably have to do is edit this post a few times with more and more code to help me diagnose what the problem is.
I'm using POS for .NET to make a Service Object for my RFID and MSR device. Although my devices are the same, I have 2 different Virtual COM Port chips that communicate to those devices. One by Silicon labs, the other by FTDI. I wanted to use the plug and play features with POS for .NET so I gave it both my Hardware ID's. Because it is plug and play I have the full hardware path available to me which I can then create a SafeFileHandle using a call to PInvoke and using that SafeFileHandle I create a FileStream. The FTDI chip doesn't let me talk to the devices directly like that so I have to get the friendly name of the device then use mutex to pull out the COM port then create a SerialPort instance. That step works fine and great. As a FYI I have tried to use the Friendly name of both chips to get the COM port and the Silicon Labs one (for some strange reason) doesn't get listed using SetupAPI.GetDeviceDetails using the Ports GUID. I'm not sure on that one since in Device Manager the Silicon labs Device Class Guid is the Ports GUID.
Well since both the SerialPort and the FileStream have a Stream object I decided to use that to read and write to that port. The problem with that is if I send a RFID command to the MSR device the MSR device doesn't respond back with anything. So if I use this code int fromReader = ReaderStream.ReadByte(); my thread is blocked. It's a blocking call and requires a minimum of 1 byte to proceed. So I looked around and it appears the only solution is to use a separate thread and set a timeout. If the timeout happens then abort the thread.
Thread t = new Thread(new ThreadStart(ReadFromStream));
t.Start();
if (!t.Join(timeout))
{
t.Abort();
}
(t.Abort has been surrounded with a try/catch to no avail, since it didn't fix the problem I removed it)
ReadFromStream is Abstract method in RFID Device. Here is one of the implementations
protected override void ReadFromStream()
{
var commandLength = USN3170Constants.MIN_RESPONSE_LENGTH;
var response = new System.Collections.Generic.List<byte>(USN3170Constants.MIN_RESPONSE_LENGTH);
for (int i = 0; i <= commandLength; i++)
{
int fromReader = ReaderStream.ReadByte();
if (fromReader == -1) break; //at end of stream
response.Add((byte)fromReader);
if (response.Count > USN3170Constants.DATA_LENGTH_INDEX && response[USN3170Constants.DATA_LENGTH_INDEX] > 0)
{
commandLength = response[USN3170Constants.DATA_LENGTH_INDEX] + 3;
}
}
streamBuffer = response.ToArray();
}
(int fromReader = ReaderStream.ReadByte(); was surrounded with a try/catch. Only thing it caught was the aborted thread exception, so I took it out)
The above code is where I suspect the problem lies. The strange thing is, though, is that I have a unit test which I feel mimics rather well the Microsoft Test App.
(FYI QUADPORT is the FTDI chipset)
PosExplorer posExplorer;
DeviceCollection smartCardRWs;
[Test]
public void TestQuadPortOpen()
{
posExplorer = new PosExplorer();
smartCardRWs = posExplorer.GetDevices(DeviceType.SmartCardRW, DeviceCompatibilities.CompatibilityLevel1);
//if using quadport one item is the MSR and the other is the RFID
//because of that one of them will fail. Currently the first Device in the collection is the the RFID, and the second is MSR
Assert.GreaterOrEqual(smartCardRWs.Count, 2);
//Hardware Id: QUADPORT\QUAD_SERIAL_INTERFACE
foreach(DeviceInfo item in smartCardRWs)
{
Assert.AreEqual("QUADPORT\\QUAD_SERIAL_INTERFACE", item.HardwareId);
}
SmartCardRW rfidDevice = (SmartCardRW)posExplorer.CreateInstance(smartCardRWs[0]);
SmartCardRW msrDevice = (SmartCardRW)posExplorer.CreateInstance(smartCardRWs[1]);
rfidDevice.Open();
Assert.AreNotEqual(ControlState.Closed, rfidDevice.State);
rfidDevice.Close();
try
{
msrDevice.Open();
Assert.Fail("MSR Device is not a RFID Device");
}
catch
{
Assert.AreEqual(ControlState.Closed, msrDevice.State);
}
rfidDevice = null;
msrDevice = null;
}
When I run that test I do not get the SafeFileHandle exception. In fact the test passes.
So I am at a loss as to how to track down this bug. Since I'll be using this Service Object in a different program that I am also creating I'll probably end up using this code from this test in that program. However I feel that the Microsoft Test App is more or less the "Golden Standard". Is it really... probably not. But it does work good for my purposes, SO I feel it is a problem with my code and not theirs.
Any tricks on how I can narrow this down? FYI I've tried using the debugger but walking the Open Code the error does not occur. I also walked the Update Status Timer and it also does not throw the error. Once I hit continue then I'll get the exception. I turned of Just My Code and Loaded Symbols and it tells me "Source Information is missing from teh debug information for this module"
This problem (and in particular the reference to a SerialPort instance) sounds suspiciously like the problem documented at http://connect.microsoft.com/VisualStudio/feedback/details/140018/serialport-crashes-after-disconnect-of-usb-com-port.
As I understand it, in the case of a non-permanent SerialPort (like one associated with a USB device, for example) when the port "goes away" unexpectedly the underlying Stream associated with it gets disposed. If there is an active read or write operation on the port at the time a subsequent call to SerialPort.Close can lead to the exception you mention, however the exception is occurring in Microsoft's code running on a different thread and cannot be caught from within your code. (It will still be seen by any "last chance" exception handler you have bound to the UnhandledException event on the AppDomain.)
There seem to be two basic workaround styles in the linked document. In both instances, after opening the port you store a reference to the BaseStream instance for the open port. One workaround then suppresses garbage collection on that base stream. The other explicitly calls Close on the base stream, capturing any exceptions thrown during that operation, before calling Close on the SerialPort.
EDIT: For what it's worth, under the .NET framework V4.5, it appears that none of the documented workarounds on the Microsoft Connect site fully resolve the problem although they may be reducing the frequency with which it occurs. :-(
I had the same error when I used a thread to read from a SerialPort. Calling Interrupt on the thread occasionally caused the uncatchable ObjectDisposedException. After hours of debugging and carefully reading this:
https://blogs.msdn.microsoft.com/bclteam/2006/10/10/top-5-serialport-tips-kim-hamilton/
I realized that the problem is just this:
NET 2.0 (and above) isn’t letting you get away with some things, such as attempting to cancel a SerialPort read by interrupting the thread accessing the SerialPort.
So before you call Thread.Interrupt() you have to close the COM... This will cause a catchable exception on the ReadByte operation.
Or you may use the ReadTimeout property on the SerialPort to avoid using a thread just to have a timeout.
I would like to post my case in which I had a similar issue trying to read from a serial port (virtual com driven by a Moxa RS232 to ethernet).
Since I did have no chance to catch the ObjectDisposedException, the only solution was to increase the ReadTimeout property which was originally set to -1 (continuous reading).
Setting the ReadTimeout to 100 millis solved this issue in my case.
EDIT
It is not the definitive solution: it can happen that if you close the application during a read attempt you can get the same uncatchable exception.
My final solution is to kill the process of the application directly in the FormClosing event :
private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
Process p = Process.GetCurrentProcess();
p.Kill();
}
Please take a look at this:
https://github.com/jcurl/SerialPortStream
I replaced System.IO.Ports with RJPC.IO.Ports, fixed up a couple parameter differences in the initialization, and all the problems went away with this issue.

Reading StandardInput stops code execution without breaking application

Im using Stockfish game engine to power Human Vs Computer games.
Here is first part of the code:
Process _proc= new Process();
_proc.StartInfo = new ProcessStartInfo(path);
_proc.StartInfo.RedirectStandardInput = true;
_proc.StartInfo.RedirectStandardOutput = true;
_proc.StartInfo.UseShellExecute = false;
_proc.StartInfo.CreateNoWindow = true;
_proc.Start();
_proc.StandardInput.WriteLine("uci");
_proc.StandardInput.WriteLine("ucinewgame");
At this point everything is ok, but when I try to read StandardOutput something weird happens.
string result = _proc.StandardOutput.ReadToEnd();
Stockfish.exe program pops-up my application is running but code after that line is not executing. When I press pause, it points at this line:
If I use:
while (!_proc.StandardOutput.EndOfStream)
{
result += _proc.StandardOutput.ReadLine();
}
Same thing happens only at while statement. result has its full value there, all the text is written into it.
Is there any way to overcome this without async reading?
Side problem:
Since this is all part of singleton class that is used over whole ASP.NET application, i dont feel like using async reading since Im not sure how can I protect (with locking) multiple threads writing into it. Also, I dont know how to stop current thread since the processing of command can last up to 10 sec.
I don't feel like using Thread.Sleep() to constantly check for end of reading output, not elegant.
Considering side problem, how could i avoid multithread problems if async is only solution?
My threading knowledge is weak, so please have that in mind when giving thread related answers. Thank you.
The call to StandardOutput.ReadToEnd will block until this process ends. Is the goal here to read, process, and respond to various text commands from the process you spawn as you receive them?
You must approach this via asynchronous reading.
For example, you could setup a listener to Process.OutputDataReceived. Then call Process.BeginOutputReadLine to start reading. Your code will continue execution. Meanwhile, the .NET Framework will handle incoming text messages on a separate thread.

C# "using" SerialPort transmit with data loss

I'm new to this forum, and I have a question that has been bothering me for a while.
My setup is a serial enabled character display connected to my pc with a usb/uart converter. I'm transmitting bytes to the display via the serialPort class in a separate write buffer thread in a C++ style:
private void transmitThread(){
while(threadAlive){
if(q.Count > 0){ // Queue not empty
byte[] b = q.Dequeue();
s.Write(b,0,b.Length);
System.Threading.Thread.Sleep(100);
}
else{ // Queue empty
System.Threading.Thread.Sleep(10);
}
}
}
Assuming the serial port is already opened, this works perfectly and transmits all the data to the display. There are though no exception handling at all in this snippet. Therefore I was looking into implementing a typical C# feature, the 'using' statement and only opening the port when needed, like so:
private void transmitThread(){
while(threadAlive){
if(q.Count > 0){ // Queue not empty
byte[] b = q.Dequeue();
using(s){ //using the serialPort
s.Open();
s.Write(b,0,b.Length);
s.Close();
}
System.Threading.Thread.Sleep(100);
}
else{ // Queue empty
System.Threading.Thread.Sleep(10);
}
}
}
The problem with this function is, that it only transmits a random amount of the data, typically about one third of the byte-array of 80 bytes. I have tried different priority settings of the thread, but nothing changes.
Am I missing something important, or do I simply close the port too fast after a transmit request?
I hope you can help me. Thanks :)
No, that was a Really Bad Idea. The things that go wrong, roughly in the order you'll encounter them:
the serial port driver discards any bytes left in the transmit buffer that were not yet transmitted when you close the port. Which is what you are seeing now.
the MSDN article for SerialPort.Close() warns that you must "wait a while" before opening the port again. There's an internal worker thread that needs to shut down. The amount of time you have to wait is not specified and is variable, depending on machine load.
closing a port allows another program to grab the port and open it. Serial ports cannot be shared, your program will fail when you try to open it again.
Serial ports were simply not designed to be opened and closed on-the-fly. Only open it at the start of your program, close it when it ends. Not calling Close() at all is quite acceptable and avoids a deadlock scenario.
I think you're missing the point of the using block. A typical using block will look like this:
using (var resource = new SomeResource())
{
resource.DoSomething();
}
The opening happens at the very beginning. Typically as part of the constructor. But sometimes on the first line of the using block.
But the big red flag I see is that the closing happens automatically. You don't need the .Close() call.
If the successful operation of your serial device is dependent on the calls to Thread.Sleep then perhaps the thread is being interrupted at some point, sufficient to make the data transmission out of sync with the device. There would most likely be ways to solve this but the first thing I would do is try to use the .NET SerialPort class instead. The Write method is very similar to what you want to do, and there are C++ code examples in those articles.

App.Current.Shutdown not letting DataSet.WriteXml complete results in corrupt config file

Environment - C#, .NET 4.0, WPF, VS2010
I have an app that uses a keyboard hook to detect when a combination of four keys is pressed. When this occurs it calls Configuration.Save(), which has a call to myConfigDataSet.WriteXml(myConfigFile). And then on the next line it calls App.Current.Shutdown().
About half the time it works as expected. But many times it would insert XML content right into the middle of a previously existing configuration file, resulting in corrupt data.
I was able to fix the above issue by using...
if(File.Exists(myConfigFile)) { File.Delete(myConfigFile) }
...on the line just above the call to myConfigDataSet.WriteXml(myConfigFile)
But now many times it just writes a 0KB size file. I am pretty sure that all of my problems are being caused by App.Current.Shutdown() not waiting for the call to myConfigDataSet.WriteXml(myConfigFile) to finish.
Shouldn't this call block execution until the file has been written to disk? ...apparently not!!!
As a workaround I've already tried inserting Thread.Sleep(1000) to create a 1 second delay just before App.Current.Shutdown. But now sometimes the app errors out with a "StackOverFlow" exception...!!!
What would you guys recommend as a fix or workaround for this? What am I doing wrong?
You can't stop a App.Current.Shutdown
Instead, use Application.Current.MainWindow.Close().
In this case, you can intercept in the Close event, process what you need to process, and then you could call App.Current.Shutdown
You can try to put the call to myConfigDataSet.WriteXml(myConfigFile) in a try/finally block. The finally block is executed completely even when the thread is aborted (see here). Not sure if it works with App.Current.Shutdown though.
So instead of:
myConfigDataSet.WriteXml(myConfigFile)
Do the following:
try {
// Empty...
} finally {
myConfigDataSet.WriteXml(myConfigFile)
}

Fastest way to send keystrokes C#

I was wondering what the fastest way to send keystrokes using C# is. Currently I am using SendKeys.Send() and SendKeys.SendWait() with SendKeys.Flush().
I am using the following code to calculate the time of how long it takes for the both of them to work:
Stopwatch sw1 = new Stopwatch();
sw1.Start();
for (int a = 1; a <= 1000; a++)
{
SendKeys.Send("a");
SendKeys.Send("{ENTER}");
}
sw1.Stop();
And:
Stopwatch sw2 = new Stopwatch();
sw2.Start();
for (int b = 1; b <= 1000; b++)
{
SendKeys.SendWait("b");
SendKeys.SendWait("{ENTER}");
SendKeys.Flush();
}
sw2.Stop();
The results of the 2 are:
Result 1: 40119 milliseconds
Result 2: 41882 milliseconds
Now if we put the SendKeys.Flush() on the second test, outside of the loop we get:
Result 3: 46278 milliseconds
I was wondering why these changes in the code make the speed very different.
I was also wondering if there is a faster way of sending many keystrokes, as my application does it a lot. (These tests were done on a really slow netbook)
Thanks!
SendWait() is slower because it waits that the message has been processed by the target application. The Send() function instead doesn't wait and returns as soon as possible. If the application is somehow busy the difference can be even much more evident.
If you call Flush() you'll stop your application to process all events related to the keyboard that are queued in the message queue. It doesn't make too much sense if you sent them using SendWait() and you'll slow down a lot the application because it's inside the loop (imagine Flush() as a selective DoEvents() - yes with all its drawbacks - and it's called by SendWait() itself too).
If you're interested about its performance (but they'll always be limited to the speed at which your application can process the messages) please read this on MSDN. In sum, you can change the SendKeys class to use the SendInput function, rather than a journal hook. As quick reference, simply add this setting to your app.config file:
<appSettings>
<add key="SendKeys" value="SendInput"/>
</appSettings>
Anyway, the goal of the new implementation isn't the speed but consistent behavior across different versions of Windows and and options (the increased performance is kind of a side effect, I guess).
If you have a lot of text to push to a client, you may notice that SendKeys is really sluggish. You can vastly speed things up by using the clipboard. The idea is to put the text you wish to "type" into a target text box in the clipboard and then send a CTRL-V to the target application to paste that text. Here's an illustration:
Clipboard.Clear(); // Always clear the clipboard first
Clipboard.SetText(TextToSend);
SendKeys.SendWait("^v"); // Paste
I found this worked well for me with a cordless bar code scanner that talks via WiFi to a host app that sends long bar codes to a web app running in Google Chrome. It went from tediously pecking out 30 digits over about 4 seconds to instantly pasting all in under a second.
One obvious downside is that this can mess with your user's use of the clipboard. Another is that it doesn't help if you intend to send control codes like TAB or F5 instead of just plain old text.

Categories