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
的方式进行操作。无论这是否合法,我都无法找到任何明确的声明。谁能提供一个?[是的,我知道有用于与注册表交互的托管代码。在我的特定情况下,我无法使用它,即使我仍然可以对总体答案感兴趣]
最佳答案
是的,这是完全正常且可以接受的技巧。几乎所有类型为BYTE*
,PVOID
,LPARAM
的winapi函数参数都适合于自定义的[DllImport]声明。字符串,数组或结构是通常等效的C#参数类型。声明SendMessage()
时特别有用。
除了它的结尾,您还可以轻松利用C#语言允许方法重载。换句话说,您可以为lpData
参数编写任意数量的具有不同类型的RegSetValueEx()声明。它们都映射到相同的本机函数,因此您无需执行其他任何操作。实际示例is here。
您只需要确保编组后传递的值具有预期的字节值即可。请注意,错误往往难以调试,如果呼叫无法解决,您可能仍想手动进行封送处理。这个问题肯定是一个怪癖,您总是想在声明中使用CharSet = CharSet.Unicode
,调用ANSI版本(RegSetValueExA)没什么用。现在,您还可以添加ExactSpelling = true
。
关于c# - 为了方便而更改P/Invoke签名的合法性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43052906/