GetPrivateProfileString Windows API working in migrated code

Make sure INI files and any configuration file used in a migrated application is located in the right location.

When working with migrated applications from VB6 to .NET (C#/VB.NET) it's very important to pay attention to the usage of INI files or any configuration file consummed by the application at runtime.

The reason is very simple, when you're developing a VB6 aplication, it's possible those INI file are located at the same folder where the VB6 source code file is, but, when this source code is migrated using the VBUC, INI files or any other configuration files aren't moved to the target folder (the folder where migrated code is located after the initial migration).

It means, all those files needed by the migrated application, has to be manually moved to the right destination. And by "right destination" it should be understood as the place where .NET puts the new binary files of the migrated code.

The following example using GetPrivateProfileString windows API method in a VB6 application will illustrate this.

This VB6 app, reads a INI file located at the same path of the VB6 source code files:

The following code shows how this small application works: It opens sample.ini file and get the value "ExeName" located under "SME100" section.

[SME100]
Applicationloc =C:\
ExeName=myexe.exe
Option Explicit

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

Dim lngRetVal As Integer

    Dim sTemp As String
    sTemp = String$(255, 32)
    On Error GoTo err
    lngRetVal = GetPrivateProfileString("SME100", "ExeName", "", sTemp, Len(sTemp), App.Path + "\sample.ini")
    MsgBox sTemp
    Exit Sub

err:
    MsgBox err.Description
End Sub

When the VB6 source code is migrated, the target folder contains the new C#/VB.NET code (for this example, the code was converted to C#). No other additional files have being added (for instance, sample.ini).

The migrated code will look like:

//UPGRADE_NOTE: (2041) The following line was commented. More Information: https://docs.mobilize.net/vbuc/ewis#2041
//[DllImport("kernel32.dll", EntryPoint = "GetPrivateProfileStringA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
//extern public static int GetPrivateProfileString([MarshalAs(UnmanagedType.VBByRefStr)] ref string lpApplicationName, System.IntPtr lpKeyName, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpDefault, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpReturnedString, int nSize, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpFileName);

//UPGRADE_WARNING: (2080) Form_Load event was upgraded to Form_Load method and has a new behavior. More Information: https://docs.mobilize.net/vbuc/ewis#2080
private void Form_Load()
{

	int lngRetVal = 0;

	string sTemp = new string((char) 32, 255);
	try
	{
		string tempRefParam = "SME100";
		string tempRefParam2 = "";
		string tempRefParam3 = Path.GetDirectoryName(Application.ExecutablePath) + "\\sample.ini";
		lngRetVal = UpgradeSolution1Support.PInvoke.SafeNative.kernel32.GetPrivateProfileString(ref tempRefParam, "ExeName", ref tempRefParam2, ref sTemp, Strings.Len(sTemp), ref tempRefParam3);
		MessageBox.Show(sTemp, AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
	}
	catch (System.Exception excep)
	{

		MessageBox.Show(excep.Message, AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
	}
}

As shown above, the GetPrivateProfileString Windows API definition has being moved to a new project where all API methods will be centralized.

If migrated code is executed, a runtime exception will be thrown by GetPrivateProfileString(). Reason: sample.ini file is not located (yet) at this path Path.GetDirectoryName(Application.ExecutablePath) + "\\sample.ini";

That line of code returns the location for the EXE file of the migrated application.

How to solve this?

Solution is very simple, go to the folder where sample.ini file is located, copy the file and then put it into the folder where the EXE file of the migrated application is generated. For this example, sample.ini file has to be copied into the bin sub-folder of the target folder for the miration.

If you are deploying the migrated application in a different location do not forget moving INI files and any configuration resource file needed by your application.

Last updated