抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

介绍一下windows注册表的数据类型

数据类型

主要有6种(其实还有更多,但常用就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%”)。

代码相关

这个其实是写上次那个jdk部署工具的过程中遇到的问题,

一般的方法取可扩充字符串的值结果都会自动填写环境变量实际的值,而想要的功能是注册表的可扩充字符串值如何不自动扩展环境变量

由于 .net 封装的注册表未提供此方面的方法,因此采用 C#winapi 的方法解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// 读取注册表值
[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;


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;
}

评论