Expert Texture Home Contact me About Subscribe Digipede Connect on LinkedIn rwandering on Twitter rwandering on FriendFeed

rwandering.net

The blogged wandering of Robert W. Anderson

Removing a hanging assembly reference

I don’t know if many people have run into this problem: a .NET assembly referencing another assembly in its manifest, though the referenced assembly isn’t used at all.

I don’t believe this is possible under normal conditions, but it is possible with an application that post-processes the assembly. Specifically, this can happen when using Dotfuscator 3.0. When obfuscating .NET 1.1 assemblies, it supports custom obfuscation attributes defined in a .NET library that they ship. Depending on the way you configure Dotfuscator, these attributes can be stripped from your obfuscated assembly. This is reasonable as the attributes have already served their purpose. There is a confirmed bug (that I’m sure they’ll fix soon) that leaves a reference in the manifest though all the attributes have been removed.

In most cases this doesn’t effect the use of your assembly. The CLR won’t try to load the referenced assembly (as there are no actual references to any types in that assembly). The one problem that I have found, though, is if your assembly is a library that others (e.g., your customers) will reference in their own projects. The assembly still functions properly, but undesirable warnings will be emitted by the compiler. And of course, this only applies if you are not shipping the unreferenced assembly.

As an interim solution, they (i.e., Preemptive support staff) suggest disassembling to il with ildasm, manually editing the il, and then reassembling with ilasm. Of course, this approach doesn’t work in an automated release environment. Understandably, they leave that as an exercise for the reader.

Here is what we did. Since all of our release builds are done with nant,
we made use of the built-in ildasm and ilasm tasks. Then we added a custom task that removes the reference from the il. The following code shows an example target assuming that the name of the library is ‘MyLibrary.dll’:

<?xml version="1.0" ?>
<project name="Hanging reference Example" default="rebuild" xmlns="http://nant.sf.net/release/0.85-rc3/nant.xsd">
    <target name="assembleobf">
        <!-- fix the Preemptive.ObfuscationAttributes.dll hanging reference bug -->
        <ildasm rebuild="true" output="MyLibrary.dll.il" rawexceptionhandling="true" quoteallnames="true"
            utf8="true" linenumbers="true" input="MyLibrary.dll" />
        <!-- define a task that takes an IL file as an input, removes the Preemptive.ObfuscationAttributes.dll, and
             writes the file out again -->
        <script language="C#">
            <imports>
                <import namespace="System" />
                <import namespace="System.IO" />
                <import namespace="System.Text" />
            </imports>
            <code>
            <![CDATA[
                [TaskName("removeRef")]
                public class RemoveRefTask : Task {
                    private string _obfuscatedLibrary;
                    [TaskAttribute("obfuscatedLibrary", Required=true)]
                    public string SomeProperty {
                        get { return _obfuscatedLibrary; }
                        set { _obfuscatedLibrary = value; }
                    }
                                                       
                    protected override void ExecuteTask() {
                        StreamReader inFile = new StreamReader(_obfuscatedLibrary + ".il");
                        string inContents = inFile.ReadToEnd();
                        inFile.Close();
                   
                        StringBuilder sb = new StringBuilder(inContents.Length);
                        StringReader stringReader = new StringReader(inContents);
                        string line;
                        while ((line = stringReader.ReadLine()) != null) {
                            if (line != @".assembly extern 'PreEmptive.ObfuscationAttributes'") {
                                sb.Append(line + '
');
                            } else {
                                for (int i=0; i < 4; i++) {
                                    stringReader.ReadLine();
                                }
                                sb.Append(stringReader.ReadToEnd());
                            }
                        }
                   
                        StreamWriter outFile = new StreamWriter(_obfuscatedLibrary + ".il");
                        outFile.Write(sb.ToString());
                        outFile.Close();
                    }
                }
            ]]>
            </code>
        </script>
        <removeRef obfuscatedLibrary="MyLibrary.dll" />
        <ilasm rebuild="true" output="MyLibrary.dll" resourcefile="MyLibrary.dll.res" target="dll">
            <sources>
                <include name="MyLibrary.dll.il"></include>
            </sources>
        </ilasm>
    </target>
</project>

They’ll fix it soon, I’m sure — but for now this will work just fine.

Tags: , ,

COM APIs for .NET Libraries

Recently I added a COM API to the Digipede Framework API – developing a good, maintainable COM API was critical. The “easy” Microsoft .NET COM interop works pretty well, but it defaults too many things for those of us building public libraries.

If your public library needs to support COM, there are several steps you will want to take to make your COM API easier to maintain and to allow your library to behave (or appear) as COM clients expect.

I am thinking of writing an article (or a series of blog entries) on the steps I took designing our COM API. While some material exists out there on this (most of it pure reference), none of it brings it all together, soup to nuts.

My quick outline for the article:

  1. Introduction
  2. Limitations of COM interfaces
  3. Overriding the class interface
  4. Eventing interfaces
  5. Building your Type Library
  6. Embedding your Type Library
  7. Enabling Registration-Free COM
  8. Building a COM API Reference w/NDoc

Every section will include examples.

I guess my only question is: do I blog it or write an article for one of the many .NET related sites? If I write an article, which site should I submit it to?

Tags: ,

« Previous entries