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

Updating File Versions in Resource Scripts

I just added an article on using UpdateVersion to update resource scripts for unmanaged code. You can read it here.

An excerpt:

At release build time, we update our version numbers using the UpdateVersion utility by Mike Gunderloy, Scott Hanselman, and Matt Griffith. This works fine for managed assemblies, but it doesn’t work for versioning unmanaged Win32 DLLs using the resource script.

I solved this problem while dealing with a completely different versioning issue (related to VS2005’s inadequacy regarding Win32 resources in managed assemblies).

Interestingly enough, just as I thought about posting this, I found on the MSBuild blog that a new MSBuild task similar to the UpdateVersion utility has just been posted to GotDotNet. If and when we migrate to MSBuild, this might just do the trick, but I suspect there will still be some extra work to get this to help with resource scripts.

Tags: , ,

Visual Studio 2005 Web Deployment Projects AddIn

In Renaming ASP.NET 2.0 Assemblies Redux, I detail a way to handle renaming ASP.NET 2.0 assemblies without aspnet_merge. The release of Visual Studio 2005 Web Deployment Projects (Beta Preview) pretty much obviates the need for my solution (unless you need exact control over your per-folder assembly names). If you haven’t heard about the new add-in (and aspnet_merge), read this Scott Guthrie post for an overview: VS 2005 Web Deployment Projects.

All in all, it seems to work well — thanks to the ASP.NET 2.0 team for getting this together so quickly. I did come across the following (very minor) issues:

  • If I happen to click on the VS IDE while building the deployment project, I get a “Microsoft Visual Studio is Busy” warning in a notification icon ballon.
  • It is cool that you can open the build deployment project without unloading the project (as you do for other project types); however, it doesn’t warn you if you edit the project file and (without saving) then change the properties. It does detect the problem when you try to save the project file, but this is a bit late.

Also, I was looking forward to the ability to replace sections of the Web.config, but found that I basically wanted to replace something in nearly every section. I ended up going back to what I used to do: have two config files stored in my development project: Web.config and Web.release.config. The former is used during development and I copy the latter for use in deployment. An easy way to do this with Web Deployment Projects is by editing the project file and using the MSBuild Copy task:

<Target Name="AfterBuild">
  <Copy
    SourceFiles="$(SourceWebPhysicalPath)\\Web.release.config"
    DestinationFiles="$(OutputPath)\\Web.config"
  />
</Target>

The functionality provided in this addin resolves the issues I had with the new ASP.NET 2.0 deployment model. We get many more choices including the old-style single assembly. Yes, this is more complex than ASP.NET 1.1, but the greater flexibility and benefits of the new model make it worth it to me.

Tags: , ,

VS Launch Partner Appreciation Party

John Powers (the Digipede CEO) and I went to the Microsoft Partner Appreciation Party at Frisson in San Francisco as prep for the VSLaunch event at Moscone center tomorrow. John and I had a great talk about how the Digipede Network is a great fit for SaaS in general.

The party was fun. They had a custom drink menu for the event:

Drink menu at the Visual Studio Partner Party

The “Visual Studio 05” wasn’t bad.

As we were heading out of the city, we found ourselves driving into a dead-end loading zone.

John said: “What we are doing here is slightly illegal.”

It became clear that If we continued we would have had to drive over a sidewalk.

I said: “No, what you are about to do is illegal. That is what makes you a visionary.”

And, no, we didn’t have too many drinks at the party!

Tags: ,

2.0 Port Update: Finished (for now)

Now that I am finished with the port to VS2005 / .NET 2.0, I wanted to point out a few final issues I came across. Note that we use the Preemptive Dotfuscator v3.0 here, but the obfuscation issues likely apply to other obfuscators as well:

New files in ASP.NET 2.0

As the compilation model for ASP.NET has changed a great deal, there are also some new files that you must deploy. Of course, this is not an issue if you use VS2005 to deploy directory to a web site, but if you are packaging up all of your files into an installer then make sure you include these new files:

  • *.resx
  • *.compiled
  • PrecompiledApp.config

In particular, I have found that if the *.compiled and PrecompiledApp.config file are not in place, your global events will not get raised.

Obfuscation Issue #1: Don’t rename __ASP

Exclude the __ASP namespace from the renamed. This is a new namespace that is generated by the compiler, so you need to exclude this in your Dotfuscator project file:

  <renaming>
    <excludelist>
        . . .
        <namespace name="__ASP" regex="false" />
        . . .
    </excludelist>
  </renaming>

Note that there is also a new ASP namespace, but I did not have to exclude this one because I was already excluding class names that are automatically placed under this namespace. Obfuscation Issue #2: Don’t obfuscate multiple Web projects at once

Before ASP.NET 2.0, it was possible to obfuscate multiple Web projects at the same time (as long as all of the namespaces are unique across projects). The new namespaces that are generated by the compiler (i.e., ASP and __ASP) will cause a conflict during obfuscation. To solve this problem, you need to break up your obfuscations into multiple projects.

This last part is somewhat non-trivial (or at least a real hassle). I have written many nant scripts that take build output and assemble them into a directory for obfuscation, breaks up the Dotfuscator configuration file, runs multiple obfuscation runs, and finally reassembles the files into individual folders for release.

I am not going to blog on those specifics, but if you are interested in my solutions to these problems, feel free to contact me.

Tags: , , ,

Renaming ASP.NET 2.0 Assemblies Redux

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).

  1. Disassemble the assemblies with ildasm.
  2. Get the generated assembly name for a particular folder from a representative file (either an aspx or ascx).
  3. Replace the assembly name for all files (pages, controls, and the il) with a fixed name (e.g., “App_Web_Root”).
  4. 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"/>

Tags: ,

VS2005 RTM Available on MSDN Subscriber Downloads

After much speculation by many (on whether or not it would be before the 7th), it is available.

This is good news for those of us exhibiting at the VS launch — we will be able to show off the Digipede Network from the final Visual Studio.

Tags: , ,

VS2005 Ships!

Where, I don’t know. It isn’t yet on MSDN. Robert Scoble said that it (and SQL Server 2005 + BizTalk 2006) are done in Three VPs on Channel 9. Tonight is the shipping party.

Congratulations to all of the teams at Microsoft that have been working on this!

Tags: ,

Merging ASP.NET 2.0 without aspnet_merge

Apparently Microsoft will be releasing a tool called aspnet_merge that will help resolve some of the shortcomings in the deployment options when precompiling ASP.NET 2.0 projects. This is supposed to be available on November 7th, but I don’t feel like I want to wait. Thanks to the DotNetNuke guys for working with Microsoft on this. I’m really surprised that it got to be so late in Microsoft’s development cycle before they figured out this was a problem.

I thought I’d try ILMerge to do it. Searching to see if someone else had, I came across this post by K. Scott Allen: Using MSBuild and ILMerge to Package User Controls For Reuse. Similar problem, different goal.

I went ahead and did this with nant as that was the quickest way for me to get this into my release process. I admit this is all a kind of a hack. First, I search for all App_Web*.dll files. Then I replace all references in the aspx and ascx files with a reference to my new merged dll. Finally, I use ILMerge to merge to the new dll. Note that I’m not merging everything, just the assemblies that have seemingly random names.

The nant code follows. It is a bit clumsy, but it works.

  <property name="ProjectPath" value="${BuildRoot}\PrecompiledWeb\${ProjectName}" />
  <property name="ilmergePath" value="c:\Program Files\Microsoft\ILMerge\ILMerge.exe" />
  <property name="mergedAssemblyName" value="ControlMerged.dll" />
  <target name="deploy">
    <property name="assemblyFiles" value="" />
    <foreach item="File" property="assembly">
      <in>
        <items basedir="${ProjectPath}\bin">
          <include name="App_Web*.dll" />
        </items>
      </in>
      <do>
        <property name="assemblyFiles" value="${assemblyFiles} ${assembly}" />
        <copy todir="${ProjectPath}/tmpBak" overwrite="true">
          <fileset basedir="${ProjectPath}">
            <include name="**\*.as?x" />
            <exclude name="tmpBak\**" />
          </fileset>
          <filterchain>
            <replacestring from="${path::get-file-name-without-extension(assembly)}" 
                           to="${path::get-file-name-without-extension(mergedAssemblyName)}" />
          </filterchain>
        </copy>
        <copy todir="${ProjectPath}" overwrite="true">
          <fileset basedir="${ProjectPath}/tmpBak">
            <include name="**\*.as?x" />
          </fileset>
        </copy>
      </do>
    </foreach>
    <exec program="${ilmergePath}" commandline="/out:${mergedAssemblyName} ${assemblyFiles}" workingdir="${ProjectPath}/bin"/>

Tags: , ,

2.0 Port Update 3: On to Release Engineering

I probably have not been clear in my previous posts about the overall methodology I’m following in our port to VS2005. I have split my porting process into several different steps to isolate the effort into manageable slices. These include:

  • Porting the projects into VS2005 for ongoing development. While doing this, I have insured that everything still builds with VS2003 while my team makes the transition to the new IDE. I am avoiding the temptation to fix the thousands of warnings related to deprecated functions. That we will start fixing these as soon as the rest of the team is using VS2005.
  • Porting our release engineering process. I view this as the next most critical item as I want to have our testers began working with the new versions as soon as possible. Note that I’m leaving installs and install issues out of this altogether as this is not managed inside of my group.
  • Continuous integration with CCNET.
  • Digipede Network product features regarding mixed .NET 1.1 / .NET 2.0 environment and continued support for VS2003.
  • Evaluation of WSE3 to determine its viability relating to our release schedule.
  • (future) Evaluate performance improvements that can be achieved with .NET 2.0.
  • (future) Evaluate Team System (regarding unit testing and source control) and its applicability in our environment.

Wrapping up the Development portion

In addition to issues I brought up in my previous post (2.0 Port Update: Mixed Progress), I have come across a few more:

  • With the loss of the ASP.NET project file, many of the build properties are stored in the solution file. I think this is unfortunate. The ability to mix and match projects across different solutions gives the developer more flexibility (and I’m not a proponent of managing solution files in source control for this reason); however, this no longer really works with ASP.NET projects. If we continue to keep solution files out of source control then critical build information won’t be versioned. This is not a huge problem, but I would rather not have to deal with this work-process issue while porting.
  • A slight annoyance: the ASP.NET 2.0 Project Properties dialog includes text boxes for paths to files (e.g., an SNK file). The UI for this translates the path into an absolute one. This is misleading, because the paths are actually stored as relative. It would be much more clear if the UI did no such translation.

On to Release builds

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).

I have come across a somewhat major problem regarding the new ASP.NET 2.0 compilation model (K. Scott Allen has a good article here on this subject). I like the idea that multiple assemblies are now supported by the compiler; however, the way that the assemblies are named presents a problem for anyone who has automated the obfuscation (and possibly the building of installs). My biggest issue right now is getting the three Web site projects that encompass our solution into a state where I can reliably send them through our obfuscator. I will definitely blog on the solution I come up with.

Tags: , , , ,

2.0 Port Update 2: Mixed Progress

After spending most of the day yesterday writing specifications for version 1.2 of the Digipede Network, I spent the afternoon continuing to migrate our projects over to VS2005. This went a little slower than expected, as I fell into a trap regarding upgrading ASP.NET projects.

The Gotcha

ASP.NET 2.0 projects are organized somewhat differently from their predecessors. One major change is that the project file is gone. This makes sense considering there has been much effort to make the Web site synonymous with the project itself. This means that every web page in a folder is a part of the project. Upgrading the project is simple: locate and open the old project file (.csproj in our case). VS2005 takes care of the rest.

But what if you attempt to upgrade it directly from source control? This works as expected for non-ASP.NET projects: simply select the project folder from source control. The project and related files are checked out from source control, and the project file is upgraded. But what happens for ASP.NET?

If you open an old ASP.NET project directly from source control, VS2005 doesn’t even look at the old project file (presumably it determines it is a Web project by the existence of web.config). It assumes that the project is in the new format. You do get prompted to upgrade to ASP.NET 2.0, but you don’t end up in the Upgrade Wizard. As a result, you get an application that has not been reorganized for ASP.NET 2.0.

So, don’t make this mistake! Get your files first and then upgrade from her whole project file.

ASP.NET 2.0 Reorganization re:Source Control

Another related issue is actually a slight beef I have with the Upgrade Wizard (OK, with the decisions made regarding it).

After upgrading your ASP.NET 2.0 project, you will likely get a message that says your project has been disconnected from source control. This is due to the project being reorganized. For example, shared source code files will have been moved into the App_Code folder. The solution suggested by the Upgrade Wizard is to add your project back into source control. Yes, that is a solution.

But what about file history? I take great pains to retain file history in source control. I don’t need to go into the reasons why (as I think they are obvious). It is important enough that I have manually tweaked the source control projects to retain the file history.? This is a bit of a time sink, but again well worth it.

Why doesn’t the Upgrade Wizard offer to move these files in source control? VS2005 does support source control file move (even with a VSS 6 source control provider). It would have saved me some hassle if this was taking care of automatically.

Inconsistency with Source Control

I found an inconsistency in the way the upgrade process deals with deleted files. In at least one case, the user is prompted to automatically remove the deleted file from source control. In another case, it is left to the user to go through the upgrade report and determine which file should be removed from source control:

  • XSDs (and related files) representing DataSets are converted from the old format to the new VS2005 format. In this process, a new file gets added (the Designer.cs file) which replaces the old code-behind file. In this case, VS2005 asks the user if the deleted file should be removed from source control.
  • The upgrade removes.resx files that contain only header information. Unfortunately, VS2005 does not from the user to delete these files from source control.

Tags: , , ,

« Previous entries · Next entries »