Hyz Yuzhou
Hyz Yuzhou

Reputation: 83

C# WPF ManagementObjectSearcher.Get() throws an exception

I need to detect USB device changed event and update the changes to WPF Window. Here is my code.

    public MainWindow()
    {
        InitializeComponent();
        SourceInitialized += (sender, e) =>
        {
            HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
            source.AddHook(WndProc);
        };
    }

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == 0x219)  // Device Changed
        {
            UpdateSerialPortDict();
        }
        return IntPtr.Zero;
    }

    private void UpdateSerialPortDict()
    {
        System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(@"^[\S\s]+\((COM([0-9])+)\)$");
        using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity"))
        {
            foreach (ManagementObject obj in searcher.Get())
            {
                if ((string)obj["PNPClass"] == "Ports")
                {
                    string key = obj["Name"] as string;
                    var mat = reg.Match(key);
                    if (mat.Success)
                    {
                        var val = mat.Groups[1].Value;
                        _comDictionary.Add(key, val);
                    }
                }
            }
        }
    }

The program will crash when calling searcher.Get(). If I use a Button to trigger UpdateSerialPortDict(), it works fine. But I would it update automatically by detecting device changed event.

Upvotes: 1

Views: 1149

Answers (1)

mm8
mm8

Reputation: 169420

Try to use the dispatcher:

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    if (msg == 0x219)  // Device Changed
    {
        Dispatcher.BeginInvoke(new Action(() => UpdateSerialPortDict()),
            System.Windows.Threading.DispatcherPriority.Background);
    }
    return IntPtr.Zero;
}

Upvotes: 2

Related Questions