首页 > 系统相关 >Windows注册表的常用字段数据类型

Windows注册表的常用字段数据类型

时间:2022-11-20 23:25:44浏览次数:39  
标签:pResult UIntPtr 注册表 数据类型 REG 常用字 hKey Marshal

介绍一下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;
}

标签:pResult,UIntPtr,注册表,数据类型,REG,常用字,hKey,Marshal
From: https://www.cnblogs.com/lollipopnougat/p/16910013.html

相关文章

  • MySQL进阶实战1,数据类型与三范式
    一、选择优化的数据类型MySQL支持的数据类型非常多,选择正确的数据类型对于获得高性能至关重要。1、更小的一般情况下,应该尽量使用较小的数据类型,更小的数据类型通常更快,因为......
  • ORA-00997: 非法使用 LONG 数据类型
    今天在创建表的时候直接用的createtableXXXasselect*fromAAA;结果出了一个:ORA-00997:非法使用LONG数据类型 的错误。后来查了一下,做下笔记:1、select查询语句中用......
  • c/c++常见的数据类型表示的范围
    首先参考博客 ​​C语言:基本数据类型及表示范围-myrj-这里有个疑问,int和long到底什么区别:看了一些博客:​​在C+中,int和long有什么区别?​​​​C和C++中int和long有什么......
  • 变量和数据类型
    Python零基礎新手入門#02變數與資料型態intfloatstring姓名=input("请输入你的姓名:")出生年=input("请输入你的出生年:")print(f"{姓名}你好,你出生于{出生......
  • Redis学习(六)之redis中的数据类型之SortedSet类型
      1、sortedset中每个元素有一个浮点值。 2、浮点值越大的,元素排序就大,浮点值相同,则按元素的字符串值比较。 3、元素必须唯一。  1、ZADDkey[NX|XX][GT......
  • JS数据类型与对象
    <!DOCTYPEhtml><html><head><metacharset="utf-8"><title></title></head><body><!--数据类型与对象--><script>......
  • ECMAScript客户端脚本语言的标准 注释 数据类型
    1基本语法:1,与html结合方式  1,内部js  定义<script>,标签内容就算js代码2,外部JS定义<script>,通过src属性引入外部的js......
  • Redis学习(五)之redis中的数据类型之Set类型
      1、set是字符串无序集合,可以执行交集,并集,差集运算。 2、sismember可以判断元素是否存在。  1、比如给新闻添加标签。就可以在点开新闻的时候,看到它有哪些标签......
  • Redis学习(四)之redis中的数据类型之Hashes类型
      1、hset设置值,hget获取值,hmget可以一次获取一个map的多个key值。 2、hsetmapnamekeyvaluekeyvalue  一些指令可以直接操作map中的key对应的value值 ......
  • Redis学习(三)之redis中的数据类型之List类型
      1、redis中的list使用的是链表结构,链表结构可以保证插入速度快。   1、LPUSH指令将元素加入链表左侧,RPUSH指令将元素加入链表右侧,LRANGE获取指定下标,-1指的......