VB Migration Partner

KNOWLEDGE BASE - Language


Previous | Index | Next 

[PRB] A call to a Windows API Declare returns a string filled with spaces

We have found an undocumented detail in the way VB6 and VB.NET deal with string arguments passed by-reference to methods, which becomes important when invoking Windows API methods. Consider the following VB6 code:

    Private Declare Function GetPrivateProfileString Lib "kernel32.dll" Alias _
        "GetPrivateProfileStringA" (ByVal lpApplicationName As String, _
        ByVal lpKeyName As String, ByVal lpDefault As String, _
        ByVal lpReturnedString As String, ByVal nSize As Long, _
        ByVal lpFileName As String) As Long

        ' ...
        Dim sRet As String
        sRet = String(255, Chr(0))
        sRet = Left(sRet, GetPrivateProfileString("mysection", ByVal "mykey", "", sRet, _
               Len(sRet), "myfile.ini"))

Notice that, even though the lpReturnedString parameter appears to be passed by value, it is actually passed by reference and is the buffer where the GetPrivateProfileString method stores its string result, whereas the 32-bit value returned by the call is the number of characters stored in the buffer. The neat effect is that, when this code terminates its execution, the sRet variable contains the value read from the INI file.

VB Migration Partner translates the above fragment to this VB.NET code, which seems to be equivalent to the original code:

        Dim sRet As String = String6(255, Chr6(0))
        ' UPGRADE_WARNING (#0384): Using the 'GetPrivateProfileString' Windows API method
        ' as an argument to the 'Left' function might result in an string filled with 
        ' spaces. Please split the next line in two statements.
        sRet = VB.Left(sRet, GetPrivateProfileString("mysection", "mykey", "", sRet, _
               Len6(sRet), "myfile.ini"))

Here’s the problem: VB.NET pushes the first argument for Left (the sRet string) on the stack and then calls GetPrivateProfileString. When the API method modifies the sRet string it creates a new instance of the string, whereas the address already on the stack still points to the old string filled with spaces. When the code completes its execution, sRet contains a number of spaces rather than the actual value. Please notice that this isn’t a VB.NET (or VB Migration Partner’s) bug, it’s just a consequence of the fact that .NET strings are immutable.

You can fix this problem by following the suggestion given by the warning the VB Migration Partner emits: modify the original VB6 code to explicitly use temporary variables.

    Dim sRet As String
    sRet = String(255, Chr(0))
    Dim length As Integer
    length = GetPrivateProfileString("mysection", ByVal "mykey", "", sRet, _
        Len(sRet), "myfile.ini")
    sRet = Left(sRet, length)

This fix doesn’t change the behavior of the VB6 code, but the converted VB.NET code behaves as intended.

Previous | Index | Next 




Follow Francesco Balena on VB6 migration’s group on

LinkedIn





Read Microsoft Corp’s official case study of a VB6 conversion using VB Migration Partner.




Code Architects and its partners offers remote and onsite migration services.

More details




Subscribe to our free newsletter for useful VB6 migration tips and techniques.

newsletter



To learn more about your VB6 applications, run VB6 Analyzer on your source code and send us the generated text file. You will receive a detailed report about your VB6 applications and how VB Migration Partner can help you to quickly and effectively migrate it to .NET.

Get free advice



A fully-working, time-limited Trial Edition of VB Migration Partner allows you to test it against your actual code

Get the Trial




The price of VB Migration Partner depends on the size of the VB6 application, the type of license, and other factors

Request a quote




Migrating a VB6 application in 10 easy steps

Comparing VB Migration Partner with Upgrade Wizard

Migration tools: Feature Comparison Table

All whitepapers