none
设备不识别此命令,串口设备读取数据时拔插后,关闭程序报错,不关闭,过一会儿也会报错。 RRS feed

答案

  • 你好:

    我没有重现过这个问题,但是搜索了一下,发现通过Try-Catch确实无法捕获到这个异常,你可以尝试一下通过AppDomain.UnhandledException事件来从AppDomain角度捕获异常。

    SerialPort底层是调用的Windows API接口来传输数据的,抛出这个异常的原因是当设备被拔出之后SerialPort会Dispose, SerialPort内部的SerialStream的实现有些问题,SerialPort调用Windows API初始化的时候忽略了一个名为"fAbortOnError"的标志位,导致SerialStream在Dispose方法中在某些情况下抛出异常无法捕获。

    可以尝试一下这篇文章中的解决办法(代码中封装了一个类,在初始化SerialPort之前调用该类中的Execute方法):

    // Copyright 2010-2014 Zach Saw
    // 
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    // 
    //     http://www.apache.org/licenses/LICENSE-2.0
    // 
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    
    using System;
    using System.IO;
    using System.IO.Ports;
    using System.Runtime.InteropServices;
    using System.Text;
    using Microsoft.Win32.SafeHandles;
    
    namespace SerialPortTester
    {
        public class SerialPortFixer : IDisposable
        {
            public static void Execute(string portName)
            {
                using (new SerialPortFixer(portName))
                {
                }
            }
            #region IDisposable Members
    
            public void Dispose()
            {
                if (m_Handle != null)
                {
                    m_Handle.Close();
                    m_Handle = null;
                }
            }
    
            #endregion
    
            #region Implementation
    
            private const int DcbFlagAbortOnError = 14;
            private const int CommStateRetries = 10;
            private SafeFileHandle m_Handle;
    
            private SerialPortFixer(string portName)
            {
                const int dwFlagsAndAttributes = 0x40000000;
                const int dwAccess = unchecked((int)0xC0000000);
    
                if ((portName == null) || !portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase))
                {
                    throw new ArgumentException("Invalid Serial Port", "portName");
                }
                SafeFileHandle hFile = CreateFile(@"\\.\" + portName, dwAccess, 0, IntPtr.Zero, 3, dwFlagsAndAttributes,
                                                  IntPtr.Zero);
                if (hFile.IsInvalid)
                {
                    WinIoError();
                }
                try
                {
                    int fileType = GetFileType(hFile);
                    if ((fileType != 2) && (fileType != 0))
                    {
                        throw new ArgumentException("Invalid Serial Port", "portName");
                    }
                    m_Handle = hFile;
                    InitializeDcb();
                }
                catch
                {
                    hFile.Close();
                    m_Handle = null;
                    throw;
                }
            }
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId,
                                                    StringBuilder lpBuffer, int nSize, IntPtr arguments);
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool GetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool SetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool ClearCommError(SafeFileHandle hFile, ref int lpErrors, ref Comstat lpStat);
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
                                                            IntPtr securityAttrs, int dwCreationDisposition,
                                                            int dwFlagsAndAttributes, IntPtr hTemplateFile);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            private static extern int GetFileType(SafeFileHandle hFile);
    
            private void InitializeDcb()
            {
                Dcb dcb = new Dcb();
                GetCommStateNative(ref dcb);
                dcb.Flags &= ~(1u << DcbFlagAbortOnError);
                SetCommStateNative(ref dcb);
            }
    
            private static string GetMessage(int errorCode)
            {
                StringBuilder lpBuffer = new StringBuilder(0x200);
                if (
                    FormatMessage(0x3200, new HandleRef(null, IntPtr.Zero), errorCode, 0, lpBuffer, lpBuffer.Capacity,
                                  IntPtr.Zero) != 0)
                {
                    return lpBuffer.ToString();
                }
                return "Unknown Error";
            }
    
            private static int MakeHrFromErrorCode(int errorCode)
            {
                return (int)(0x80070000 | (uint)errorCode);
            }
    
            private static void WinIoError()
            {
                int errorCode = Marshal.GetLastWin32Error();
                throw new IOException(GetMessage(errorCode), MakeHrFromErrorCode(errorCode));
            }
    
            private void GetCommStateNative(ref Dcb lpDcb)
            {
                int commErrors = 0;
                Comstat comStat = new Comstat();
    
                for (int i = 0; i < CommStateRetries; i++)
                {
                    if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
                    {
                        WinIoError();
                    }
                    if (GetCommState(m_Handle, ref lpDcb))
                    {
                        break;
                    }
                    if (i == CommStateRetries - 1)
                    {
                        WinIoError();
                    }
                }
            }
    
            private void SetCommStateNative(ref Dcb lpDcb)
            {
                int commErrors = 0;
                Comstat comStat = new Comstat();
    
                for (int i = 0; i < CommStateRetries; i++)
                {
                    if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
                    {
                        WinIoError();
                    }
                    if (SetCommState(m_Handle, ref lpDcb))
                    {
                        break;
                    }
                    if (i == CommStateRetries - 1)
                    {
                        WinIoError();
                    }
                }
            }
    
            #region Nested type: COMSTAT
    
            [StructLayout(LayoutKind.Sequential)]
            private struct Comstat
            {
                public readonly uint Flags;
                public readonly uint cbInQue;
                public readonly uint cbOutQue;
            }
    
            #endregion
    
            #region Nested type: DCB
    
            [StructLayout(LayoutKind.Sequential)]
            private struct Dcb
            {
                public readonly uint DCBlength;
                public readonly uint BaudRate;
                public uint Flags;
                public readonly ushort wReserved;
                public readonly ushort XonLim;
                public readonly ushort XoffLim;
                public readonly byte ByteSize;
                public readonly byte Parity;
                public readonly byte StopBits;
                public readonly byte XonChar;
                public readonly byte XoffChar;
                public readonly byte ErrorChar;
                public readonly byte EofChar;
                public readonly byte EvtChar;
                public readonly ushort wReserved1;
            }
    
            #endregion
    
            #endregion
        }
    
        internal class Program
        {
            private static void Main(string[] args)
            {
                SerialPortFixer.Execute("COM1");
                using (SerialPort port = new SerialPort("COM1"))
                {
                    port.Write("test");
                }
            }
        }
    }
    


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2015年5月4日 10:02
    版主

全部回复

  • using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Text.RegularExpressions;
    
    namespace getGps
    {
        public partial class Form1 : Form
        {
            #region 变量
            /// <summary>
            /// GPS设备名称
            /// </summary>
            string gpsDeviceName;
            /// <summary>
            /// 是否没有执行完invoke相关操作
            /// </summary>
            private bool Listening = false;
            /// <summary>
            /// 是否正在关闭串口,执行Application.DoEvents,并阻止再次invoke  
            /// </summary>
            private bool Closing = false;
            /// <summary>
            /// 获取从GPS设备返回的数据
            /// </summary>
            string[] gps;
            /// <summary>
            /// 临时保存从GPS返回的字符串
            /// </summary>
            string data;
            /// <summary>
            /// 度格式
            /// </summary>
            private bool _isDegreeFormat = true;
            #endregion
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                //if (!serialPort1.IsOpen)//1.判断串口是否打开
                //{
                //    try
                //    {
                //        string portname = cboDeviceList.SelectedItem.ToString();//1.1.1.获取串口名称
                //        Regex reg = new Regex(@"\((\w*)\)");//1.1.2.定义一个正则表达式用于获取括号内的端口号
                //        Match m = reg.Match(portname);//1.1.3.获取端口号
                //        serialPort1.PortName = m.Groups[1].Value;//1.1.4.端口号赋值
                //        serialPort1.BaudRate = 4800;//1.1.5.波特率赋值
                //        serialPort1.DataBits = 8;//1.1.6.数据位长度赋值
                //        serialPort1.Parity = Parity.None;//1.1.7.奇偶校验协议赋值
                //        serialPort1.StopBits = StopBits.One;//1.1.8.停止位数赋值
                //        serialPort1.Open();//1.1.9.打开端口
                //    }
                //    catch
                //    {
                //        MessageBox.Show("GPS设备故障,请重新拔插设备!");//1.2.1.如果出错,则报故障,让重新拔插GPS设备
                //    }
                //}
                //else//2.如果端口已经打开
                //{
                //    serialPortClose();//2.1.调用关闭串口方法
                //}
                
               
            }
    
            #region 根据用户选择将GPS设备传过来的数据转换成标准的经纬度
            /// <summary>
            /// 根据用户选择将GPS设备传过来的数据转换成标准的经纬度
            /// </summary>
            /// <param name="gps">含有GPS数据的字符串</param>
            /// <param name="radionIndex">用户选择是【小数】格式还是【度分秒】格式,通常0代表【小数】,1代表【度分秒】</param>
            /// <returns></returns>
            string[] convertToStandardLongitudeAndLatitude(string[] gps, int radioIndex)
            {
                string[] result = { "", "" };
                string longitude = gps[5];//经度,暂时不管东西经
                string latitude = gps[3];//纬度,暂时不管南北纬
    
                //string lon = textBox1.Text;
                //textBox3.Text =
                result[0] = Math.Round((Convert.ToDouble(longitude.Substring(0, longitude.IndexOf(".") - 2)) + Convert.ToDouble(longitude.Substring(longitude.IndexOf(".") - 2)) / 60), 6).ToString();
                result[1] = Math.Round((Convert.ToDouble(latitude.Substring(0, latitude.IndexOf(".") - 2)) + Convert.ToDouble(latitude.Substring(latitude.IndexOf(".") - 2)) / 60), 6).ToString();
                //string longLimit = (longitude).ToString().Substring(0, longitude.ToString().IndexOf('.'));//经度度
                //string longMinute = (longitude).ToString().Substring(longitude.ToString().IndexOf('.'), 3).Replace(".", "");//经度分
                //string longSecond = (Math.Round(longitude, 4)).ToString().Substring(longitude.ToString().IndexOf('.') + 3, 2);//经度秒
                //string latLimit = (latitude).ToString().Substring(0, latitude.ToString().IndexOf('.'));//纬度度
                //string latMinute = (latitude).ToString().Substring(latitude.ToString().IndexOf('.'), 3).Replace(".", "");//纬度分
                //string latSecond = (Math.Round(latitude, 4)).ToString().Substring(latitude.ToString().IndexOf('.') + 3, 2);//纬度秒
                //result[0] = longLimit + "°" + longMinute + "′" + longSecond + "″";
                //result[1] = latLimit + "°" + latMinute + "′" + latSecond + "″";
                if (radioIndex == 0)//如果选择的是小数格式
                {
                    return result;
                }
                else//否则返回【度分秒】格式 
                {
                    result[0] = ConvertDigitalToDegrees(result[0]).ToString();//经度
                    result[1] = ConvertDigitalToDegrees(result[1]).ToString();//纬度
                    return result;
                }
            }
            #endregion
    
            #region 度分秒经纬度(必须含有'°')和数字经纬度转换
            /// <summary>
            /// 度分秒经纬度(必须含有'°')和数字经纬度转换 
            /// </summary>
            /// <param name="digitalDegree">度分秒经纬度</param>
            /// <return>数字经纬度</return>
            static public double ConvertDegreesToDigital(string degrees)
            {
                const double num = 60;
                double digitalDegree = 0.0;
                int d = degrees.IndexOf('°');//度的符号对应的 Unicode 代码为:00B0[1](六十进制),显示为°。
                if (d < 0)
                {
                    return digitalDegree;
                }
                string degree = degrees.Substring(0, d);
                digitalDegree += Convert.ToDouble(degree);
                int m = degrees.IndexOf('′');//分的符号对应的 Unicode 代码为:2032[1](六十进制),显示为′。
                if (m < 0)
                {
                    return digitalDegree;
                }
                string minute = degrees.Substring(d + 1, m - d - 1);
                digitalDegree += ((Convert.ToDouble(minute)) / num);
                int s = degrees.IndexOf('″');//秒的符号对应的 Unicode 代码为:2033[1](六十进制),显示为″。
                if (s < 0)
                {
                    return digitalDegree;
                }
                string second = degrees.Substring(m + 1, s - m - 1);
                digitalDegree += (Convert.ToDouble(second) / (num * num));
                return Math.Round(digitalDegree, 6);
            }
            #endregion
    
            #region 数字经纬度和度分秒经纬度转换
            /// <summary>
            /// 数字经纬度和度分秒经纬度转换 (Digital degree of latitude and longitude and vehicle to latitude and longitude conversion)
            /// </summary>
            /// <param name="digitalLati_Longi">数字经纬度</param>
            /// <return>度分秒经纬度</return>
            static public string ConvertDigitalToDegrees(string digitalLati_Longi)
            {
                double digitalDegree = Convert.ToDouble(digitalLati_Longi);
                return ConvertDigitalToDegrees(digitalDegree);
            }
            #endregion
    
            #region 数字经纬度和度分秒经纬度转换
            /// <summary>
            /// 数字经纬度和度分秒经纬度转换 (Digital degree of latitude and longitude and vehicle to latitude and longitude conversion)
            /// </summary>
            /// <param name="digitalDegree">数字经纬度</param>
            /// <return>度分秒经纬度</return>
            static public string ConvertDigitalToDegrees(double digitalDegree)
            {
                const double num = 60;
                int degree = (int)digitalDegree;
                double tmp = (digitalDegree - degree) * num;
                int minute = (int)tmp;
                double second = Math.Round((tmp - minute) * num, 4);
                string degrees = "" + degree + "°" + minute + "′" + second + "″";
                return degrees;
            }
            #endregion
    
            private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
            {
                /* 1.判断是否正在关闭串口
           * 1.1.如果正在关闭,忽略操作,直接返回,尽快完成串口监听线程的一次循环
           * 2.尝试执行命令
           * 2.1.设置标志,说明我已经开始处理数据,一会儿要使用系统UI的线程
           * 2.2.从串口处获取一行数据
           * 2.3.执行委托
           * 2.3.1.判断显示数据的文本框的字符是否大于300
           * 2.3.1.1如果大于300,则清空文本框
           * 2.3.2.判断从串口读取到的字符串是否包含【GPRMC】
           * 2.3.2.1.添加字符串到文本框显示
           * 2.3.2.2.解析串口返回的字符串
           * 2.3.3.判断返回的字符串中是否包含【A】,此标志表示获取经纬度成功
           * 2.3.3.1.根据用户选择将GPS设备传过来的数据转换成标准的经纬度
           * 2.3.3.2.给经度文本框赋值
           * 2.3.3.3.给纬度文本框赋值
           * 3.报错处理
           * 4.最后一定要完成工作
           * 4.1.整个进程已结束,UI可以关闭串口
           */
    
    
                if (Closing)//1.判断是否正在关闭串口
                {
                    return;//1.1.如果正在关闭,忽略操作,直接返回,尽快完成串口监听线程的一次循环  
                }
                try//2.尝试执行命令
                {
                    if (_isFinished)
                    {
                        lock (_object)
                        {
                            if (_isFinished)
                            {
                                _isFinished = false;
    
    
                                #region content
                                Listening = true;//2.1.设置标志,说明我已经开始处理数据,一会儿要使用系统UI的线程
                                data = serialPort1.ReadLine();//2.2.从串口处获取一行数据
                               // serialPort1.DiscardInBuffer();
                              //  serialPort1.DiscardOutBuffer();
                                this.Invoke((EventHandler)(delegate//2.3.执行委托
                                {
                                    if (textBox1.Text.Length > 300)//2.3.1.判断显示数据的文本框的字符是否大于300
                                    {
                                        textBox1.Text = "";//2.3.1.1如果大于300,则清空文本框
                                    }
                                    if (data.Contains("GPRMC"))//2.3.2.判断从串口读取到的字符串是否包含【GPRMC】
                                    {
                                        textBox1.Text += data;//2.3.2.1.添加字符串到文本框显示
                                        gps = data.Trim().Split(',');//2.3.2.2.解析串口返回的字符串
                                        if (gps[2] == "A")//2.3.3.判断返回的字符串中是否包含【A】,此标志表示获取经纬度成功
                                        {
                                            //2.3.3.1.根据用户选择将GPS设备传过来的数据转换成标准的经纬度
                                            //int indexSelect = 0;
                                            //if (radioButton1.Checked)
                                            //{
                                            //    indexSelect = 0;
                                            //}
                                            //else
                                            //{
                                            //    indexSelect = 1;
                                            //}
                                          //  string[] result = convertToStandardLongitudeAndLatitude(gps, indexSelect);
                                           // txblongitude.Text = result[0];//2.3.3.2.给经度文本框赋值
                                          //  txblatitude.Text = result[1];//2.3.3.3.给纬度文本框赋值
                                            txblongitude.Text = gps[5];//2.3.3.2.给经度文本框赋值
                                            txblatitude.Text = gps[3];//2.3.3.3.给纬度文本框赋值
                                        }
                                    }
                                }));
                                #endregion
    
    
                                _isFinished = true;
                            }
                        }
                    }
                    
                }
                catch (Exception ex)//3.报错处理
                {
                    //richTextBox1.AppendText(ex.Message + "\n");
                    //serialPortClose();
                }
                finally//4.最后一定要完成工作
                {
                    Listening = false;//4.1.整个进程已结束,UI可以关闭串口
                }
            }
    
            #region 关闭串口
            /// <summary>
            /// 关闭串口
            /// </summary>
            private void serialPortClose()
            {
                try
                {
                    lock (this)
                    {
    
                        Closing = true;
                        while (Listening) Application.DoEvents();
                        //打开时点击,则关闭串口  
                        serialPort1.Dispose();
                        serialPort1.Close();
    
                        //serialPort1 = null;
    
                        Closing = false;
                    }
                }
                catch (Exception ex)
                {
    
                }
    
            }
            #endregion
    
            private void Form1_Load(object sender, EventArgs e)
            {
                //gpsDeviceName = Hardware.GetHarewareInfo();//获取GPS设备名称
                //if (!string.IsNullOrWhiteSpace(gpsDeviceName))
                //{
                //    /*先获取GPS设备的端口号。
                //     * 端口赋值然后,启用timer控件获取数据
                //     */
                //    Regex reg = new Regex(@"\((\w*)\)");//1.1.2.定义一个正则表达式用于获取括号内的端口号
                //    Match m = reg.Match(gpsDeviceName);//1.1.3.获取端口号
                //    // serialPort1.Dispose();
                //    serialPort1.PortName = m.Groups[1].Value;//1.1.4.端口号赋值
                //    timerGPSDeviceStatus.Enabled = true;
                //    serialPort1.Open();
                //}
               
            }
    
           
    
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {/* 在关闭窗体前,关闭串口
              * 1.关闭串口
              */
                serialPortClose();//1.关闭串口
                
            }
            private static readonly object _object = new object();
            bool _isFinished = true;
            /// <summary>
            /// 判断GPS设备是否接上来了。
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void timerGPSDeviceStatus_Tick(object sender, EventArgs e)
            {
                try
                {
                    gpsDeviceName = Hardware.GetHarewareInfo();//获取GPS设备名称
                    if (!string.IsNullOrWhiteSpace(gpsDeviceName))
                    {
                        /*先获取GPS设备的端口号。
                         * 端口赋值然后,启用timer控件获取数据
                         */
                        Regex reg = new Regex(@"\((\w*)\)");//1.1.2.定义一个正则表达式用于获取括号内的端口号
                        Match m = reg.Match(gpsDeviceName);//1.1.3.获取端口号
                        // serialPort1.Dispose();
                        serialPort1.PortName = m.Groups[1].Value;//1.1.4.端口号赋值
                       // timerGPSDeviceStatus.Enabled = true;
                        serialPort1.Open();
                    }
                    else
                    {
                        if (serialPort1.IsOpen)
                        {
    
    
                            serialPortClose();
                            // serialPort1 = null;
                        }
                    }
                }
                catch (Exception ex)
                {
                    richTextBox1.AppendText(ex.Message.ToString() + "\n");
                }
            }
        }
    }
    

    2015年4月29日 7:36
  • 我在获取USB转串口的GPS设备信息时,如果突然拔出设备。那么关闭程序或者等个几分钟,程序就会报错。

    显示system.io.ioexception类型未经处理的异常出现在system.dll中, 其他信息:设备不识别此命令。

    我在所有的地方都加上TRY CATCH了,但是还是不能捕获该错误。然后程序就被结束了。

    2015年4月29日 7:39
  • 你好:

    我没有重现过这个问题,但是搜索了一下,发现通过Try-Catch确实无法捕获到这个异常,你可以尝试一下通过AppDomain.UnhandledException事件来从AppDomain角度捕获异常。

    SerialPort底层是调用的Windows API接口来传输数据的,抛出这个异常的原因是当设备被拔出之后SerialPort会Dispose, SerialPort内部的SerialStream的实现有些问题,SerialPort调用Windows API初始化的时候忽略了一个名为"fAbortOnError"的标志位,导致SerialStream在Dispose方法中在某些情况下抛出异常无法捕获。

    可以尝试一下这篇文章中的解决办法(代码中封装了一个类,在初始化SerialPort之前调用该类中的Execute方法):

    // Copyright 2010-2014 Zach Saw
    // 
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    // 
    //     http://www.apache.org/licenses/LICENSE-2.0
    // 
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    
    using System;
    using System.IO;
    using System.IO.Ports;
    using System.Runtime.InteropServices;
    using System.Text;
    using Microsoft.Win32.SafeHandles;
    
    namespace SerialPortTester
    {
        public class SerialPortFixer : IDisposable
        {
            public static void Execute(string portName)
            {
                using (new SerialPortFixer(portName))
                {
                }
            }
            #region IDisposable Members
    
            public void Dispose()
            {
                if (m_Handle != null)
                {
                    m_Handle.Close();
                    m_Handle = null;
                }
            }
    
            #endregion
    
            #region Implementation
    
            private const int DcbFlagAbortOnError = 14;
            private const int CommStateRetries = 10;
            private SafeFileHandle m_Handle;
    
            private SerialPortFixer(string portName)
            {
                const int dwFlagsAndAttributes = 0x40000000;
                const int dwAccess = unchecked((int)0xC0000000);
    
                if ((portName == null) || !portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase))
                {
                    throw new ArgumentException("Invalid Serial Port", "portName");
                }
                SafeFileHandle hFile = CreateFile(@"\\.\" + portName, dwAccess, 0, IntPtr.Zero, 3, dwFlagsAndAttributes,
                                                  IntPtr.Zero);
                if (hFile.IsInvalid)
                {
                    WinIoError();
                }
                try
                {
                    int fileType = GetFileType(hFile);
                    if ((fileType != 2) && (fileType != 0))
                    {
                        throw new ArgumentException("Invalid Serial Port", "portName");
                    }
                    m_Handle = hFile;
                    InitializeDcb();
                }
                catch
                {
                    hFile.Close();
                    m_Handle = null;
                    throw;
                }
            }
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId,
                                                    StringBuilder lpBuffer, int nSize, IntPtr arguments);
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool GetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool SetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool ClearCommError(SafeFileHandle hFile, ref int lpErrors, ref Comstat lpStat);
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
                                                            IntPtr securityAttrs, int dwCreationDisposition,
                                                            int dwFlagsAndAttributes, IntPtr hTemplateFile);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            private static extern int GetFileType(SafeFileHandle hFile);
    
            private void InitializeDcb()
            {
                Dcb dcb = new Dcb();
                GetCommStateNative(ref dcb);
                dcb.Flags &= ~(1u << DcbFlagAbortOnError);
                SetCommStateNative(ref dcb);
            }
    
            private static string GetMessage(int errorCode)
            {
                StringBuilder lpBuffer = new StringBuilder(0x200);
                if (
                    FormatMessage(0x3200, new HandleRef(null, IntPtr.Zero), errorCode, 0, lpBuffer, lpBuffer.Capacity,
                                  IntPtr.Zero) != 0)
                {
                    return lpBuffer.ToString();
                }
                return "Unknown Error";
            }
    
            private static int MakeHrFromErrorCode(int errorCode)
            {
                return (int)(0x80070000 | (uint)errorCode);
            }
    
            private static void WinIoError()
            {
                int errorCode = Marshal.GetLastWin32Error();
                throw new IOException(GetMessage(errorCode), MakeHrFromErrorCode(errorCode));
            }
    
            private void GetCommStateNative(ref Dcb lpDcb)
            {
                int commErrors = 0;
                Comstat comStat = new Comstat();
    
                for (int i = 0; i < CommStateRetries; i++)
                {
                    if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
                    {
                        WinIoError();
                    }
                    if (GetCommState(m_Handle, ref lpDcb))
                    {
                        break;
                    }
                    if (i == CommStateRetries - 1)
                    {
                        WinIoError();
                    }
                }
            }
    
            private void SetCommStateNative(ref Dcb lpDcb)
            {
                int commErrors = 0;
                Comstat comStat = new Comstat();
    
                for (int i = 0; i < CommStateRetries; i++)
                {
                    if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
                    {
                        WinIoError();
                    }
                    if (SetCommState(m_Handle, ref lpDcb))
                    {
                        break;
                    }
                    if (i == CommStateRetries - 1)
                    {
                        WinIoError();
                    }
                }
            }
    
            #region Nested type: COMSTAT
    
            [StructLayout(LayoutKind.Sequential)]
            private struct Comstat
            {
                public readonly uint Flags;
                public readonly uint cbInQue;
                public readonly uint cbOutQue;
            }
    
            #endregion
    
            #region Nested type: DCB
    
            [StructLayout(LayoutKind.Sequential)]
            private struct Dcb
            {
                public readonly uint DCBlength;
                public readonly uint BaudRate;
                public uint Flags;
                public readonly ushort wReserved;
                public readonly ushort XonLim;
                public readonly ushort XoffLim;
                public readonly byte ByteSize;
                public readonly byte Parity;
                public readonly byte StopBits;
                public readonly byte XonChar;
                public readonly byte XoffChar;
                public readonly byte ErrorChar;
                public readonly byte EofChar;
                public readonly byte EvtChar;
                public readonly ushort wReserved1;
            }
    
            #endregion
    
            #endregion
        }
    
        internal class Program
        {
            private static void Main(string[] args)
            {
                SerialPortFixer.Execute("COM1");
                using (SerialPort port = new SerialPort("COM1"))
                {
                    port.Write("test");
                }
            }
        }
    }
    


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2015年5月4日 10:02
    版主