none
Problem accessing serial port after migrating from 1.1 to 3.5 RRS feed

  • Question

  • Greetings,

    I have a desktop application that was written in 2003 with .NET 1.1. One of the functions of the application is to control a traffic light connected to Serial port COM1 (Plain old 9-Pin RS-232 serial port). 

    The class that performs the function is very simple (see code below). Basically the light is always green by default. When I open the serial port (using Win32 CreateFile) the light goes red, when I close it, the light goes green again.

    Recently, I migrated the application to .NET 3.5. Everything else in the application works smoothly, except this functionality. The same PC (running WinXP) and having the .NET 1.1 installed, works perfectly and the traffic light goes green and red without problems as it has always done for the past 10 years. The .NET 3.5 version running on same xp machine and same Windows user, does nothing. No exception is thrown.

    The 3.5 version is built targeting x86 platform since both versions use an old 32-bit unmanaged dll written in C++ which can't run as 64-bit.

    The code below (code unrelated to the problem was removed for clarity).

    using System;
    using System.ComponentModel; using System.Runtime.InteropServices; public enum LightStatus { Red, Green } public class TrafficLightIO { [DllImport("Kernel32.dll")] private static extern IntPtr CreateFile(string filename, uint access, uint share, IntPtr sec, uint disp, uint flags, IntPtr template); [DllImport("Kernel32.dll")] public static extern bool CloseHandle(IntPtr handle); const uint GENERIC_WRITE = 0x40000000U; const uint OPEN_EXISTING = 0x00000003U; static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); private static IntPtr lightPort = IntPtr.Zero; private static readonly object lightPortLock = new object(); public static LightStatus LightStatus { get { lock (lightPortLock) { return lightPort == IntPtr.Zero || lightPort == INVALID_HANDLE_VALUE ? LightStatus.Green : LightStatus.Red; } } set { lock (lightPortLock) { if (LightStatus == value) return; if (value == LightStatus.Red) { lightPort = CreateFile("COM1", GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); if (lightPort == INVALID_HANDLE_VALUE || lightPort == IntPtr.Zero) { int lastError = Marshal.GetLastWin32Error(); throw new Win32Exception(lastError); } } else { if (!CloseHandle(lightPort)) { int lastError = Marshal.GetLastWin32Error(); throw new Win32Exception(lastError); } lightPort = IntPtr.Zero; } } } } }

    Thanks a lot in advance,

    Best regards,

    Sherif


    http://sherifelmetainy.blogspot.com/


    Tuesday, October 15, 2013 4:19 PM

Answers

  • I don't see anything particularly wrong with your code.  I do see places where your code isn't exception safe so if an exception occurred you might get into a state where you wouldn't recover.  Have you tried stepping through the code and verifying it is executing in the manner you expected?  You might also consider getting the last Win32 error if it truly didn't open the port.  Also note that SetLastError defaults to false for DllImport so you might consider setting it to true to ensure you are getting the correct info back.  I'm not aware of any changes in this area but I would say the original v1 code wasn't setting it properly either.

    An alternative is to switch to the SerialPort type that was added post v1.  This would drastically reduce your code and be more future proof.  It might also resolve the issue although I'd still be unclear why.

    Michael Taylor
    http://msmvps.com/blogs/p3net

    Wednesday, October 16, 2013 2:07 PM
    Moderator

All replies

  • I don't see anything particularly wrong with your code.  I do see places where your code isn't exception safe so if an exception occurred you might get into a state where you wouldn't recover.  Have you tried stepping through the code and verifying it is executing in the manner you expected?  You might also consider getting the last Win32 error if it truly didn't open the port.  Also note that SetLastError defaults to false for DllImport so you might consider setting it to true to ensure you are getting the correct info back.  I'm not aware of any changes in this area but I would say the original v1 code wasn't setting it properly either.

    An alternative is to switch to the SerialPort type that was added post v1.  This would drastically reduce your code and be more future proof.  It might also resolve the issue although I'd still be unclear why.

    Michael Taylor
    http://msmvps.com/blogs/p3net

    Wednesday, October 16, 2013 2:07 PM
    Moderator
  • Hello Michael,

    Thanks a lot for your reply. I can see the problem with SetLastError not being set to true, and I will fix it. This issue would cause Marshal.GetLastWin32Error() to return the wrong error code, and causes wrong exception to be thrown. In my case, I am not getting any exception thrown.

    Unfortunately, I cannot step through the code since I don't have access to that machine as it's located at customer's premises (in another country) behind a firewall and it doesn't have any development tools installed. I stepped through the code on my machine which is not connected to a traffic light hardware, and on my machine it behaves as expected (the port gets is open).

    I will try using the SerialPort type.

    Thanks a lot and best regards,
    Sherif


    http://sherifelmetainy.blogspot.com/

    Thursday, October 17, 2013 9:57 AM
  • Thanks Sherif ,
    From a support perspective this is really beyond what we can do here in the forums. If you cannot determine your answer here or on your own, consider opening a support case with us. Visit this link to see the various support options that are available to better meet your needs: http://support.microsoft.com/default.aspx?id=fh;en-us;offerprophone
    Monday, November 4, 2013 8:45 PM