Microsoft KB Archive/834056

= BUG: The ByValTStr attribute is incorrectly applied to the fixed-length string member when you upgrade a Visual Basic 6.0 project to a Visual Basic .NET project =

Article ID: 834056

Article Last Modified on 4/24/2007

-

APPLIES TO


 * Microsoft Visual Studio .NET 2003 Professional Edition
 * Microsoft Visual Studio .NET 2003 Enterprise Architect
 * Microsoft Visual Studio .NET 2003 Enterprise Developer
 * Microsoft Visual Studio .NET 2003 Academic Edition
 * Microsoft Visual Studio .NET 2002 Enterprise Architect
 * Microsoft Visual Studio .NET 2002 Enterprise Developer
 * Microsoft Visual Studio .NET 2002 Professional Edition
 * Microsoft Visual Studio .NET 2002 Academic Edition

-





''Microsoft Visual Studio .NET changes the ByValTStr attribute to ByValArray when you upgrade a Microsoft Visual Basic 6.0 project to a Microsoft Visual Basic .NET project. The ByValTStr attribute is incorrectly applied in Visual Basic .NET.''



SYMPTOMS
When you upgrade a Visual Basic 6.0 project application that passes a structure to an API to a Visual Basic .NET project application, the ByValTStr attribute is incorrectly applied to the fixed-length string member.



CAUSE
This bug occurs because the ByValTStr attribute in Visual Basic .NET is incorrectly applied after you upgrade your project application from Visual Basic 6.0 to Visual Basic .NET. The size of the fixed-length string member of the string buffer that is marshaled includes the NULL termination character.



STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed in the &quot;Applies to&quot; section.



MORE INFORMATION
When you upgrade Visual Basic 6.0 to Visual Basic .NET, Microsoft Visual Studio .NET produces the following two changes in the Visual Basic .NET code:
 * Visual Studio .NET changes the ByValTStr attribute to ByValArray.
 * Visual Studio .NET changes the MyString type from the String data type to a Char data type array.

The following code exists in the Visual Basic .NET Module1.vb file: Option Strict Off Option Explicit On Module Module1 Private Structure MyStruct  Public MyString As Char End Structure 'UPGRADE_WARNING: Structure MyStruct may require marshaling 'attributes to be passed as an argument in this Declare statement. 'Click for more: 'ms-help://MS.VSCC/commoner/redir/redirect.htm?keyword=&quot;vbup1050&quot;' Private Declare Sub TestStructByRef Lib &quot;C:\Test\StructTest.dll&quot; (ByRef ms As MyStruct) 'UPGRADE_WARNING: Application will quit when Sub Main finishes. 'Click for more: 'ms-help://MS.VSCC/commoner/redir/redirect.htm?keyword=&quot;vbup1047&quot;' Public Sub Main Dim ms As MyStruct ms.MyString = &quot;12345&quot; TestStructByRef(ms) MsgBox(ms.MyString) End Sub End Module Note In this code,  is a placeholder for a folder in your local hard disk drive.

The potential issues with the changes that occur when you upgrade Visual Basic 6.0 to Visual Basic .NET are the following:  You must set the MyString value to exactly five characters in length when MyString is passed to the API function that accepts the structure. You must do this because the SizeConst field value is set to five characters in length.  A Component Object Model (COM) exception occurs if the size of the Char data type array does not match the SizeConst field value when the MyString value is set to less than five characters in length.

To avoid the COM exception, replace this code MyStruct.MyString = &quot;123&quot; with the following code: MyStruct.MyString = &quot;123 &quot; Notice that there are two spaces after the string value 123 to make it five characters in length. Therefore, the string value matches the SizeConst field value. 

Steps to reproduce the behavior
 Create a DLL, as follows:  Start Visual Studio .NET.</li> On the File menu, point to New, and then click Project.

The New Project dialog box appears.</li> Under Project Types, click Visual C++ Projects.</li> Under Templates, click Win32 Project.</li> In the Location box, type C:\.

Note In this step,  is a placeholder for the name of the folder where you want to save your application.</li> In the Name box, type StructTest as the name of your application, and then click OK.

The Win32 Application Wizard - StructTest dialog box appears.</li> In the Win32 Application Wizard - StructTest dialog box, click Application Settings.</li> In the Application Settings section, click DLL under Application type.</li> Under Additional options, click to select the Empty Project check box. Click Finish.</li> In the Solution Explorer pane, right-click Source Files, point to Add, and then click Add New Item.

The Add New Item - StructTest dialog box appears.</li> Under Templates, click C++ File (.cpp).</li> In the Name box, type StructTest, and then click Open.</li>  Add the following code to the StructTest.cpp file:
 * 1) include <windows.h>

struct MyStruct {   char MyString[5]; };

BOOL WINAPI DllMain( HINSTANCE hinstDLL,  // handle to DLL module  DWORD fdwReason,     // reason for calling function  LPVOID lpvReserved   // reserved ) {   return TRUE; }

void __declspec(dllexport) __stdcall TestStructByRef(MyStruct *inObj) {   MyStruct *ms1 = (MyStruct*)inObj; }

void __declspec(dllexport) __stdcall TestStructByVal(MyStruct inObj) {   MyStruct ms1 = inObj; } </li> In the Solution Explorer pane, right-click Source Files, point to Add, and then click Add New Item.

The Add New Item - StructTest dialog box appears.</li> Under Templates, click Module-Definition File (.def).</li> In the Name box, type StructTest, and then click Open.</li> <li> Replace the code in the StructTest.def file with the following code: LIBRARY StructTest

EXPORTS

TestStructByRef TestStructByVal </li> <li>On the Build menu, click Build Solution.

The StructTest.dll file is created in the C:\ \Debug folder.

Note In this step,  is a placeholder for the name of your folder.</li></ol> </li> <li>Add the DLL that you created in step 1 to the project application, as follows: <ol style="list-style-type: lower-alpha;"> <li>Start Visual Basic 6.0.</li> <li>Create a Standard EXE project.

By default, the Form1 form is added to your project.</li> <li>In Project Explorer, right-click the project, point to Add, and then click Module.

The Add Module dialog box appears.</li> <li>Click the New tab, click Module, and then click Open.</li> <li> Add the following code to the Module1.bas file: Private Type MyStruct MyString As String * 5 End Type

Private Declare Sub TestStructByRef Lib &quot;C:\Test\StructTest.dll&quot;&quot; (ByRef ms As MyStruct)

Sub Main Dim ms As MyStruct ms.MyString = &quot;12345&quot; TestStructByRef ms   MsgBox ms.MyString End Sub Note In this step,  is a placeholder for the path of the DLL that you created in step 1. </li> <li>On the File menu, click Save Project As.

The Save Project As dialog box appears.</li> <li>In the File name box, type TestStructTest .</li> <li>Copy the StructTest.dll file that you built in step 1 to the  folder.

Note In this step,  is a placeholder for a folder on your local hard disk drive.</li> <li>On the Project menu, click Project1 Properties.</li> <li>In the Project1 - Project Properties dialog box, click the General tab, set the value of the Startup Object box to Sub Main, and then click OK.</li> <li>On the Run menu, click Start.

You receive a message with a value of 12345.</li></ol> </li> <li>In Visual Studio .NET, open the Visual Basic 6.0 project that you created in step 2, as follows: <ol style="list-style-type: lower-alpha;"> <li>Start Visual Studio .NET.</li> <li>On the File menu, point to Open, and then click Project.

The Open Project dialog box appears.</li> <li>In the Open Project dialog box, click the TestStructTest.vbp project file that you created in step 2, and then click Open.

The Visual Basic Upgrade Wizard - Page 1 of 5 dialog box appears.</li> <li>In the Visual Basic Upgrade Wizard - Page 1 of 5 dialog box, click Next.

The Visual Basic Upgrade Wizard - Page 2 of 5 dialog box appears.</li> <li>In the Visual Basic Upgrade Wizard - Page 2 of 5 dialog box, click EXE, and then click Next.

The Visual Basic Upgrade Wizard - Page 3 of 5 dialog box appears.</li> <li>In the Visual Basic Upgrade Wizard - Page 3 of 5 dialog box, type C:\ \DotNetProject in the Where do you want your new project created box, and then click Next.

The Visual Basic Upgrade Wizard - Page 4 of 5 dialog box appears.

If the DotNetProject folder does not exist in the  folder, create the DotNetProject folder.

Note In this step,  is a placeholder for a folder in your local hard disk drive.</li> <li>In the Visual Basic Upgrade Wizard - Page 4 of 5 dialog box, click Next.

The Visual Basic Upgrade Wizard - Page 5 of 5 dialog box appears.</li> <li>Upgrade your project.

The Visual Basic Upgrade Wizard- Page 5 of 5 dialog box closes after you upgrade your project from Visual Basic 6.0 to Visual Studio .NET.</li> <li> In the Solution Explorer pane, double-click the Module1.vb file. Notice the following code: Option Strict Off Option Explicit On Module Module1 Private Structure MyStruct <VBFixedString(5),System.Runtime.InteropServices.MarshalAs _ (System.Runtime.InteropServices.UnmanagedType.ByValTStr,SizeConst:=5)> Public MyString As String End Structure

'UPGRADE_WARNING: Structure MyStruct may require marshaling attributes to be passed as an 'argument in this Declare statement. Click for more: 'ms-help://MS.VSCC/commoner/redir/redirect.htm?keyword=&quot;vbup1050&quot;' Private Declare Sub TestStructByRef Lib &quot;C:\Test\StructTest.dll&quot; (ByRef ms As MyStruct) 'UPGRADE_WARNING: Application will quit when Sub Main finishes. Click for more: 'ms-help://MS.VSCC/commoner/redir/redirect.htm?keyword=&quot;vbup1047&quot;' Public Sub Main Dim ms As MyStruct ms.MyString = &quot;12345&quot; TestStructByRef(ms) MsgBox(ms.MyString) End Sub End Module Note In this code,  is a placeholder for a folder in your local hard disk drive. </li> <li>Save the Visual Studio .NET project to the C:\ \DotNetProject folder.

Note In this step,  is a placeholder for a folder in your local hard disk drive.</li> <li>On the Project menu, click TestStructTest Properties.</li> <li>In the General section of the TestStructTest Property Pages dialog box, set the value of the Startup object box to Sub Main under Common Properties.</li> <li>On the Debug menu, click Start.

You receive a message with a value of 1234.</li></ol> </li></ol>

<div class="references_section">