介绍一下windows注册表的数据类型,顺便提供C#访问REG_EXPAND_SZ类型的原始值(不使用环境变量值替换)的方法

Windows注册表的字段类型

常用主要有6种

  • 二进制(REG_BINARY)
    在注册表中,二进制是没有长度限制的,可以是任意个字节的长度。

  • DWORD值(REG_DWORD)
    DWORD值是一个32位(4个字节,即双字)长度的整数。在注册表编辑器中,系统以十六进制的方式显示DWORD值。

  • 字符串值(REG_SZ)
    在注册表中,字符串值一般用来表示文件的描述、硬件的标识等,通常它是以空字符(\0)结尾的字符串。

  • QWORD值(REG_QWORD)
    DWORD值是一个64位(8个字节,即四字)长度的数值。在注册表编辑器中,系统以十六进制的方式显示QWORD值。

  • 多字符串值(REG_MULTI_SZ)
    由两个空字符终止的空终止字符串数组。

  • 可扩充字符串值(REG_EXPAND_SZ)
    包含对环境变量的未扩展引用的空终止字符串(例如,“%PATH%”)。

C#针对可扩充字符串值获取原始值

C#一般的方法(Microsoft.Win32下的注册表相关类)获取可扩充字符串(REG_EXPAND_SZ)的值,都会自动将环境变量填充实际的值,如何获取可扩充字符串的原始值而不自动扩展环境变量呢?
这个只能通过调用 Win32 API 来实现。

C#实现方式

// 读取注册表值
[DllImport("advapi32.dll", SetLastError = true)]
static extern uint RegQueryValueEx(
    UIntPtr hKey,
    string lpValueName,
    int lpReserved,
    ref RegistryValueKind lpType,
    IntPtr lpData,
    ref int lpcbData
);

// 打开注册表键
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern int RegOpenKeyEx(
    UIntPtr hKey,
    string subKey,
    int ulOptions,
    int samDesired,
    out UIntPtr hkResult
);
// 关闭注册表键 因为是非托管内存,GC不会自动回收,一定需要手动释放掉注打开册表键的句柄
[DllImport("advapi32.dll", SetLastError = true)]
public static extern int RegCloseKey(UIntPtr hKey);

private static readonly UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);
private static readonly int READ_FLAG_MASK = 0x20019;

// 返回regPath下项名为valName的原始值
public string GetLMNamedValue(string valName, string regPath)
{
    UIntPtr hKey = UIntPtr.Zero;
    IntPtr pResult = IntPtr.Zero;
    try
    {
        if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, regPath, 0, READ_FLAG_MASK, out hKey) == 0)
        {
            int size = 0;
            RegistryValueKind type = RegistryValueKind.Unknown;
            // 获取需要的缓冲区大小
            uint retVal = RegQueryValueEx(hKey, valName, 0, ref type, IntPtr.Zero, ref size);
            if (size == 0)
            {
                return null;
            }
            // Marshal 提供了一个方法集合,这些方法用于分配非托管内存、复制非托管内存块、将托管类型转换为非托管类型,此外还提供了在与非托管代码交互时使用的其他杂项方法。
            pResult = Marshal.AllocHGlobal(size);
            retVal = RegQueryValueEx(hKey, valName, 0, ref type, pResult, ref size);
            if (retVal != 0)
            {
                throw new ApplicationException($"查询错误 '{regPath}\\{valName}: 0x{Marshal.GetLastWin32Error().ToString("x2")}, 返回: {retVal}");
            }
            else
            {
                switch (type)
                {
                    case RegistryValueKind.String:
                        return Marshal.PtrToStringAnsi(pResult);
                    case RegistryValueKind.DWord:
                        return Marshal.ReadInt32(pResult).ToString();
                    case RegistryValueKind.QWord:
                        return Marshal.ReadInt64(pResult).ToString();
                    case RegistryValueKind.ExpandString:
                        // 直接输出原始内容
                        return Marshal.PtrToStringAnsi(pResult);
                }
            }
        }
        else
        {
            throw new ApplicationException($"打开注册表键错误 HKLM\\{regPath}: {Marshal.GetLastWin32Error().ToString("1:x")}");
        }
    }
    finally
    {
        if (hKey != UIntPtr.Zero)
        {
            RegCloseKey(hKey);
        }

        if (pResult != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(pResult);
        }
    }
    return null;
}

原文地址:http://www.cnblogs.com/lollipopnougat/p/16910013.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性