Friday, March 13, 2009

Injecting Code into .NET Assemblies

What you need for this kind of surgery is:
1.) Reflector
2.) Reflexil (Reflector plugin)
3.) Your DLL or custom Assembly to call some code
4.) 10 Minutes time

The patient:
svcutil.exe (C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\svcutil.exe)

The enhancement:
svcutilImportCommentExtension

Primary Mission Goal:
Pimp svcutil to create nice code comments in my DataContracts from my annotations in XSD ( /dconly Option )
Secondary Mission Goal:
Pimp svcutil to create nice code comments in my WCF proxies from my WCF Service WSDL


1.) Copy the patient

2.) Start Reflector and
a.) Open the copy of svcutil.exe
b.) Open the DLL

3.) Right click on svcutil and select "Go to entry Point".

4.) Click on Main(string[] args) in "return (int) runtime.Run();"



5.) Click on ExecuteToolMode in "return this.ExecuteToolMode(toolMode, inputModule);"

6.) Click on ImportDataContracts in "this.ImportDataContracts(inputModule);"



7.) Click on ImportDataContracts in "module.ImportDataContracts();"

8.) Click on "Tools - Reflexil 0.9"

9.) Right click Line 7 "Call .... WriteConversionErrors" and select "Create New"
Choose
Opcode: ldstr
Operand Type: string
Operand: Calling svcutil extension....

Finish with selecting "Insert before selection"

10.) Right click Line 7 which now contains our "ldstr..." and select "Create New"
Choose
Opcode: Call
Operand Type: Method Reference
Operand: svcutilImportCommentExtension - svcutilImportCommentExtension.dll - ContractGenTest - CommentWriter - Hello(System.String) : System.Void



Finish with selecting "Insert after selection"

11.) Right click Line 8 which now contains our "call Hello(..)." and select "Create New"
Choose
Opcode: ldarg.0
Operand Type: None
Operand:

Finish with selecting "Insert after selection"

12.) Right click Line 9 which now contains our "ldarg.0" and select "Create New"
Choose
Opcode: ldfld
Operand Type: Field Reference
Operand: svcutil - svcutil.exe - Microsoft.Tools.ServiceModel.SvcUtil - ImportModule - schemas : System.Xml.XmlSchemaSet

13.) Right click Line 10 which now contains our "ldfld schemas" and select "Create New"
Choose
Opcode: ldarg.0
Operand Type: None
Operand:

Finish with selecting "Insert after selection"

14.) Right click Line 11 which now contains our "ldarg.0" and select "Create New"
Choose
Opcode: ldfld
Operand Type: Field Reference
Operand: svcutil - svcutil.exe - Microsoft.Tools.ServiceModel.SvcUtil - ImportModule - codeCompileUnit : System.CodeDom.CodeCompileUnit

Finish with selecting "Insert after selection"

15.) Right click Line 12 which now contains our "ldfld codeCompileUnit" and select "Create New"
Choose
Opcode: Call
Operand Type: Method Reference
Operand: svcutilImportCommentExtension - svcutilImportCommentExtension.dll - ContractGenTest - CommentWriter - WriteComments(System.Xml.Schema.SchemaSet,System.CodeDom.CodeCompileUnit)


Finish with selecting "Insert after selection"

This is how ImportDataContracts should look like now....

(Note that the Dissambler part should still display the unchanged code as we did not save it yet. This screenshot is taken from a already modified version...)

Now click on the symbol "svcutil.exe" in the reflector and select "Save as". You will now get a warning that svcutil is a signed assembly. Select "Remove Strong Name - Remove Strong Name and update referencing assemblies" and both windows. Now select "Save as" again and replace the file.

Now when you call svcutil you should get....



and have some nice comments in your code collected from all your

<xs:annotation>
<xs:documentation>.....</xs:documentation>


tags.


Sweet.

If you do the same for ImportServiceContracts() function you will be even able to create fully documented WCF proxies....

Just make sure you this time you call

CommentWriter.WriteComments(WsdlImporter importer, CodeCompileUnit compileUnit)

using the

Operand: svcutil - svcutil.exe - Microsoft.Tools.ServiceModel.SvcUtil - ImportModule - wsdlImporter: System.ServiceModel.Description

instead of the SchemaSet.

This is how ImportServiceContracts should look like after your surgery...



To bad comments don't get exported in WCF WSDL's? Well think again and get WCFExtras. A very nice WCF Extension to get XMLComments into WCF WSDL's as well as a working flat WSDL and support for Soap Headers.

Mission accomplished

5 comments:

Anonymous said...

thank you, works like a charm.

Anonymous said...

excellent. why in the hell couldn't microsoft have just done this from the start?

Anonymous said...

Is there anyway to tie this into visual studio's "add service reference"? It seems to not call svcutil under the hood

elLoco said...

I looked into the "add service reference" option, but I did not find a way. Different from the WCF-Testclient, this function in Visual Studio does not use svcutil.

Asher Frank said...

.NET Reflector can be used to track down efficiency problems and insects, surf sessions, and maintain or help become familiar with rule angles.