Microsoft KB Archive/318608

= FIX: Tlbimp.exe Generates Interface Wrappers that Cannot Be Used =

Article ID: 318608

Article Last Modified on 2/23/2007

-

APPLIES TO


 * Microsoft .NET Framework 1.1
 * Microsoft .NET Framework 1.0

-



This article was previously published under Q318608



SYMPTOMS
In a .NET application, if you call a COM function that accepts a pointer to a COM interface as its parameter, and you then pass a .NET class that implements a wrapper interface that is created around the COM interface to the function, the function call is unsuccessful and you receive the following error message:

An unhandled exception of type 'System.NullReferenceException' occurred in YourApp.exe

Additional information: Object reference not set to an instance of an object.



CAUSE
The wrapper class that the Type Library Importer utility (Tlbimp.exe) generates for the COM interface changes the COM function definition so that the function accepts a .NET wrapper interface instead of the actual COM interface pointer. Note that Tlbimp.exe only does this for the default interface for coclasses. If you use an interface that is not the default interface for a coclass, the application works as expected.



RESOLUTION
To work around the problem, change the wrapper assembly so that the COM function takes a pointer to the actual COM interface instead of to a wrapper interface. To modify the wrapper, follow these steps:  Follow these steps to use the MSIL Disassembler (Ildasm.exe) to disassemble the wrapper dynamic-link library (DLL):  From a .NET command prompt, run ILDASM. On the File menu, click Open. Open the wrapper DLL that is created by using Tlbimp.exe. On the File menu, click Dump. Click OK in the dialog box that appears. Specify a file name, and then click OK.  In a text editor, modify the contents of the intermediate language that is generated.</li>  Search for the function that you want, and then change the parameter list so that it takes the actual COM interface. In the intermediate language code, underscore characters (_) typically precede the name of the COM interfaces. Therefore, you must type an underscore (_) before the interface name in the function definition. For example, change the following function([in][out] class IBug.myinterface& marshal( interface) func) runtime managed internalcall to: function([in][out] class IBug._myinterface& marshal( interface) func) runtime managed internalcall </li> Save the changes to the file.</li>  Run the following command from a .NET command prompt to use ILASM to reassemble the intermediate language as a DLL: ilasm /dll <.il file> /out=<output .dll file> </li> In your .NET application, remove the reference to the old DLL and add a reference to the new wrapper DLL that you just created.</li></ol>

<div class="status_section">

STATUS
This bug was corrected in .NET Framework (2003|1.1).

<div class="moreinformation_section">

Steps to Reproduce the Behavior
  Create a new class in a Microsoft Visual Basic DLL. Name the class MyInterface, and then paste the following code in the code window for the class: Public Function f As String f = &quot;MyInterface:f&quot; End Function </li>  Create another class, name the class MyClass, and then paste the following code in the code window for the class: Note that the first parameter of the function is a pointer to the MyInterface class. Function answer(func As myinterface) As String answer = func.f + &quot; ... answering from COM&quot; End Function </li> On the File menu, click Make to build the DLL.</li>  Use Tlbimp.exe to generate a COM Interop assembly for the COM DLL that you just created. To do this, run the following from a .NET command prompt, where  is the file that you just created: tlbimp /out=Bug.Interop.dll </li> Create a new Visual Basic .NET or Visual C# .NET Windows Application project.</li> Add a reference to the COM Interop DLL, Bug.Interop.dll, that you just created.</li>  Create a new class that will implement the first COM wrapper interface. Name the class Class2, and then paste the following code in the code window for the new class: Public Class Class2 Implements Bug.Interop.MyInterface Private mystring As String

Public Sub setstring(ByVal astring As String) mystring = astring End Sub

Function f As String Implements Bug.Interop.MyInterface.f       Return mystring End Function End Class </li> Add a command button to Form1. Double-click the command button to open the code window for Form1.</li>  Call the COM function on your newly-created object, and then pass the .NET class that implemented the first wrapper interface to the function. To do this, paste the following code in the Button1_Click event handler: Dim netimpl2 As New Class1 Dim com As New Bug.Interop.MyClass

netimpl2.setstring(&quot;I'm calling from .NET&quot;)

'This line generates the error. MsgBox(com.answer(netimpl2)) </li> Press F5 to run the application, and then click the command button to generate the error.</li></ol>

<div class="references_section">