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

无法调用CsWin32生成的SetupDiGetDeviceRegistryProperty正确重载

问题

测试C#/Win32项目时,试图通过自动生成的PInvoke包装器调用Win32 Setup API的SetupDiGetDeviceRegistryProperty函数,但编译器始终匹配错误的重载,导致编译失败。

生成的两个SetupDiGetDeviceRegistryProperty重载如下(希望调用第一个“易用”重载):

[SupportedOSPlatform("windows5.0")]
internal static unsafe winmdroot.Foundation.BOOL SetupDiGetDeviceRegistryProperty(SafeHandle DeviceInfoSet, in winmdroot.Devices.DeviceAndDriverInstallation.SP_DEVINFO_DATA DeviceInfoData, winmdroot.Devices.DeviceAndDriverInstallation.SETUP_DI_REGISTRY_PROPERTY Property, uint* PropertyRegDataType, Span<byte> PropertyBuffer, uint* RequiredSize)
{
  // 生成代码省略,目标调用此重载
}

[DllImport("SETUPAPI.dll", ExactSpelling = true, EntryPoint = "SetupDiGetDeviceRegistryPropertyW", SetLastError = true),DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
[SupportedOSPlatform("windows5.0")]
internal static extern unsafe winmdroot.Foundation.BOOL SetupDiGetDeviceRegistryProperty(winmdroot.Devices.DeviceAndDriverInstallation.HDEVINFO DeviceInfoSet, winmdroot.Devices.DeviceAndDriverInstallation.SP_DEVINFO_DATA* DeviceInfoData, winmdroot.Devices.DeviceAndDriverInstallation.SETUP_DI_REGISTRY_PROPERTY Property, [Optional] uint* PropertyRegDataType, [Optional] byte* PropertyBuffer, uint PropertyBufferSize, [Optional] uint* RequiredSize);

测试代码中步骤3的调用始终匹配第二个重载,编译报错:

internal unsafe bool TryGetUsbDeviceRegistryString(
    string                     deviceInstance,
    SETUP_DI_REGISTRY_PROPERTY prop,
    out string                 name)
{
    name = string.Empty;

    var guidDevinterfaceUsbDevice =
        new Guid("{A5DCBF10-6530-11D2-901F-00C04FB951ED}");

    SETUP_DI_GET_CLASS_DEVS_FLAGS flags =
        SETUP_DI_GET_CLASS_DEVS_FLAGS.DIGCF_DEVICEINTERFACE | SETUP_DI_GET_CLASS_DEVS_FLAGS.DIGCF_PRESENT;

    // 获取DeviceInfoList的SafeHandle
    SetupDiDestroyDeviceInfoListSafeHandle info =
        PInvoke.SetupDiGetClassDevs(guidDevinterfaceUsbDevice, deviceInstance, HWND.Null, flags);

    uint dwSize = 0;
    var did = new SP_DEVINFO_DATA{ cbSize = (uint)Marshal.SizeOf<SP_DEVINFO_DATA>()};
    uint memberIndex = 0;
    uint propType = 0;

     Span<byte> buffer = stackalloc byte[1];

    // 遍历设备
    while (PInvoke.SetupDiEnumDeviceInfo(info, memberIndex, ref did))
    {
        // 尝试获取注册表属性所需的缓冲区大小
        // *** 编译时匹配了错误的重载 ***
        PInvoke.SetupDiGetDeviceRegistryProperty(info, did, prop, ref propType, buffer, ref dwSize);

        // 后续代码省略...

        memberIndex++;
    }
    return false;
}

编译错误信息:

Build started at 12:20 PM...
1>------ Build started: Project: TestPInvoke, Configuration: Debug x64 ------
1>C:\Users\joe\source\repos\TestPInvoke\TestPInvoke\DeviceInfoSet.cs(39,50,39,54): error CS1503: Argument 1: cannot convert from 'Windows.Win32.SetupDiDestroyDeviceInfoListSafeHandle' to 'Windows.Win32.Devices.DeviceAndDriverInstallation.HDEVINFO'
1>C:\Users\joe\source\repos\TestPInvoke\TestPInvoke\DeviceInfoSet.cs(39,74,39,82): error CS1615: Argument 4 may not be passed with the 'ref' keyword
1>C:\Users\joe\source\repos\TestPInvoke\TestPInvoke\DeviceInfoSet.cs(39,90,39,96): error CS1503: Argument 6: cannot convert from 'System.Span<byte>' to 'uint'
1>C:\Users\joe\source\repos\TestPInvoke\TestPInvoke\DeviceInfoSet.cs(39,102,39,108): error CS1615: Argument 7 may not be passed with the 'ref' keyword
1>Done building project "TestPInvoke.csproj" -- FAILED.
Build has been canceled.
========== Elapsed 00.993 seconds ==========
解决方法

问题核心是你传递的参数与目标重载的签名不匹配,导致编译器无法定位到第一个“易用”重载,转而匹配第二个原始重载。修正参数即可解决:

  1. 指针参数传递方式错误:目标重载的第4个参数(PropertyRegDataType)和第6个参数(RequiredSize)类型是uint*,但你使用了ref关键字传递,不符合签名要求。在unsafe上下文里,应该用&运算符获取变量的指针。
  2. 第二个参数优化(可选):目标重载的第二个参数是in SP_DEVINFO_DATA(只读引用),直接传递did虽然可以,但加上in关键字更贴合签名语义,避免不必要的值拷贝。

修正后的调用代码:

PInvoke.SetupDiGetDeviceRegistryProperty(info, in did, prop, &propType, buffer, &dwSize);

这样编译器就能正确匹配到第一个“易用”重载,解决所有编译错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 19:54:50