Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding VBByRefStr in VB.NET P/Invoke declarations

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?

like image 356
Paul B. Avatar asked Dec 06 '25 08:12

Paul B.


1 Answers

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.

like image 154
Mark Bertenshaw Avatar answered Dec 09 '25 00:12

Mark Bertenshaw