RegSetValueEx
具有以下P / Invoke签名:
[DllImport("advapi32.dll", SetLastError = true)]
static extern uint RegSetValueEx(
UIntPtr hKey,
[MarshalAs(UnmanagedType.LPStr)]
string lpValueName,
int Reserved,
RegistryValueKind dwType,
IntPtr lpData,
int cbData);
IntPtr
lpData参数可能很难处理。要传递字符串值,我需要调用其中一个Marshall.StringToHGlobal
函数,然后在完成后释放它。如果我将lpData
参数的类型更改为[MarshalAs(UnmanagedType.LPStr)]String lpData
,我的代码会更简单。这似乎工作,我可以想象幕后编组代码正在做我要做的IntPtr
。如果这是合法的,我无法找到任何明确的陈述。任何人都可以提供吗?
[是的,我知道有托管代码与注册表连接。在我的特殊情况下,我不能使用它,即使我可以,我仍然会对一般的答案感兴趣]
答案 0 :(得分:5)
是的,这是pinvoke中完全正常且可接受的技术。几乎任何类型BYTE*
的winapi函数参数,PVOID
,LPARAM
都适用于自定义的[DllImport]声明。字符串,数组或结构是通常的等效C#参数类型。声明SendMessage()
。
不是它结束的地方,你也可以轻松利用允许方法重载的C#语言。换句话说,您可以为lpData
参数编写具有不同类型的任意数量的RegSetValueEx()声明。它们都映射到相同的本机函数,因此您无需执行任何其他操作。一个实际的例子is here。
您必须确保在编组后传递的值具有预期的字节值。请注意,错误往往难以调试,如果调用没有完成,您可能仍希望手动编组。对于这个问题,一个怪癖肯定是值得注意的,你总是希望在声明中使用CharSet = CharSet.Unicode
,调用ANSI版本(RegSetValueExA)是没用的。现在您还可以添加ExactSpelling = true
。