为方便起见,更改P / Invoke签名的合法性

时间:2017-03-27 17:32:13

标签: c# pinvoke

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。如果这是合法的,我无法找到任何明确的陈述。任何人都可以提供吗?

[是的,我知道有托管代码与注册表连接。在我的特殊情况下,我不能使用它,即使我可以,我仍然会对一般的答案感兴趣]

1 个答案:

答案 0 :(得分:5)

是的,这是pinvoke中完全正常且可接受的技术。几乎任何类型BYTE*的winapi函数参数,PVOIDLPARAM都适用于自定义的[DllImport]声明。字符串,数组或结构是通常的等效C#参数类型。声明SendMessage()

时特别有用

不是它结束的地方,你也可以轻松利用允许方法重载的C#语言。换句话说,您可以为lpData参数编写具有不同类型的任意数量的RegSetValueEx()声明。它们都映射到相同的本机函数,因此您无需执行任何其他操作。一个实际的例子is here

您必须确保在编组后传递的值具有预期的字节值。请注意,错误往往难以调试,如果调用没有完成,您可能仍希望手动编组。对于这个问题,一个怪癖肯定是值得注意的,你总是希望在声明中使用CharSet = CharSet.Unicode,调用ANSI版本(RegSetValueExA)是没用的。现在您还可以添加ExactSpelling = true