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: , ,

    Trackback

3 Comments »

[...] The release engineering process has gone fairly smoothly. I have been able to remove the hanging reference problem that is a bug in Dotfuscator (I blogged on that previously here). [...]

    Marco wrote @ November 18th, 2006 at 8:04 am

Very interesting. Demenor from WiseOwl (http://www.wiseowl.com/default.aspx) had exactly the same problem and they initially suggested the same resolution.

It’s time they both start using the System.Reflection.ObfuscationAttribute. Instead of their inhouse designed attribute. This would make our declarative obfuscation also more independent of the obfuscation tool sellers. Probably that’s why they have not been to eager on this.

    Robert W. Anderson wrote @ November 18th, 2006 at 9:00 am

Marco, thanks for the comment.

Actually, PreEmptive does support the .NET 2.0 ObfuscationAttribute. I believe they have ever since the .NET 2.0 betas. This post was only about how to deal with the .NET 1.1 problem.

Cheers,
Robert

Your comment

HTML-Tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>