protected IntPtr WindowProcHandler(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            MessageType msgType = (MessageType)msg;

            Console.WriteLine(msgType);

            if (msg == (int)MessageType.WM_DEVICECHANGE)
            {
                DeviceBroadcastType dbt = (DeviceBroadcastType)wParam.ToInt32();
                Console.WriteLine(dbt);

                switch (dbt)
                {
                case DeviceBroadcastType.DBT_DEVICEARRIVAL:
                case DeviceBroadcastType.DBT_DEVICEREMOVECOMPLETE:
                    Console.WriteLine(dbt == DeviceBroadcastType.DBT_DEVICEARRIVAL ? "Device Arrival" : "Device Move Complete");

                    DEV_BROADCAST_HDR hdr = Marshal.PtrToStructure <DEV_BROADCAST_HDR>(lParam);
                    Console.WriteLine("{0}", hdr);

                    if (hdr.dbch_devicetype == DeviceType.DBT_DEVTYP_PORT)
                    {
                        DEV_BROADCAST_PORT port = Marshal.PtrToStructure <DEV_BROADCAST_PORT>(lParam);
                        Console.WriteLine(port);
                    }
                    if (hdr.dbch_devicetype == DeviceType.DBT_DEVTYP_VOLUME)
                    {
                        DEV_BROADCAST_VOLUME volume = Marshal.PtrToStructure <DEV_BROADCAST_VOLUME>(lParam);
                        Console.WriteLine(volume);
                    }
                    break;

                default:
                    break;
                }

                handled = true;
            }

            return(IntPtr.Zero);
        }
        /// <summary>
        /// 串口设备热插拔自动重新连接
        /// <para>使用 HwndSource Hook Window Message #WM_DEVICECHANGE 事件监听模式</para>
        /// </summary>
        /// <param name="serialPort"></param>
        /// <param name="window">IsLoaded 为 True 的窗口对象</param>
        public static void AutoReconnection(this SerialPort serialPort, System.Windows.Window window)
        {
            if (serialPort == null || window == null)
            {
                throw new ArgumentException("参数不能为空");
            }
            if (!window.IsLoaded)
            {
                throw new InvalidOperationException("Window 对象 IsLoaded 为 True 时才能获取窗口句柄");
            }
            SpaceCGUtils.Log.InfoFormat("HwndSource Hook Window Message #WM_DEVICECHANGE Event Listen SerialPort Name:{0}", serialPort.PortName);

            HwndSource hwndSource = HwndSource.FromVisual(window) as HwndSource;

            if (hwndSource != null)
            {
                hwndSource.AddHook((IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) =>
                {
                    MessageType mt = (MessageType)msg;
                    if (mt != MessageType.WM_DEVICECHANGE)
                    {
                        return(IntPtr.Zero);
                    }

                    DeviceBroadcastType dbt = (DeviceBroadcastType)wParam.ToInt32();
                    if (dbt == DeviceBroadcastType.DBT_DEVICEARRIVAL || dbt == DeviceBroadcastType.DBT_DEVICEREMOVECOMPLETE)
                    {
                        DEV_BROADCAST_HDR hdr = (DEV_BROADCAST_HDR)Marshal.PtrToStructure(lParam, typeof(DEV_BROADCAST_HDR));
                        if (hdr.dbch_devicetype != DeviceType.DBT_DEVTYP_PORT)
                        {
                            return(IntPtr.Zero);
                        }

                        DEV_BROADCAST_PORT port = (DEV_BROADCAST_PORT)Marshal.PtrToStructure(lParam, typeof(DEV_BROADCAST_PORT));
                        if (port.dbcp_name.ToUpper() != serialPort.PortName.ToUpper())
                        {
                            return(IntPtr.Zero);
                        }

                        if (dbt == DeviceBroadcastType.DBT_DEVICEARRIVAL)
                        {
                            if (!serialPort.IsOpen)
                            {
                                serialPort.Open();
                            }
                            SpaceCGUtils.Log.InfoFormat("Device Arrival SerialPort Name:{0}", port.dbcp_name);
                        }
                        if (dbt == DeviceBroadcastType.DBT_DEVICEREMOVECOMPLETE)
                        {
                            if (serialPort.IsOpen)
                            {
                                serialPort.Close();
                            }
                            SpaceCGUtils.Log.ErrorFormat("Device Remove Complete SerialPort Name:{0}", port.dbcp_name);
                        }

                        handled = true;
                    }

                    return(IntPtr.Zero);
                });
            }

            window.Closing += (s, e) =>
            {
                hwndSource?.Dispose();
                hwndSource = null;
            };
        }