I'm working in Visual Studio C#, and I opened up a serial port, but I didn't properly close it. Now I cannot run my program to try to close it. I know it was me that was using it, but somehow I've lost control of it..? Is there a way to close it otherwise?
I've tried exiting out of visual studio and it still says that my access is denied. I've unplugged and replugged in the actual object I'm using. My next step is to restart the computer, but I don't want to have to do that everytime I mess up (which is frequently!)
On a side-note, I'm working in a lab and do not have administrative access on this computer. Another note is that the error's text is "Access to the port 'COM1' is denied."
In response to those asking for code,.. comPort.Open(); What else are you looking for?
private void updateAccuSwayData() {
Console.WriteLine("Update thread started...");
comPort.Open();
comPort.WriteLine("Q");
Thread.Sleep(5);
while (!cancelRequested) {
//do stuff...
}
Console.WriteLine("Update thread halted.");
comPort.WriteLine("R");
comPort.Close();
}
In a nutshell, I ended my debugging session while it was in middle of something it seems. That's about all I know.
You'll likely need to reboot to clear this up, although one approach would be to use Process Explorer and search for a handle to \Device\Serial0. You can then see if closing this handle works, it may not however.
To work to keep this from happening in the future, you need to put the comPort.Close() call in a finally-block:
try
{
comPort.Open();
// ...
}
finally
{
// Almost always ensures the COM port will be cleaned up,
// however, the MSDN remarks state that the port may not
// be closed immediately.
comPort.Close();
}
Related
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.
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.
I have a backup power supply for my computer which is attached inline with it and the wall. When I pull the power cord from the wall, I have 2-5 minutes before the backup supply shuts down the computer. It is during this time that I want to write data to a file with the code below:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason.Equals(CloseReason.WindowsShutDown))
{
writeContents("Interrupted");
sendMessage("PWR - The Spring Test Machine has stopped");
return;
}
if (e.CloseReason.Equals(CloseReason.UserClosing))
{
if (MessageBox.Show("You are closing this application.\n\nAre you sure you wish to exit ?", "Warning: Not Submitted", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Stop) == DialogResult.Yes)
{
writeContents("Interrupted");
return;
}
else
e.Cancel = true;
}
}
The problem is that it didn't work. I don't think the the closing event ever got called. Any ideas would greatly be appreciated. Thank you.
From here http://www.daniweb.com/software-development/csharp/threads/253249/application-exit-does-not-trigger-the-formclosing
when you use taskmanager to "kill" the appliction, it doesn't fire any
events, It simply stops the execution, This is how you close an
application that has frozen. if you waited for it to handle any
events, then it would still be frozen.
as for when you restart the computer or shutdown, the event will be
called only if there is enough time, they system tells all
applications it is shutting down and only gives them a short amount of
time to handle business before it kills them. Windows 7 will show a
dialog telling you which applications are still busy and ask you if
you want to kill them and shutdown, or cancel. But as for XP, it just
kills them after X amount of seconds.
That's pretty much how I would have imagined the behavior of FormClosing... Would Application.ApplicationExit Event be a better event to listen for?
Here is some usful info about Properties of FormClosing event:
Bug in FormClosingEventArgs.CloseReason?
And you can try using switch statement, like here:
Detect reason for form closing
Not sure if it works cuase i need to check it first and im not infront of my machine now .. but have you also tried the other elements of the CloseReason enum ?
try TaskManagerClosing .
In any case try first to throw a message( messagebox ) to see if you actually have the correct CloseReason you want and also don't forget to use the e.Cancel = true if you dont want the pc to close everytime you check it .
After that check if the method you have for writting to the file is ok .
maybe this will help also
Prompt user to save when closing app
After some poking around on how to reset my computer and or shut it down from C# I found this explanation on how to do that:
ManagementBaseObject outParameters = null;
ManagementClass sysOS = new ManagementClass("Win32_OperatingSystem");
sysOS.Get();
// Enables required security privilege.
sysOS.Scope.Options.EnablePrivileges = true;
// Get our in parameters
ManagementBaseObject inParameters = sysOS.GetMethodParameters("Win32Shutdown");
// Pass the flag of 0 = System Shutdown
inParameters["Flags"] = "1"; //shut down.
inParameters["Reserved"] = "0";
foreach (ManagementObject manObj in sysOS.GetInstances())
{
outParameters = manObj.InvokeMethod("Win32Shutdown", inParameters, null);
}
This worked in Windows 7, but not on the Windows XP box I tried it on. So I figured well lets go with a simpler solution:
Process.Start("shutdown", "/s /t 00");
Alas that as well seems to work on my windows 7 box, but not my Windows XP box. I have only tried it on one Windows XP machine, but it flashes up like a command prompt, my program that is up is minimized to the system tray and then nothing happens..so its like it wants to do something but ultimately nothing happens. (I do have code that purposely puts my program to the sys tray when the close X is hit, and the user has to purposely exit it... ) is there an issue with that? My FormClosing code is this:
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (!canExit)
{
e.Cancel = true;
this.WindowState = FormWindowState.Minimized;
}
else
{
// Write out the logs.
List<String> logs = LogUtil.getLog(); // mic.getLog();
// Create a writer and open the file
TextWriter tw = new StreamWriter(userAppData + "\\logTMC.txt", true);
// Write a line of text to the file
tw.WriteLine("----- " + DateTime.Now + " ------");
foreach (String log in logs)
{
tw.WriteLine(log);
}
// Close the stream
tw.Close();
}
}
I am not sure why I can reset, and shutdown my pc from C# in Windows 7, but not on Windows XP...maybe I missed something? An extra command? A better way to close out the log file I have open when the form closes? Some way to force a shutdown or reset no matter what, the Windows XP box I am using does indeed have an SVN server as a windows service running, but I am not sure if this makes a difference or not.
So I am not really sure where to investigate my problem. Does the Process.Start() have a way to see a return or a try catch to see what might of caused it not to shut down or is it a "fire and forget" type a deal?
You could use the ExitWindowsEx API via pinvoke.net.
See the ExitWindowsEx, ExitWindows-Enum and ShutdownReason-Enum on pinvoke.net for more information. Note that your process must have the SE_SHUTDOWN_NAME priviledge aquired (for example via AdjustTokenPrivileges API).
The answers to this stackoverflow question contain some "complete" examples (although most of them are missing errorchecking and resource cleanup - the latter might not matter when you successfully shutdown, YMMV).
Finally, note that using Process.Start() as you showed, without a fully qualified name to shutdown.exe is also problematic from a security standpoint. Someone could put a malicious EXE named shutdown in your PATH. Since you probably need to run with admin rights to be able to execute the "real" shutdown.exe, this can cause some trouble. If you specify something like Process.Start(Environment.ExpandEnvironmentVariables("%windir%\system32\shutdown.exe")) you can at least assume that the real shutdown.exe is protected from malicious replacement by file system rights (if the attacker himself is an admin your basically busted anyway).
I can't add comments yet, so have to post it as an answer.
There is an article on this site, showing several methods on shutting down the PC here: How to shut down the computer from C#
At a glance I noticed in the above link, for XP, Pop Catalin uses Process.Start("shutdown","/s /t 0");. I'm not sure if using 1 0 is going to make any difference.
I believe it's correct. You just have to change the command to:
shutdown.exe -s -t 00
It works on my Windows box (from cmd).
I found an ftp client class in c# over a year ago and have been using it in a process that uploads files on a nightly basis. A few days ago we started having a problem where it would time out. I'm not well versed in this so I'm not sure why it's doing this.
When the program starts uploading a file it checks to see if it's logged in and if not, it calls the login method. In that method is this block of code.
if (this.resultCode != 230)
{
this.sendCommand("PASS " + password);
if (!(this.resultCode == 230 || this.resultCode == 202))
{
this.cleanup();
throw new FtpException(this.result.Substring(4));
}
}
On the line that says this.sendCommand("PASS"... it goes into this code.
private void sendCommand(String command)
{
if (this.verboseDebugging) Debug.WriteLine(command, "FtpClient");
Byte[] cmdBytes = Encoding.ASCII.GetBytes((command + "\r\n").ToCharArray());
clientSocket.Send(cmdBytes, cmdBytes.Length, 0);
this.readResponse();
}
If I let the program run, it times out. However if I step through it into the sendCommand method it executes fine. Does anyone know why it would work fine when I step through it? Nothing on our end has changed and I've been told nothing on the client's end has changed so I'm stumped. Thanks.
Let it run in debug mode and when it freezes hit pause so you can see exactly what line it's hung up on.
If it starts the transfer - it'll not need to login again, unless the connection interrupts and your client tries to reconnect which will result in relogin.
I strongly suggest into looking if the client supports "NOOP" command (used to keep the control connection alive while the data is transferred over data connection). That's the most common problem with FTP implementations.