When trying to use a P/Invoke declaration made in a VB.NET assembly from C# I noticed that string
arguments become ref string
arguments.
A closer inspection reveals that e.g.
Public Declare Unicode Function RegDeleteValue Lib "advapi32.dll" Alias "RegDeleteValueW" ( _
ByVal hKey As IntPtr, ByVal lpValueName As String) As UInteger
is compiled to
[DllImport(...)]public static extern uint RegDeleteValue(
IntPtr hKey, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpValueName);
On MSDN I read: "VBByRefStr: A value that enables Visual Basic .NET to change a string in unmanaged code, and have the results reflected in managed code. This value is supported only for platform invoke. This is default value in Visual Basic for ByVal strings."
I still don't get it. Why is it only string lpValueName
in C# (see pinvoke.net - edit: for RegDeleteKey as Damien_The_Unbeliever pointed out, signature is the same like RegDeleteValue) but strange VBByRefStr
in VB.NET? Should I declare with <MarshalAs(UnmanagedType.LPWStr)>
in VB.NET to avoid ref
in C#? Or does that have any adverse effects?
This is for backwards compatibility with VB6 Declare statements.
When using ByVal x As String, you indicated that you wanted to convert the VB UTF-16 "String" type into an ASCII representation, pass a pointer to that ASCII buffer to that parameter, and after the call had succeeded, convert the contents of that buffer back into the original UTF-16 string.
This has subsequently been enhanced in VB.NET to support Unicode API calls. However, I would imagine that the VBByRefStr constant indicates that the marshalling done in .NET must follow the method in VB6 exactly.
If you want the standard marshalling for UnmanagedType.LPWStr, then use attributes.