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

P/Invoke调用OREnumValue返回ERROR_INVALID_PARAMETER错误如何解决

问题原因与解决方案

你遇到的ERROR_INVALID_PARAMETER(0x57)错误由两个核心问题导致:

  1. P/Invoke声明的字符集配置错误:Offreg.dll的所有导出函数仅提供Unicode实现,不存在ANSI版本,你使用CharSet.Auto会导致字符长度计算逻辑与非托管API预期不匹配
  2. 可选参数传参不符合API校验规则:OREnumValue的lpcbData参数为可选参数,如果你不需要获取值内容,仅需要查询值名称,必须将该参数显式传NULL,你当前声明为ref uint会始终传入非空指针,触发Offreg的严格参数校验失败

修正后的代码

1. P/Invoke声明修正

// 仅用于查询值名称的重载,不需要类型和数据参数时使用
[DllImport("Offreg.dll", CharSet = CharSet.Unicode, SetLastError = false)]
public static extern uint OREnumValue(
    SafeRegistryHandle Handle,
    uint dwIndex,
    IntPtr lpValueName,
    ref uint lpcValueName,
    IntPtr lpType,
    IntPtr lpData,
    IntPtr lpcbData);

// 可选补充:需要读取值内容时的重载
[DllImport("Offreg.dll", CharSet = CharSet.Unicode, SetLastError = false)]
public static extern uint OREnumValue(
    SafeRegistryHandle Handle,
    uint dwIndex,
    IntPtr lpValueName,
    ref uint lpcValueName,
    out uint lpType,
    IntPtr lpData,
    ref uint lpcbData);

2. GetValueNames实现修正

public class OfflineRegistryKey : IDisposable
{
    private readonly SafeRegistryHandle hKey;
    private const uint ERROR_NO_MORE_ITEMS = 0x103;
    private const uint ERROR_MORE_DATA = 0xEA;
    private const uint ERROR_SUCCESS = 0;

    public string[] GetValueNames()
    {
        List<string> valueNames = new List<string>();
        uint dwIndex = 0;

        while (true)
        {
            uint nameCharLength = 0;
            // 首次调用查询所需的名称缓冲区长度
            uint ret = OREnumValue(hKey, dwIndex, IntPtr.Zero, ref nameCharLength, 
                IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
            
            if (ret == ERROR_NO_MORE_ITEMS)
            {
                break;
            }
            if (ret != ERROR_MORE_DATA)
            {
                throw new Win32Exception((int)ret);
            }

            // 缓冲区长度+1兼容末尾空字符
            nameCharLength++;
            IntPtr nameBuffer = Marshal.AllocHGlobal((int)nameCharLength * 2); // Unicode每个字符占2字节
            try
            {
                ret = OREnumValue(hKey, dwIndex, nameBuffer, ref nameCharLength,
                    IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
                if (ret == ERROR_SUCCESS)
                {
                    valueNames.Add(Marshal.PtrToStringUni(nameBuffer, (int)nameCharLength));
                }
                else
                {
                    throw new Win32Exception((int)ret);
                }
            }
            finally
            {
                Marshal.FreeHGlobal(nameBuffer);
            }

            dwIndex++;
        }

        return valueNames.ToArray();
    }

    // 其余IDisposable实现逻辑省略
}

额外注意事项

  • 确保你使用的SafeRegistryHandle是对Offreg返回的ORHKEY句柄的正确封装,句柄释放逻辑要匹配Offreg的ORCloseKey函数
  • 如果后续需要读取值内容,使用第二个重载传入对应的类型、数据缓冲区参数即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 10:15:05