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

bmm*_*m6o 2 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);
Run Code Online (Sandbox Code Playgroud)

IntPtr的lpData参数可以一起工作有疼痛感.要传递一个字符串值,我需要调用其中一个Marshall.StringToHGlobal函数,然后在完成后释放它.如果我将lpData参数类型更改为,我的代码可以更简单[MarshalAs(UnmanagedType.LPStr)]String lpData.这似乎工作,我可以想象在幕后,编组代码正在做我要做的事情IntPtr.如果这是合法的,我无法找到任何明确的陈述.任何人都可以提供吗?

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

Han*_*ant 5

是的,这是pinvoke中完全正常且可接受的技术.只是类型的任何WINAPI函数参数BYTE*,PVOID,LPARAM本身借给一个自定义函数[DllImport]宣言.字符串,数组或结构是通常的等效C#参数类型.声明时特别有用SendMessage().

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

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