1.   动机
应用程序开发语言为C# 
应用程序要求既能在PDA上运行,又能在PC上运行,具备良好的兼容性 
应用程序要求尽可能多的兼容不同PDA上的红外线设备 
.net自带的SerialPort在HP某型号PDA上操作红外线设备时,只能接受,不能发射 
2.   目标
具备良好的兼容性,既能够在PC上运行也能够在PDA上运行。 
挡在PDA上运行时,尽可能多的兼容红外设备。 
3.   局限性
单线程 
仅提供send/receive模式的接口,无事件驱动机制 
4.   关键技术问题及典型测试案例
最关键的是对EscapeCommFunction的调用,当串口为红外设备时,必须调用此函数才能确保串口工作正常。当串口为一般的COM口时,出于兼容性的考虑,切勿调用此函数。

在HP某PDA上测试时,不管串口是否为红外设备,均调用此函数启用红外功能,均能够工作正常。 
在SIEMENS某PDA上测试时,如果串口为一般COM接口,并且调用了此函数,那么串口不能正常工作,屏蔽此函数后,一切正常。 
5.   源码

SerialPort Source Code
 using System;
 using System.Runtime.InteropServices;namespace NativeDll
 {
     public class SerialPort
     {
         serial port api#region serial port api
         //for ir control
         private const int SETIR = 10;
         private const int CLRIR = 11;
         //win32 api constants
         private const uint GENERIC_READ = 0x80000000;
         private const uint GENERIC_WRITE = 0x40000000;
         private const int OPEN_EXISTING = 3;
         private const int INVALID_HANDLE_VALUE = -1;
         private const int MAXBLOCK = 4096;        private const uint PURGE_TXABORT = 0x0001;
         // Kill the pending/current writes to the comm port.
         private const uint PURGE_RXABORT = 0x0002;
         // Kill the pending/current reads to the comm port.
         private const uint PURGE_TXCLEAR = 0x0004;
         // Kill the transmit queue if there.
         private const uint PURGE_RXCLEAR = 0x0008;
         // Kill the typeahead buffer if there.        [StructLayout(LayoutKind.Sequential)]
         private struct DCB
         {
             //taken from c struct in platform sdk
             public int DCBlength; // sizeof(DCB)
             public int BaudRate; // current baud rate
             public int fBinary; // binary mode, no EOF check
             public int fParity; // enable parity checking
             public int fOutxCtsFlow; // CTS output flow control
             public int fOutxDsrFlow; // DSR output flow control
             public int fDtrControl; // DTR flow control type
             public int fDsrSensitivity; // DSR sensitivity
             public int fTXContinueOnXoff; // XOFF continues Tx
             public int fOutX; // XON/XOFF out flow control
             public int fInX; // XON/XOFF in flow control
             public int fErrorChar; // enable error replacement
             public int fNull; // enable null stripping
             public int fRtsControl; // RTS flow control
             public int fAbortOnError; // abort on error
             public int fDummy2; // reserved
             public ushort wReserved; // not currently used
             public ushort XonLim; // transmit XON threshold
             public ushort XoffLim; // transmit XOFF threshold
             public byte ByteSize; // number of bits/byte, 4-8
             public byte Parity; // 0-4=no,odd,even,mark,space
             public byte StopBits; // 0,1,2 = 1, 1.5, 2
             public char XonChar; // Tx and Rx XON character
             public char XoffChar; // Tx and Rx XOFF character
             public char ErrorChar; // error replacement character
             public char EofChar; // end of input character
             public char EvtChar; // received event character
             public ushort wReserved1; // reserved; do not use
         }        [StructLayout(LayoutKind.Sequential)]
         private struct COMMTIMEOUTS
         {
             public int ReadIntervalTimeout;
             public int ReadTotalTimeoutMultiplier;
             public int ReadTotalTimeoutConstant;
             public int WriteTotalTimeoutMultiplier;
             public int WriteTotalTimeoutConstant;
         }        [StructLayout(LayoutKind.Sequential)]
         private struct OVERLAPPED
         {
             public int Internal;
             public int InternalHigh;
             public int Offset;
             public int OffsetHigh;
             public int hEvent;
         }        [StructLayout(LayoutKind.Sequential)]
         private struct COMSTAT
         {
             /**//*public int fCtsHold;
             public int fDsrHold;
             public int fRlsdHold;
             public int fXoffHold;
             public int fXoffSent;
             public int fEof;
             public int fTxim;
             public int fReserved;
             public int cbInQue;
             public int cbOutQue;*/
             // Should have a reverse, i don't know why!!!!!
             public int cbOutQue;
             public int cbInQue;
             public int fReserved;
             public int fTxim;
             public int fEof;
             public int fXoffSent;
             public int fXoffHold;
             public int fRlsdHold;
             public int fDsrHold;
             public int fCtsHold;
         }        #endregion
        private int hComm = INVALID_HANDLE_VALUE;
         private bool bOpened = false;
         private API api = null;        public SerialPort()
         {
             if (System.Environment.OSVersion.Platform != PlatformID.WinCE)
                 api = new PCAPI();
             else
                 api = new PDAAPI();
         }        public bool Opened
         {
             get
             {
                 return bOpened;
             }
         }        /** <summary>
         /// open port
         /// </summary>
         /// <param name="lpFileName"></param>
         /// <param name="baudRate"></param>
         /// <param name="parity"></param>
         /// <param name="byteSize"></param>
         /// <param name="stopBits"></param>
         /// <returns></returns>
         public bool OpenPort(string lpFileName, int baudRate, byte parity, byte
             byteSize, byte stopBits)
         {
             // OPEN THE COMM PORT.
             hComm = api.CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, 0,
                 0, OPEN_EXISTING, 0, 0);
             // IF THE PORT CANNOT BE OPENED, BAIL OUT.
             if (hComm == INVALID_HANDLE_VALUE)
             {
                 return false;
             }            api.SetupComm(hComm, MAXBLOCK, MAXBLOCK);
             // SET THE COMM TIMEOUTS.
             COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS();
             api.GetCommTimeouts(hComm, ref ctoCommPort);
             ctoCommPort.ReadIntervalTimeout = Int32.MaxValue;
             ctoCommPort.ReadTotalTimeoutConstant = 1000;
             ctoCommPort.ReadTotalTimeoutMultiplier = 0;
             ctoCommPort.WriteTotalTimeoutMultiplier = 0;
             ctoCommPort.WriteTotalTimeoutConstant = 1000;
             api.SetCommTimeouts(hComm, ref ctoCommPort);            // SET BAUD RATE, PARITY, word SIZE, AND STOP BITS.
             // THERE ARE OTHER WAYS OF DOING SETTING THESE BUT THIS IS THE EASIEST.
             // IF YOU WANT TO LATER ADD CODE FOR OTHER BAUD RATES, REMEMBER
             // THAT THE ARGUMENT FOR BuildCommDCB MUST BE A POINTER TO A STRING.
             // ALSO NOTE THAT BuildCommDCB() DEFAULTS TO NO HANDSHAKING.
             DCB dcbCommPort = new DCB();
             dcbCommPort.DCBlength = Marshal.SizeOf(dcbCommPort);
             api.GetCommState(hComm, ref dcbCommPort);
             dcbCommPort.BaudRate = baudRate;
             dcbCommPort.Parity = parity;
             dcbCommPort.ByteSize = byteSize;
             dcbCommPort.StopBits = stopBits;
             api.SetCommState(hComm, ref dcbCommPort);            api.PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);
             api.PurgeComm(hComm, PURGE_TXCLEAR | PURGE_TXABORT);            bOpened = true;
             return true;
         }
         /** <summary>
         /// when set this property ,be sure the port is opened.
         /// </summary>
         public bool IREnable
         {
             set
             {
                 if (bOpened)
                 {
                     if (System.Environment.OSVersion.Platform == PlatformID.WinCE)
                     {
                         if (value)
                         {
                             api.EscapeCommFunction(hComm, SETIR);//enable ir
                         }
                         else
                         {
                             api.EscapeCommFunction(hComm, CLRIR);//disable ir
                         }
                     }
                 }
             }
         }
         /** <summary>
         /// get/set baudrate
         /// </summary>
         public int BaudRate
         {
             get
             {
                 DCB dcbCommPort = new DCB();
                 dcbCommPort.DCBlength = Marshal.SizeOf(dcbCommPort);
                 api.GetCommState(hComm, ref dcbCommPort);
                 return dcbCommPort.BaudRate;
             }
             set
             {
                 DCB dcbCommPort = new DCB();
                 dcbCommPort.DCBlength = Marshal.SizeOf(dcbCommPort);
                 api.GetCommState(hComm, ref dcbCommPort);
                 dcbCommPort.BaudRate = value;
                 api.SetCommState(hComm, ref dcbCommPort);                //12/21/2006 wang
                 //api.PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);
                 //api.PurgeComm(hComm, PURGE_TXCLEAR | PURGE_TXABORT);
             }
         }
         /** <summary>
         /// close port
         /// </summary>
         /// <returns></returns>
         public bool ClosePort()
         {
             if (hComm == INVALID_HANDLE_VALUE)
             {
                 return false;
             }            if (api.CloseHandle(hComm))
             {
                 hComm = INVALID_HANDLE_VALUE;
                 bOpened = false;
                 return true;
             }
             else
             {
                 return false;
             }
         }        /** <summary>
         /// write to port
         /// </summary>
         /// <param name="WriteBytes"></param>
         /// <returns></returns>
         public bool WritePort(byte[] WriteBytes)
         {
             bool flag = false;
             COMSTAT ComStat = new COMSTAT();
             int dwErrorFlags = 0;
             int BytesWritten = 0;
             OVERLAPPED ovlCommPort = new OVERLAPPED();
             api.ClearCommError(hComm, ref dwErrorFlags, ref ComStat);
             api.PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);
             //api.PurgeComm(hComm, PURGE_TXCLEAR | PURGE_TXABORT);//19/10 2006 wang this is because of the hitachi mode writing bytes continuesly
             flag = api.WriteFile(hComm, WriteBytes, WriteBytes.Length, ref BytesWritten, ref ovlCommPort);
             return flag;
         }        /** <summary>
         /// read from port
         /// </summary>
         /// <param name="NumBytes"></param>
         /// <param name="commRead"></param>
         /// <returns></returns>
         public bool ReadPort(int NumBytes, ref byte[] commRead)
         {
             bool flag = false;
             COMSTAT ComStat = new COMSTAT();
             int dwErrorFlags = 0;
             int BytesRead = 0;
             OVERLAPPED ovlCommPort = new OVERLAPPED();
             api.ClearCommError(hComm, ref dwErrorFlags, ref ComStat);
             flag = api.ReadFile(hComm, commRead, NumBytes, ref BytesRead, ref ovlCommPort);
             return flag;
         }
         interface API
         {
             int CreateFile(string lpFileName,  // file name
             uint dwDesiredAccess,  // access mode
             int dwShareMode,  // share mode
             int lpSecurityAttributes,  // SD
             int dwCreationDisposition,  // how to create
             int dwFlagsAndAttributes,  // file attributes
             int hTemplateFile  // handle to template file
             );             bool GetCommState(int hFile,  // handle to communications device
             ref DCB lpDCB  // device-control block
             );             bool BuildCommDCB(string lpDef,  // device-control string
             ref DCB lpDCB  // device-control block
             );             bool SetCommState(int hFile,  // handle to communications device
             ref DCB lpDCB  // device-control block
             );             bool GetCommTimeouts(int hFile,  // handle to comm device
             ref COMMTIMEOUTS lpCommTimeouts  // time-out values
             );             bool SetCommTimeouts(int hFile,  // handle to comm device
             ref COMMTIMEOUTS lpCommTimeouts  // time-out values
             );             bool ReadFile(int hFile,  // handle to file
             byte[] lpBuffer,  // data buffer
             int nNumberOfBytesToRead,  // number of bytes to read
             ref int lpNumberOfBytesRead,  // number of bytes read
             ref OVERLAPPED lpOverlapped  // overlapped buffer
             );             bool WriteFile(int hFile,  // handle to file
             byte[] lpBuffer,  // data buffer
             int nNumberOfBytesToWrite,  // number of bytes to write
             ref int lpNumberOfBytesWritten,  // number of bytes written
             ref OVERLAPPED lpOverlapped  // overlapped buffer
             );             bool CloseHandle(int hObject  // handle to object
             );             bool ClearCommError(int hFile,  // handle to file
             ref int lpErrors, ref COMSTAT lpStat);             bool PurgeComm(int hFile,  // handle to file
             uint dwFlags);             bool SetupComm(int hFile, int dwInQueue, int dwOutQueue);
            int EscapeCommFunction(int hFile, UInt32 dwFunc);
         }
         class PCAPI : API
         {
             public int CreateFile(string lpFileName,  // file name
             uint dwDesiredAccess,  // access mode
             int dwShareMode,  // share mode
             int lpSecurityAttributes,  // SD
             int dwCreationDisposition,  // how to create
             int dwFlagsAndAttributes,  // file attributes
             int hTemplateFile  // handle to template file
             )
             {
                 return WinCreateFile(lpFileName,  // file name
                 dwDesiredAccess,  // access mode
                 dwShareMode,  // share mode
                 lpSecurityAttributes,  // SD
                 dwCreationDisposition,  // how to create
                 dwFlagsAndAttributes,  // file attributes
                 hTemplateFile  // handle to template file
                 );
             }             public bool GetCommState(int hFile,
                 // handle to communications device
             ref DCB lpDCB  // device-control block
             )
             {
                 return WinGetCommState(hFile,
                     // handle to communications device
                 ref lpDCB  // device-control block
                 );
             }             public bool BuildCommDCB(string lpDef,  // device-control string
             ref DCB lpDCB  // device-control block
             )
             {
                 return WinBuildCommDCB(lpDef,  // device-control string
                 ref lpDCB  // device-control block
                 );
             }             public bool SetCommState(int hFile,
                 // handle to communications device
             ref DCB lpDCB  // device-control block
             )
             {
                 return WinSetCommState(hFile,
                     // handle to communications device
                 ref lpDCB  // device-control block
                 );
             }             public bool GetCommTimeouts(int hFile,  // handle to comm device
             ref COMMTIMEOUTS lpCommTimeouts  // time-out values
             )
             {
                 return WinGetCommTimeouts(hFile,  // handle to comm device
                 ref lpCommTimeouts  // time-out values
                 );
             }             public bool SetCommTimeouts(int hFile,  // handle to comm device
             ref COMMTIMEOUTS lpCommTimeouts  // time-out values
             )
             {
                 return WinSetCommTimeouts(hFile,  // handle to comm device
                 ref lpCommTimeouts  // time-out values
                 );
             }             public bool ReadFile(int hFile,  // handle to file
             byte[] lpBuffer,  // data buffer
             int nNumberOfBytesToRead,  // number of bytes to read
             ref int lpNumberOfBytesRead,  // number of bytes read
             ref OVERLAPPED lpOverlapped  // overlapped buffer
             )
             {
                 return WinReadFile(hFile,  // handle to file
                 lpBuffer,  // data buffer
                 nNumberOfBytesToRead,  // number of bytes to read
                 ref lpNumberOfBytesRead,  // number of bytes read
                 ref lpOverlapped  // overlapped buffer
                 );
             }             public bool WriteFile(int hFile,  // handle to file
             byte[] lpBuffer,  // data buffer
             int nNumberOfBytesToWrite,  // number of bytes to write
             ref int lpNumberOfBytesWritten,  // number of bytes written
             ref OVERLAPPED lpOverlapped  // overlapped buffer
             )
             {
                 return WinWriteFile(hFile,  // handle to file
                 lpBuffer,  // data buffer
                 nNumberOfBytesToWrite,  // number of bytes to write
                 ref lpNumberOfBytesWritten,  // number of bytes written
                 ref lpOverlapped  // overlapped buffer
                 );
             }             public bool CloseHandle(int hObject  // handle to object
             )
             {
                 return WinCloseHandle(hObject  // handle to object
                 );
             }             public bool ClearCommError(int hFile,  // handle to file
             ref int lpErrors, ref COMSTAT lpStat)
             {
                 return WinClearCommError(hFile,  // handle to file
                 ref lpErrors, ref lpStat);
             }             public bool PurgeComm(int hFile,  // handle to file
             uint dwFlags)
             {
                 return WinPurgeComm(hFile,  // handle to file
                 dwFlags);
             }             public bool SetupComm(int hFile, int dwInQueue, int dwOutQueue)
             {
                 return WinSetupComm(hFile, dwInQueue, dwOutQueue);
             }            public int EscapeCommFunction(int hFile, UInt32 dwFunc)
             {
                 return WinEscapeCommFunction(hFile, dwFunc);
             }
             P/Invoke#region P/Invoke
             [DllImport("kernel32", EntryPoint = "CreateFile")]
             private static extern int WinCreateFile(string lpFileName,
                 // file name
             uint dwDesiredAccess,  // access mode
             int dwShareMode,  // share mode
             int lpSecurityAttributes,  // SD
             int dwCreationDisposition,  // how to create
             int dwFlagsAndAttributes,  // file attributes
             int hTemplateFile  // handle to template file
             );            [DllImport("kernel32", EntryPoint = "GetCommState")]
             private static extern bool WinGetCommState(int hFile,
                 // handle to communications device
             ref DCB lpDCB  // device-control block
             );            [DllImport("kernel32", EntryPoint = "BuildCommDCB")]
             private static extern bool WinBuildCommDCB(string lpDef,
                 // device-control string
             ref DCB lpDCB  // device-control block
             );            [DllImport("kernel32", EntryPoint = "SetCommState")]
             private static extern bool WinSetCommState(int hFile,
                 // handle to communications device
             ref DCB lpDCB  // device-control block
             );            [DllImport("kernel32", EntryPoint = "GetCommTimeouts")]
             private static extern bool WinGetCommTimeouts(int hFile,
                 // handle to comm device
             ref COMMTIMEOUTS lpCommTimeouts  // time-out values
             );            [DllImport("kernel32", EntryPoint = "SetCommTimeouts")]
             private static extern bool WinSetCommTimeouts(int hFile,
                 // handle to comm device
             ref COMMTIMEOUTS lpCommTimeouts  // time-out values
             );            [DllImport("kernel32", EntryPoint = "ReadFile")]
             private static extern bool WinReadFile(int hFile,  // handle to file
             byte[] lpBuffer,  // data buffer
             int nNumberOfBytesToRead,  // number of bytes to read
             ref int lpNumberOfBytesRead,  // number of bytes read
             ref OVERLAPPED lpOverlapped  // overlapped buffer
             );            [DllImport("kernel32", EntryPoint = "WriteFile")]
             private static extern bool WinWriteFile(int hFile,
                 // handle to file
             byte[] lpBuffer,  // data buffer
             int nNumberOfBytesToWrite,  // number of bytes to write
             ref int lpNumberOfBytesWritten,  // number of bytes written
             ref OVERLAPPED lpOverlapped  // overlapped buffer
             );            [DllImport("kernel32", EntryPoint = "CloseHandle")]
             private static extern bool WinCloseHandle(int hObject
                 // handle to object
             );            [DllImport("kernel32", EntryPoint = "ClearCommError")]
             private static extern bool WinClearCommError(int hFile,
                 // handle to file
             ref int lpErrors, ref COMSTAT lpStat);            [DllImport("kernel32", EntryPoint = "PurgeComm")]
             private static extern bool WinPurgeComm(int hFile,
                 // handle to file
             uint dwFlags);            [DllImport("kernel32", EntryPoint = "SetupComm")]
             private static extern bool WinSetupComm(int hFile, int dwInQueue,
                 int dwOutQueue);            [DllImport("kernel32", EntryPoint = "EscapeCommFunction")]
             private static extern int WinEscapeCommFunction(int hFile, UInt32 dwFunc);
             #endregion
         }
         class PDAAPI : API
         {
             public int CreateFile(string lpFileName,  // file name
             uint dwDesiredAccess,  // access mode
             int dwShareMode,  // share mode
             int lpSecurityAttributes,  // SD
             int dwCreationDisposition,  // how to create
             int dwFlagsAndAttributes,  // file attributes
             int hTemplateFile  // handle to template file
             )
             {
                 return CECreateFile(lpFileName,  // file name
                 dwDesiredAccess,  // access mode
                 dwShareMode,  // share mode
                 lpSecurityAttributes,  // SD
                 dwCreationDisposition,  // how to create
                 dwFlagsAndAttributes,  // file attributes
                 hTemplateFile  // handle to template file
                 );
             }             public bool GetCommState(int hFile,
                 // handle to communications device
             ref DCB lpDCB  // device-control block
             )
             {
                 return CEGetCommState(hFile,  // handle to communications device
                 ref lpDCB  // device-control block
                 );
             }             public bool BuildCommDCB(string lpDef,  // device-control string
             ref DCB lpDCB  // device-control block
             )
             {
                 return CEBuildCommDCB(lpDef,  // device-control string
                 ref lpDCB  // device-control block
                 );
             }             public bool SetCommState(int hFile,
                 // handle to communications device
             ref DCB lpDCB  // device-control block
             )
             {
                 return CESetCommState(hFile,  // handle to communications device
                 ref lpDCB  // device-control block
                 );
             }             public bool GetCommTimeouts(int hFile,  // handle to comm device
             ref COMMTIMEOUTS lpCommTimeouts  // time-out values
             )
             {
                 return CEGetCommTimeouts(hFile,  // handle to comm device
                 ref lpCommTimeouts  // time-out values
                 );
             }             public bool SetCommTimeouts(int hFile,  // handle to comm device
             ref COMMTIMEOUTS lpCommTimeouts  // time-out values
             )
             {
                 return CESetCommTimeouts(hFile,  // handle to comm device
                 ref lpCommTimeouts  // time-out values
                 );
             }             public bool ReadFile(int hFile,  // handle to file
             byte[] lpBuffer,  // data buffer
             int nNumberOfBytesToRead,  // number of bytes to read
             ref int lpNumberOfBytesRead,  // number of bytes read
             ref OVERLAPPED lpOverlapped  // overlapped buffer
             )
             {
                 return CEReadFile(hFile,  // handle to file
                 lpBuffer,  // data buffer
                 nNumberOfBytesToRead,  // number of bytes to read
                 ref lpNumberOfBytesRead,  // number of bytes read
                 ref lpOverlapped  // overlapped buffer
                 );
             }             public bool WriteFile(int hFile,  // handle to file
             byte[] lpBuffer,  // data buffer
             int nNumberOfBytesToWrite,  // number of bytes to write
             ref int lpNumberOfBytesWritten,  // number of bytes written
             ref OVERLAPPED lpOverlapped  // overlapped buffer
             )
             {
                 return CEWriteFile(hFile,  // handle to file
                 lpBuffer,  // data buffer
                 nNumberOfBytesToWrite,  // number of bytes to write
                 ref lpNumberOfBytesWritten,  // number of bytes written
                 ref lpOverlapped  // overlapped buffer
                 );
             }             public bool CloseHandle(int hObject  // handle to object
             )
             {
                 return CECloseHandle(hObject  // handle to object
                 );
             }             public bool ClearCommError(int hFile,  // handle to file
             ref int lpErrors, ref COMSTAT lpStat)
             {
                 return CEClearCommError(hFile,  // handle to file
                 ref lpErrors, ref lpStat);
             }             public bool PurgeComm(int hFile,  // handle to file
             uint dwFlags)
             {
                 return CEPurgeComm(hFile,  // handle to file
                 dwFlags);
             }             public bool SetupComm(int hFile, int dwInQueue, int dwOutQueue)
             {
                 return CESetupComm(hFile, dwInQueue, dwOutQueue);
             }            public int EscapeCommFunction(int hFile, UInt32 dwFunc)
             {
                 return CEEscapeCommFunction(hFile, dwFunc);
             }
             P/Invoke#region P/Invoke
             [DllImport("coredll", EntryPoint = "CreateFile")]
             private static extern int CECreateFile(string lpFileName,
                 // file name
             uint dwDesiredAccess,  // access mode
             int dwShareMode,  // share mode
             int lpSecurityAttributes,  // SD
             int dwCreationDisposition,  // how to create
             int dwFlagsAndAttributes,  // file attributes
             int hTemplateFile  // handle to template file
             );            [DllImport("coredll", EntryPoint = "GetCommState")]
             private static extern bool CEGetCommState(int hFile,
                 // handle to communications device
             ref DCB lpDCB  // device-control block
             );            [DllImport("coredll", EntryPoint = "BuildCommDCB")]
             private static extern bool CEBuildCommDCB(string lpDef,
                 // device-control string
             ref DCB lpDCB  // device-control block
             );            [DllImport("coredll", EntryPoint = "SetCommState")]
             private static extern bool CESetCommState(int hFile,
                 // handle to communications device
             ref DCB lpDCB  // device-control block
             );            [DllImport("coredll", EntryPoint = "GetCommTimeouts")]
             private static extern bool CEGetCommTimeouts(int hFile,
                 // handle to comm device
             ref COMMTIMEOUTS lpCommTimeouts  // time-out values
             );            [DllImport("coredll", EntryPoint = "SetCommTimeouts")]
             private static extern bool CESetCommTimeouts(int hFile,
                 // handle to comm device
             ref COMMTIMEOUTS lpCommTimeouts  // time-out values
             );            [DllImport("coredll", EntryPoint = "ReadFile")]
             private static extern bool CEReadFile(int hFile,  // handle to file
             byte[] lpBuffer,  // data buffer
             int nNumberOfBytesToRead,  // number of bytes to read
             ref int lpNumberOfBytesRead,  // number of bytes read
             ref OVERLAPPED lpOverlapped  // overlapped buffer
             );            [DllImport("coredll", EntryPoint = "WriteFile")]
             private static extern bool CEWriteFile(int hFile,  // handle to file
             byte[] lpBuffer,  // data buffer
             int nNumberOfBytesToWrite,  // number of bytes to write
             ref int lpNumberOfBytesWritten,  // number of bytes written
             ref OVERLAPPED lpOverlapped  // overlapped buffer
             );            [DllImport("coredll", EntryPoint = "CloseHandle")]
             private static extern bool CECloseHandle(int hObject
                 // handle to object
             );            [DllImport("coredll", EntryPoint = "ClearCommError")]
             private static extern bool CEClearCommError(int hFile,
                 // handle to file
             ref int lpErrors, ref COMSTAT lpStat);            [DllImport("coredll", EntryPoint = "PurgeComm")]
             private static extern bool CEPurgeComm(int hFile,  // handle to file
             uint dwFlags);            [DllImport("coredll", EntryPoint = "SetupComm")]
             private static extern bool CESetupComm(int hFile, int dwInQueue,
                 int dwOutQueue);            [DllImport("coredll", EntryPoint = "EscapeCommFunction")]
             private static extern int CEEscapeCommFunction(int hFile, UInt32 dwFunc);
             #endregion
         }
     }
 }

6.   补充
自定义的SerialPort类虽然对IR有较大的兼容性,但毕竟测试范围有限,不能保证对所有的设备都能够兼容。因此最初的想法是对.net自带的SerialPort对象调用EscapeCommFunction函数,但苦于无法得到对象的Handle对象,一直没有实现,如果可以的话,将能享受到更强大的串口功能。

当然,该类远未完善,希望大家能够尽可能的测试并给出意见:)