弱弱地以为,可以试试DefWndProc(ref Message m)方法来监测插入或拔出PC的硬件,如果是你的设备,你就把它映射的COM口关掉。 不确定的是,你插拔你的设备时,DefWndProc(ref Message m)方法是否能监测到。以下代码试试能否监测到你的设备:(如果插拔设备能,弹出了MessageBox,就说明能监测到;如果没弹出,就说明监测不到。) 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;namespace TorquePcSoftware { public partial class Form1 : Form { public Form1() { InitializeComponent(); } int i = 0; protected override void DefWndProc(ref Message m) { if (m.Msg == 0x0219) { i++; Console.WriteLine(i.ToString() + ": " + m.ToString()); MessageBox.Show(i.ToString() + ": " + m.ToString()); //deviceChangeDeal(); } base.DefWndProc(ref m); } } }第一次回答帖子,希望有帮助
一些解决方案都包括部分或者全部使用WinAPI。
我刚才试了下添加timer控件不断检测com口,然后或者关闭,或者重新赋值为其他com口,或者dispose,还是解决不了问题,软件关闭时仍然报错
啊啊啊啊啊啊啊啊啊啊啊啊啊,555555,还以为这个方法可行呢,这下彻底没招了啊。巨期待高手。。
另外,我就纳闷了,使用timer控件监测串口,发现没了映射com口后,serialport就重新改变了,软件代码与映射端口毛关系没有了,怎么关闭还会报错?不是修改后与映射的那个com口都没有关系了吗
想不通啊想不通,@高手,嘿嘿嘿
另外,三楼的哥们,可不可以在关闭的时候禁止软件访问串口?谢谢啦。。
不确定的是,你插拔你的设备时,DefWndProc(ref Message m)方法是否能监测到。以下代码试试能否监测到你的设备:(如果插拔设备能,弹出了MessageBox,就说明能监测到;如果没弹出,就说明监测不到。)
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;namespace TorquePcSoftware
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} int i = 0;
protected override void DefWndProc(ref Message m)
{
if (m.Msg == 0x0219)
{
i++;
Console.WriteLine(i.ToString() + ": " + m.ToString());
MessageBox.Show(i.ToString() + ": " + m.ToString()); //deviceChangeDeal();
} base.DefWndProc(ref m);
}
}
}第一次回答帖子,希望有帮助
try { serialPort1.BaseStream.Close(); }
catch (Exception ex) { MessageBox.Show(ex.ToString()); }
这样就不会再抛出IOException了,亲测可行。
所有。果断用timer。没错USB监控平台。路过。
今天上午用timer试了,还是那个问题,解决不了,详述在四楼。
求大侠指教解决方法
解决方法很简单把对应的服务重起一下就好了。
程序报错是正常的直接屏蔽掉。
usb转串口。后台有个服务在运行。
就算你拔掉了设备后台服务并不是立即或根本不会检测到。
你的程序发的包只是发到了这个后台服务。再由这个服务转发。
这个后台的服务并不健壮。并不会每时每刻都会去轮询设备还在不在。
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
}
}源码来自blogpost地址就算了。在
serialPort.Open();
前加一句
SerialPortTester.SerialPortFixer.Execute(Settings.Default.PortName);
顺带我的系统是win7 64位,USB-串口是PL2303,框架版本是4.0 Client Profile
虽然不能解决你的报错根源问题但报错还是不会提示的
这个报错。估计是释放资源报错。也可能是线程出了问题报错。总之。如果多线程没管理好的话。或者辅助线程接触到UI线程也会可能报类似的错误
这个是原理和结构问题试试看能不能解决眼前的问题
iyomumx,可以提供你的QQ吗,请教一下,这问题真的困着我了
注意∶报错时不会定位到如何一行代码,晕死,这样的不错第一次碰到,好头疼
软件都做完了,就剩下这么个问题困扰我,叫同事也看了,也是束手无策,只是建议我不用serialport控件,改用api函数实现,晕,那个我也是差不多门外汉,工作量也大,而且能不能解决这样的问题也暂不知道。。
求助大神,再次拜谢大神们,请支支招,万分感谢。。
姑且试试吧 网上现成源码 无非替换下
不过 有可能一样会报错还有一个办法是在串口关闭前 重启后台服务
foreach (ServiceController service in slist)
{
if (service.ServiceName == "服务名")
{
service.Stop();
service.Start();
}
}
第一个标注红色地方:猜测你的程序不会报错是因为你catch住不处理,但是还是一直在发送数据。第二个标注红色地方:你的程序界面关闭,但是还在运行。这说明你的多线程应该没有 IsBackground = true; 导致程序退出时没有关闭线程。你试着把 Thread 的 IsBackground 设为 true 看看。
下载:
http://115.com/file/e704quat#或者:http://163.fm/IFzgf2L 提取码:LucGDi3Q (163邮箱的网盘)
问题程序源代码:
private void Form1_Load(object sender, EventArgs e)
{
serialPort1.Close();
serialPort1.BaudRate = 9600;
serialPort1.DataBits = 8;
serialPort1.StopBits = StopBits.One;
serialPort1.Parity = Parity.None;
serialPort1.PortName = "COM4"; //USB 转串口映射的串口号为com4
serialPort1.Open();
} private void button1_Click(object sender, EventArgs e) //发送数据到设备
{
byte[] bytWrite = new byte[] { 0xe1, 0xee, 0xee, 0xee,0x30 }; //byte数组
try
{
if (!serialPort1.IsOpen)
serialPort1.Open();
serialPort1.Write(bytWrite, 0, bytWrite.Length);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
serialPort1.Close();
serialPort1.Dispose();
}
} private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) //从串口接收数据
{
int n = serialPort1.BytesToRead;
byte[] buf = new byte[n];
serialPort1.Read(buf, 0, n);
Console.WriteLine("当前串口收到数据: "+BitConverter.ToString(buf));
} private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
serialPort1.Close(); //窗体关闭前关闭串口
serialPort1.Dispose(); //窗体关闭前释放串口
}另外,我发现了用很多网络上下载的串口调试程序进行调试的时候,很多串口调试软件也存在这个问题,当USB拔掉后,关闭软件出错,而且有些软件根本就关不掉,一直弹出出错提示,看来这个问题还是普遍存在啊,相当多的程序员在写串口程序的时候,都忽略了这个问题。因为平常的情况下,com口在软件运行过程中都是一直存在的,刚好这次我写程序遇到usb转串口这样的情况,调试软件时才发现了这个问题。呵呵
但是,也不是所有的串口调试软件在这种情况下都会出错,现目前我发现一个叫做UartAssist.exe的串口调试软件在遇到这种情况的时候不会出错,关闭软件一切正常,呵呵,看来这个问题还是能够避免的,就是我才疏学浅还没有掌握到,所以特地再来此顶贴,希望高手们都来看看,不要忽略了这个问题。
小弟不胜感谢!!!
这个方法是不行的,已经试了。软件故障现象是:拔掉usb接口后,即使在关闭软件之前再次插上usb线缆,关闭时也会报错。总之,软件运行过程中只要有拔掉usb线缆,之后任何情况软件关闭都会出错,也就是说即使那个com口还存在,依然报错。
痛苦,现在还没有找到解决方法。
AppDomain.Current.UnhandledException 事件
注册处理程序,在这里应该可以捕捉到错误,并能通过设置UnhandledExceptionEventArgs.ExitApplication来保证应用程序正常退出。
我们经常用串口一样的毛病,串口故障了,软件反应的是数据没获得。
你去用软件解决这个问题,为什么不保持你的串口不变动呢?USB转串口我们都是笔记本临时调试用,就这还有时候会罢工呢,不用说用到成品软件上了。
==================
拔掉USB不会出错是因为串口没有数据,不会触发DataReceived事件,此过程中没有对端口进行操作。
但是关闭窗体的时候,是要释放串口资源的,于是就出错了。没想到什么好的办法,试试在关闭窗口的时候直接退出程序“Environment.Exit(0);"
这样在执行close的时候一定会出错
测试过吗,不要靠猜想