RegSetValueEx returns 998 (ERROR_NOACCESS) 如果在没有引用的情况下调用
RegSetValueEx returns 998 (ERROR_NOACCESS) if called without ref
我正在尝试使用 C# 将 DWORD 写入注册表。
由于注册表重定向,使用 p/invoke。
我搜索了这个问题,终于可以解决了,但我不明白。
[DllImport("advapi32.dll", SetLastError = true)]
static extern uint RegSetValueEx(
IntPtr hKey,
[MarshalAs(UnmanagedType.LPStr)]
string lpValueName,
int Reserved,
RegistryValueKind dwType,
ref IntPtr lpData,
int cbData);
int checkreturn = RegOpenKeyEx(HKeyLocalMachine, @"SOFTWARE\Test", 0, (int) RegistrySecurity.KEY_WOW64_64KEY | (int) RegistrySecurity.KEY_SET_VALUE, ref keyHandle);
const int dataStored = 0;
IntPtr p = new IntPtr(dataStored);
int size = Marshal.SizeOf(dataStored);
uint checkreturn2 = RegSetValueEx(keyHandle, "valueName", 0, RegistryValueKind.DWord, ref p, size);
如果我将 out
或 ref
放在 lpData 参数上,这将起作用,如果我不这样做,则会出现 returns 错误 998 (ERROR_NOACCESS),这是为什么呢?如果我将 IntPtr 更改为 int,并传递实际值,也会发生同样的事情,但这次我在代码中遇到第一个异常 AccessViolation。
它的 winapi 声明是 *lpData
,我认为这是传递 IntPtr
的意思。
_In_ const BYTE *lpData,
api需要一个指向数据的指针加上数据的大小。您不能传递 int
、char
或 bool
。您需要传递一个指向数据的指针。如果您传递其他内容,API 会将其解释为指向数据的指针,并且会发生随机结果。
使用 P/Invoke,指向某物的 ref
被转换为指向该某物的指针。
现在,您可以
[DllImport("advapi32.dll", SetLastError = true)]
static extern uint RegSetValueEx(
IntPtr hKey,
[MarshalAs(UnmanagedType.LPStr)]
string lpValueName,
int Reserved,
RegistryValueKind dwType,
ref uint lpData,
int cbData);
然后在 cbData
中传递 sizeof(uint)
和 这个 将起作用,因为 P/Invoke 的 ref
是 ref
.
只有一件事,我建议删除
[MarshalAs(UnmanagedType.LPStr)]
因为没有它 P/Invoke 将使用该方法的 Unicode 版本,这更正确。
我正在尝试使用 C# 将 DWORD 写入注册表。 由于注册表重定向,使用 p/invoke。
我搜索了这个问题,终于可以解决了,但我不明白。
[DllImport("advapi32.dll", SetLastError = true)]
static extern uint RegSetValueEx(
IntPtr hKey,
[MarshalAs(UnmanagedType.LPStr)]
string lpValueName,
int Reserved,
RegistryValueKind dwType,
ref IntPtr lpData,
int cbData);
int checkreturn = RegOpenKeyEx(HKeyLocalMachine, @"SOFTWARE\Test", 0, (int) RegistrySecurity.KEY_WOW64_64KEY | (int) RegistrySecurity.KEY_SET_VALUE, ref keyHandle);
const int dataStored = 0;
IntPtr p = new IntPtr(dataStored);
int size = Marshal.SizeOf(dataStored);
uint checkreturn2 = RegSetValueEx(keyHandle, "valueName", 0, RegistryValueKind.DWord, ref p, size);
如果我将 out
或 ref
放在 lpData 参数上,这将起作用,如果我不这样做,则会出现 returns 错误 998 (ERROR_NOACCESS),这是为什么呢?如果我将 IntPtr 更改为 int,并传递实际值,也会发生同样的事情,但这次我在代码中遇到第一个异常 AccessViolation。
它的 winapi 声明是 *lpData
,我认为这是传递 IntPtr
的意思。
_In_ const BYTE *lpData,
api需要一个指向数据的指针加上数据的大小。您不能传递 int
、char
或 bool
。您需要传递一个指向数据的指针。如果您传递其他内容,API 会将其解释为指向数据的指针,并且会发生随机结果。
使用 P/Invoke,指向某物的 ref
被转换为指向该某物的指针。
现在,您可以
[DllImport("advapi32.dll", SetLastError = true)]
static extern uint RegSetValueEx(
IntPtr hKey,
[MarshalAs(UnmanagedType.LPStr)]
string lpValueName,
int Reserved,
RegistryValueKind dwType,
ref uint lpData,
int cbData);
然后在 cbData
中传递 sizeof(uint)
和 这个 将起作用,因为 P/Invoke 的 ref
是 ref
.
只有一件事,我建议删除
[MarshalAs(UnmanagedType.LPStr)]
因为没有它 P/Invoke 将使用该方法的 Unicode 版本,这更正确。