<small id='7pasc'></small><noframes id='7pasc'>

    • <bdo id='7pasc'></bdo><ul id='7pasc'></ul>
      <tfoot id='7pasc'></tfoot><legend id='7pasc'><style id='7pasc'><dir id='7pasc'><q id='7pasc'></q></dir></style></legend>

    1. <i id='7pasc'><tr id='7pasc'><dt id='7pasc'><q id='7pasc'><span id='7pasc'><b id='7pasc'><form id='7pasc'><ins id='7pasc'></ins><ul id='7pasc'></ul><sub id='7pasc'></sub></form><legend id='7pasc'></legend><bdo id='7pasc'><pre id='7pasc'><center id='7pasc'></center></pre></bdo></b><th id='7pasc'></th></span></q></dt></tr></i><div id='7pasc'><tfoot id='7pasc'></tfoot><dl id='7pasc'><fieldset id='7pasc'></fieldset></dl></div>
    2. 检测串口插入/移除

      Detect serial port insertion/removal(检测串口插入/移除)

        <tbody id='vTLmI'></tbody>
    3. <tfoot id='vTLmI'></tfoot><legend id='vTLmI'><style id='vTLmI'><dir id='vTLmI'><q id='vTLmI'></q></dir></style></legend>
    4. <small id='vTLmI'></small><noframes id='vTLmI'>

        <i id='vTLmI'><tr id='vTLmI'><dt id='vTLmI'><q id='vTLmI'><span id='vTLmI'><b id='vTLmI'><form id='vTLmI'><ins id='vTLmI'></ins><ul id='vTLmI'></ul><sub id='vTLmI'></sub></form><legend id='vTLmI'></legend><bdo id='vTLmI'><pre id='vTLmI'><center id='vTLmI'></center></pre></bdo></b><th id='vTLmI'></th></span></q></dt></tr></i><div id='vTLmI'><tfoot id='vTLmI'></tfoot><dl id='vTLmI'><fieldset id='vTLmI'></fieldset></dl></div>

            • <bdo id='vTLmI'></bdo><ul id='vTLmI'></ul>
                本文介绍了检测串口插入/移除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                问题描述

                我正在连接一个可以随时插入或移除的 USB 转串口.我发现我可以使用 WMI (特别是使用 WMI 代码创建器) 查询 PC 中的设备更改.

                I am interfacing with a USB-to-serial port that can be inserted or removed at any time. I've found that I can use WMI (particularly with the use of WMI Code Creator) to query for device changes in the PC.

                在下面生成的代码段中,订阅了 Win32_DeviceChangeEvent.但是,此事件不会显示 哪个设备(例如 USB、串行端口等)导致了该事件.有没有办法只在插入或移除串行端口时接收通知?

                In the generated snippet below, the Win32_DeviceChangeEvent is subscribed to. However, this event doesn't reveal which device (e.g. USB, serial port, etc) caused the event. Is there a way to only receive notifications when serial ports are inserted or removed?

                澄清一下,代码的重点不是检测串口的开启/关闭,而是检测是否有端口已添加到计算机或之前的端口已删除.

                To clarify, the point of the code is not to detect opening/closing of serial ports, it is to detect whether a new port has been added to the machine or a previous port was removed.

                using System;
                using System.Management;
                using System.Windows.Forms;
                
                namespace WMISample
                {
                    public class WMIReceiveEvent
                    {
                        public WMIReceiveEvent()
                        {
                            try
                            {
                                WqlEventQuery query = new WqlEventQuery(
                                    "SELECT * FROM Win32_DeviceChangeEvent");
                
                                ManagementEventWatcher watcher = new ManagementEventWatcher(query);
                                Console.WriteLine("Waiting for an event...");
                
                                watcher.EventArrived += 
                                    new EventArrivedEventHandler(
                                    HandleEvent);
                
                                // Start listening for events
                                watcher.Start();
                
                                // Do something while waiting for events
                                System.Threading.Thread.Sleep(10000);
                
                                // Stop listening for events
                                watcher.Stop();
                                return;
                            }
                            catch(ManagementException err)
                            {
                                MessageBox.Show("An error occurred while trying to receive an event: " + err.Message);
                            }
                        }
                
                        private void HandleEvent(object sender,
                            EventArrivedEventArgs e)
                        {
                            Console.WriteLine("Win32_DeviceChangeEvent event occurred.");
                        }
                
                        public static void Main()
                        {
                            WMIReceiveEvent receiveEvent = new WMIReceiveEvent();
                            return;
                        }
                
                    }
                }
                

                推荐答案

                我最终使用 WMI 和 @Hans 的建议来检查哪些串行端口是新的/缺少的.

                I ended up using WMI and @Hans' advice to check what serial ports are new/missing.

                using System;
                using System.Collections.Generic;
                using System.Linq;
                using System.Diagnostics.Contracts;
                using System.IO.Ports;
                using System.Management;
                
                public static class SerialPortService
                {
                    private static SerialPort _serialPort;
                
                    private static string[] _serialPorts;
                
                    private static ManagementEventWatcher arrival;
                
                    private static ManagementEventWatcher removal;
                
                    static SerialPortService()
                    {
                        _serialPorts = GetAvailableSerialPorts();
                        MonitorDeviceChanges();
                    }
                
                    /// <summary>
                    /// If this method isn't called, an InvalidComObjectException will be thrown (like below):
                    /// System.Runtime.InteropServices.InvalidComObjectException was unhandled
                    ///Message=COM object that has been separated from its underlying RCW cannot be used.
                    ///Source=mscorlib
                    ///StackTrace:
                    ///     at System.StubHelpers.StubHelpers.StubRegisterRCW(Object pThis, IntPtr pThread)
                    ///     at System.Management.IWbemServices.CancelAsyncCall_(IWbemObjectSink pSink)
                    ///     at System.Management.SinkForEventQuery.Cancel()
                    ///     at System.Management.ManagementEventWatcher.Stop()
                    ///     at System.Management.ManagementEventWatcher.Finalize()
                    ///InnerException: 
                    /// </summary>
                    public static void CleanUp()
                    {
                        arrival.Stop();
                        removal.Stop();
                    }
                
                    public static event EventHandler<PortsChangedArgs> PortsChanged;
                
                    private static void MonitorDeviceChanges()
                    {
                        try
                        {
                            var deviceArrivalQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
                            var deviceRemovalQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3");
                
                            arrival = new ManagementEventWatcher(deviceArrivalQuery);
                            removal = new ManagementEventWatcher(deviceRemovalQuery);
                
                            arrival.EventArrived += (o, args) => RaisePortsChangedIfNecessary(EventType.Insertion);
                            removal.EventArrived += (sender, eventArgs) => RaisePortsChangedIfNecessary(EventType.Removal);
                
                            // Start listening for events
                            arrival.Start();
                            removal.Start();
                        }
                        catch (ManagementException err)
                        {
                
                        }
                    }
                
                    private static void RaisePortsChangedIfNecessary(EventType eventType)
                    {
                        lock (_serialPorts)
                        {
                            var availableSerialPorts = GetAvailableSerialPorts();
                            if (!_serialPorts.SequenceEqual(availableSerialPorts))
                            {
                                _serialPorts = availableSerialPorts;
                                PortsChanged.Raise(null, new PortsChangedArgs(eventType, _serialPorts));
                            }
                        }
                    }
                
                    public static string[] GetAvailableSerialPorts()
                    {
                        return SerialPort.GetPortNames();
                    }
                }
                
                public enum EventType
                {
                    Insertion,
                    Removal,
                }
                
                public class PortsChangedArgs : EventArgs
                {
                    private readonly EventType _eventType;
                
                    private readonly string[] _serialPorts;
                
                    public PortsChangedArgs(EventType eventType, string[] serialPorts)
                    {
                        _eventType = eventType;
                        _serialPorts = serialPorts;
                    }
                
                    public string[] SerialPorts
                    {
                        get
                        {
                            return _serialPorts;
                        }
                    }
                
                    public EventType EventType
                    {
                        get
                        {
                            return _eventType;
                        }
                    }
                }
                

                MonitorDeviceChanges 方法实际上可以查看所有设备更改(如设备管理器),但检查串行端口允许我们仅在更改时引发事件.

                The MonitorDeviceChanges method actually sees all device changes (like Device Manager), but checking the serial ports allows us to only raise an event when those have changed.

                要使用代码,只需订阅 PortsChanged 事件,例如SerialPortService.PortsChanged += (sender1, changedArgs) =>DoSomethingSerial(changedArgs.SerialPorts);

                To use the code, simply subscribe to the PortsChanged event, e.g. SerialPortService.PortsChanged += (sender1, changedArgs) => DoSomethingSerial(changedArgs.SerialPorts);

                哦,.Raise 方法只是我在某处找到的扩展方法:

                Oh, and the .Raise method is just an extension method I picked up somewhere:

                /// <summary>
                /// Tell subscribers, if any, that this event has been raised.
                /// </summary>
                /// <typeparam name="T"></typeparam>
                /// <param name="handler">The generic event handler</param>
                /// <param name="sender">this or null, usually</param>
                /// <param name="args">Whatever you want sent</param>
                public static void Raise<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs
                {
                    // Copy to temp var to be thread-safe (taken from C# 3.0 Cookbook - don't know if it's true)
                    EventHandler<T> copy = handler;
                    if (copy != null)
                    {
                        copy(sender, args);
                    }
                }
                

                这篇关于检测串口插入/移除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

                相关文档推荐

                Multicast delegate weird behavior in C#?(C# 中的多播委托奇怪行为?)
                How to store delegates in a List(如何将代表存储在列表中)
                Delegate.CreateDelegate() and generics: Error binding to target method(Delegate.CreateDelegate() 和泛型:错误绑定到目标方法)
                CreateDelegate with unknown types(具有未知类型的 CreateDelegate)
                Does Funclt;Tgt;.BeginInvoke use the ThreadPool?(Funclt;Tgt;.BeginInvoke 使用线程池吗?)
                How to create a delegate to an instance method with a null target?(如何为具有空目标的实例方法创建委托?)
                <legend id='Ps1ph'><style id='Ps1ph'><dir id='Ps1ph'><q id='Ps1ph'></q></dir></style></legend>

                <i id='Ps1ph'><tr id='Ps1ph'><dt id='Ps1ph'><q id='Ps1ph'><span id='Ps1ph'><b id='Ps1ph'><form id='Ps1ph'><ins id='Ps1ph'></ins><ul id='Ps1ph'></ul><sub id='Ps1ph'></sub></form><legend id='Ps1ph'></legend><bdo id='Ps1ph'><pre id='Ps1ph'><center id='Ps1ph'></center></pre></bdo></b><th id='Ps1ph'></th></span></q></dt></tr></i><div id='Ps1ph'><tfoot id='Ps1ph'></tfoot><dl id='Ps1ph'><fieldset id='Ps1ph'></fieldset></dl></div>

                    <small id='Ps1ph'></small><noframes id='Ps1ph'>

                        <tbody id='Ps1ph'></tbody>
                      • <tfoot id='Ps1ph'></tfoot>
                        • <bdo id='Ps1ph'></bdo><ul id='Ps1ph'></ul>