You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中通过P/Invoke调用CM_Register_Notification函数?

在C#中用P/Invoke实现设备变化通知

要在C#里调用CM_Register_Notification实现设备增减通知,核心是先映射C++原生类型到C#,再通过委托处理回调。以下是关键实现步骤:

1. 定义对应枚举与结构体

先把Windows API里的相关类型转换成C#可识别的结构:

// 通知过滤器类型枚举
public enum CM_NOTIFY_FILTER_TYPE
{
    CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE = 0,
    CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE = 1,
    CM_NOTIFY_FILTER_TYPE_DEVICEINSTANCE = 2
}

// 通知过滤器头部结构
[StructLayout(LayoutKind.Sequential)]
public struct CM_NOTIFY_FILTER_HEADER
{
    public uint cbSize;
    public CM_NOTIFY_FILTER_TYPE FilterType;
    public uint Reserved;
}

// 设备实例过滤器结构
[StructLayout(LayoutKind.Sequential)]
public struct CM_NOTIFY_FILTER
{
    public CM_NOTIFY_FILTER_HEADER Header;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string DeviceInstanceId;
}

2. 声明P/Invoke函数与回调委托

// 设备通知回调委托
public delegate void CM_NOTIFY_CALLBACK(
    IntPtr hNotify,
    IntPtr Context,
    uint NotificationType,
    IntPtr NotificationData,
    uint NotificationDataSize);

// 注册设备通知的P/Invoke签名
[DllImport("cfgmgr32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CM_Register_Notification(
    ref CM_NOTIFY_FILTER pFilter,
    CM_NOTIFY_CALLBACK pCallback,
    IntPtr Context,
    out uint pdwNotifyCookie);

// 注销设备通知的P/Invoke签名
[DllImport("cfgmgr32.dll", SetLastError = true)]
public static extern int CM_Unregister_Notification(uint dwNotifyCookie);

3. 注册通知并处理回调

因为你只需要感知设备变化,回调里可以简化处理,只触发自定义逻辑即可:

private uint _notifyCookie;

// 注册全局设备变化通知
public void StartDeviceMonitoring()
{
    var filter = new CM_NOTIFY_FILTER();
    filter.Header.cbSize = (uint)Marshal.SizeOf(typeof(CM_NOTIFY_FILTER));
    filter.Header.FilterType = CM_NOTIFY_FILTER_TYPE.CM_NOTIFY_FILTER_TYPE_DEVICEINSTANCE;
    filter.DeviceInstanceId = ""; // 空字符串表示监听所有设备实例

    if (CM_Register_Notification(ref filter, OnDeviceChanged, IntPtr.Zero, out _notifyCookie) == IntPtr.Zero)
    {
        // 注册失败,可通过Marshal.GetLastWin32Error()获取错误码排查
    }
}

// 设备变化回调
private void OnDeviceChanged(IntPtr hNotify, IntPtr Context, uint NotificationType, IntPtr NotificationData, uint NotificationDataSize)
{
    // 仅触发设备变化提示,后续自行确认具体变化
    Console.WriteLine("设备状态已发生变化");
}

// 停止监听时注销通知,避免资源泄漏
public void StopDeviceMonitoring()
{
    CM_Unregister_Notification(_notifyCookie);
}

注意事项

  • 结构体的内存布局必须与C++原生定义一致,通过StructLayout保证顺序正确
  • 程序退出或不再需要监听时,务必调用CM_Unregister_Notification释放资源
  • 若需监听特定类型设备,可修改CM_NOTIFY_FILTER参数(比如指定设备接口GUID)

内容的提问来源于stack exchange,提问作者ispiro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 14:17:41