Windows注册表的常用字段数据类型
介绍一下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;
}