I have posted a bit on merging ASP.NET 2.0 (without aspnet_merge) and also on renaming ASP.NET 2.0 auto-named assemblies. My first solution on renaming was incomplete in that it would only work when there were no dependencies between the renamed assemblies.
This solution is correct and produces assemblies that properly get through Dotfuscator 3.0 / and actually run! All of the code below are either nant targets or nant tasks. These should be generally applicable (with the right properties assigned).
- Disassemble the assemblies with ildasm.
- Get the generated assembly name for a particular folder from a representative file (either an aspx or ascx).
- Replace the assembly name for all files (pages, controls, and the il) with a fixed name (e.g., “App_Web_Root”).
- Reassemble and rename the assembly’s DLL to the fixed name (using ilasm).
These targets assume the following properties are set:
- ProjectPath
- the path to your build project directory
- ildasm
- the full path to the ildasm executable
- ilasm
- the full path to the ilasm executable
The first part is disassembly (the most straight-forward part):
<!-- disassembles all App_Web assemblies to il --> <target name="disassembleAspNet20Assemblies" > <foreach item="File" property="assembly"> <in> <items basedir="${ProjectPath}\bin"> <include name="App_Web*.dll" /> </items> </in> <do> <exec program="${ildasm}" workingdir="${ProjectPath}" commandline= "/out=${assembly}.il /nobar /raweh /utf8 /quoteallnames /linenumbers ${assembly}" /> </do> </foreach> </target>
The second part is to change the files to point to the new name:
<!-- Renames a generated-assembly for ASP.NET 2.0 --> <!-- 'page' property is a representative page or control in the folder --> <!-- 'fixedAssemblyName' property is the new desired name of the assembly --> <target name="renameAspNet20Assembly"> <loadfile property="loadedPage" file="${ProjectPath}\${page}" /> <!-- get the assembly name from the representative page --> <regex pattern="(?'assembly'App_Web.+\s*)\042" input="${loadedPage}" /> <!-- store the assembly name to fixed name mapping --> <property name="${assembly}" value="${fixedAssemblyName}"/> <!-- copy all of the pages (and il), replacing this assembly name with the fixed name. --> <copy todir="${ProjectPath}/tmpBak" overwrite="true"> <fileset basedir="${ProjectPath}"> <include name="**\*.as?x" /> <include name="**\*.dll.il" /> <exclude name="tmpBak\**" /> </fileset> <filterchain> <replacestring from="${assembly}" to="${fixedAssemblyName}" /> </filterchain> </copy> <!-- copy them all back --> <copy todir="${ProjectPath}" overwrite="true"> <fileset basedir="${ProjectPath}/tmpBak"> <include name="**\*.as?x" /> <include name="**\*.dll.il" /> </fileset> </copy> </target>
Finally, the assemblies must be reassembled:
<!-- Reassembles all the App_Web*il into a new fixedAssembly. --> <!-- This requires that the il's assembly name exists as a property that maps to the new fixedAssembly name.--> <target name="reassembleAspNet20Assemblies" > <foreach item="File" property="assembly"> <in> <items basedir="${ProjectPath}\bin"> <include name="App_Web*.dll.il" /> </items> </in> <do> <!-- get the old DLL name --> <property name="dllName" value="${path::get-file-name-without-extension(assembly)}"/> <!-- get the old assembly name --> <property name="assemblyOnly" value="${path::get-file-name-without-extension(dllName)}"/> <!-- get the new, fixed assembly name --> <property name="fixedAssemblyName" value="${property::get-value(assemblyOnly)}"/> <!-- reassemble --> <exec program="${ilasm}" workingdir="${ProjectPath}" commandline="/out=${ProjectPath}\bin\${fixedAssemblyName}.dll /dll /res=${ProjectPath}\bin\${dllName}.res ${assembly}" /> </do> </foreach> </target>
Then, for each folder, I call the target like so:
<!--Dissasemble the assemblies--> <call target="disassembleAspNet20Assemblies"/> <!-- use Administration.aspx as a proxy for the site's root directory --> <property name="page" value="Administration.aspx" /> <property name="fixedAssemblyName" value="App_Web.ControlRoot" /> <call target="renameAspNet20Assembly" /> <!-- use Login.aspx as a proxy for the site's Secure directory --> <property name="page" value="Secure\Login.aspx" /> <property name="fixedAssemblyName" value="App_Web.Secure" /> <call target="renameAspNet20Assembly" /> <!-- use Headers.ascx as a proxy for the site's Control directory --> <property name="page" value="Controls\Header.ascx" /> <property name="fixedAssemblyName" value="App_Web.Controls" /> <call target="renameAspNet20Assembly" /> <!--reassemble the assemblies--> <call target="reassembleAspNet20Assemblies"/>