Tricks for Modifying Interop Assemblies
Interop assemblies produced by the type library importer sometimes need modifications, due to limitations in version 1.0 of the importer, limitations of type library expressiveness, or errors/omissions in the input type library. Using two important tools in the .NET Framework SDKthe IL Assembler (ILASM.EXE) and the IL Disassembler (ILDASM.EXE)you can change Interop assemblies to suit your needs. Of course, any changes you make must adhere to the rules of the CLR and the Interop marshaler.
Modifying Interop assemblies (and alternatives to doing this) is a large topic, discussed in depth in Chapter 7 of .NET and COM: The Complete Interoperability Guide, but this article gives some highlights. The basic steps for generating, then modifying, an Interop assembly are
Generate the original Interop assembly:
TLBIMP MyTypeLib.tlb /out:MyAssembly.dll
Disassemble the Interop assembly:
ILDASM MyAssembly.dll /out:MyAssembly.il
Change the contents of the output file with a text editor.
Reassemble the assembly:
ILASM /dll MyAssembly.il
Step 3 is the tricky part. What follows are some commonly needed transformations, all shown in IL Assembler syntax, because that is what appears inside the text file generated by the IL Disassembler. If you don't know the IL Assembler syntax for a higher-level language construct that isn't covered here, the easiest way to learn it is to write a small program that contains this construct in a familiar .NET language, then open and inspect the compiled assembly with the IL Disassembler.
Changing Data Types
You often need to change parameters or fields to the System.IntPtr type to bypass marshaling limitations and enable managed code to perform do-it-yourself marshaling with members of the System.Runtime.InteropServices.Marshal class. This class enables useful operations to be performed on such size-agnostic integers representing pointers. For example, to change a structure's SAFEARRAY field to an IntPtr (because SAFEARRAY fields are not supported in version 1.0 of the Interop marshaler), change this
.field public marshal( safearray bstr) string SomeField
.field public native int SomeField
Whenever changing a member signature in an Interop assembly, remember to change all occurrences of it (such as on an interface and any classes that implement it), otherwise the modified assembly will not work.