If you want to redistribute the source of a Visual Studio project you cannot just zip the folder tree because otherwise the archive will contain lots of useless files and folders:

  • the bin and obj folders;
  • the _ReSharper.projectName folder that contains the ReSharper cache;
  • the .svn folders with the Subversion state files;
  • all the .user files which contains the user specific configurations for a visual studio project;
  • the .suo file with contains the user specific settings for a given Visual Studio solution.

All these summed up, not only clutters the archive, but also make it grow in size, sometimes even 3 times the “clean” folder structure.

I’m in this situation right now, since I’ve to pack all the code samples for my book, and doing it manually is pretty boring (I’ve 10 chapters with an average of 5-6 sample solutions per chapter). Furthermore I’ll have to rebuild all the solutions when the RTM of ASP.NET MVC comes out, so I’ll have to repeat the cleanup again.

Another thing I’ve to remove is the Company Name and Copyright from the AssemblyInfo.cs file: when Visual Studio creates a solution it automatically puts the name of company VisualStudio was registered for, but the samples for the book don’t need to have a copyright. So I’ve to remove them as well.

Without further ado, here is the quick hack I came out with, using NAnt and embedding the Regex replacement call inside the build file.

<?xml version="1.0"?>
<project name="CleanUp" default="clean">
    <property name="debug" value="true"/>
    
    <target name="clean">
        <foreach item="Folder" property="foldername">
            <in>
                <items basedir=".">
                    <include name="**\bin" />
                    <include name="**\obj" />
                    <include name="**\_ReSharper.*" />
                </items>
            </in>
            <do>
                <delete dir="${foldername}" />
            </do>
        </foreach>
        <foreach item="File" property="filename">
            <in>
                <items basedir=".">
                    <include name="**\*.user" />
                    <include name="**\*.suo" />
                </items>
            </in>
            <do>
                <delete file="${filename}" />
            </do>
        </foreach>
        
                <foreach item="File" property="filename">
            <in>
                <items basedir=".">
                    <include name="**\AssemblyInfo.cs" />
                </items>
            </in>
            <do>
                <echo message="${filename}" />
                <property name="AssemblyFileName" value="${filename}"/>
                <property name="find1" value=".*(assembly:\sAssemblyCopyright).*"/>
                <property name="find2" value=".*(assembly:\sAssemblyCompany).*"/>
                <property name="replace" value=""/>
                <call target="regex-replace" />
            </do>
        </foreach>
        
    </target>
    
    <target name="regex-replace">
        <script language="C#">
              <imports>
                    <import namespace="System.Text.RegularExpressions"/>
                    <import namespace="System.IO"/>
              </imports>
              <code><![CDATA[
        public static void ScriptMain(Project project) {
              StreamReader reader = File.OpenText(project.Properties["AssemblyFileName"]);
              string file = String.Empty;
              try {
                    Regex expression1 = new Regex(project.Properties["find1"]);
                    Regex expression2 = new Regex(project.Properties["find2"]);
                    file = reader.ReadToEnd();
                    file = expression1.Replace(file, project.Properties["replace"]);
                    file = expression2.Replace(file, project.Properties["replace"]);
              } finally {
                    reader.Close();
              }
              TextWriter tw = new StreamWriter(project.Properties["AssemblyFileName"]);
              try {
                    tw.WriteLine(file);
              } finally {
                    tw.Close();
              }
        }]]></code>
        </script>
    </target>
</project>

Probably not the best piece of software, but it does it’s job, and saved me going into each of the 50+ folders and removing the the lines in the assemblyinfo file.

For your convenience, I uploaded a zip file containing the build file and bat file to launch it.

Technorati Tags: ,