Wednesday, May 07, 2008

Today I was struggling to figure out why I kept getting this error message when downloading a ClickOnce app:

The file 'C:\Documents and Settings\[user]\Local Settings\Temp\2\Deployment\RCAX3K4W.T8E\GRY27V4Q.GBE\SomeDll.dll' already exists.

First, let me just say that I don't use Visual Studio to create the ClickOnce deployment, but the Mage.exe utility. If you use Visual Studio this problem will be solved on Publish in Visual Studio.

I knew there was only one of this dll present on the server where ClickOnce downloads its files, but still it insisted that it was already downloaded. I checked my application manifest and there where only one entry for my dll. The dll causing this problem is a COM dll with generated manifest files (Reg-Free COM) as described here.

I started to inspect the Reg-Free COM manifest file generated by Visual Studio. It turns out that this manifest file use the same syntax as ClickOnce, or actually ClickOnce use the existing manifest schema that was introduced with Windows XP and Reg-Free COM. So in my ClickOnce manifest I had this:

...
<file name="My.dll" size="1121280">
  <hash>
    <dsig:Transforms>
      <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
    </dsig:Transforms>
    <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
    <dsig:DigestValue>UwpS1EpkD7aJk3uWdOtX+3BHiOA=</dsig:DigestValue>
  </hash>
</file>
...

...and in my Reg-Free COM manifest I had this:

...
<file name="My.dll" asmv2:size="1121280">
    <hash xmlns="urn:schemas-microsoft-com:asm.v2">
      <dsig:Transforms>
        <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
      </dsig:Transforms>
      <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
      <dsig:DigestValue>UwpS1EpkD7aJk3uWdOtX+3BHiOA=</dsig:DigestValue>
    </hash>
    <typelib tlbid="{2d5e2d34-bed5-4b9f-9793-a31e26e6806e}" version="4.1" helpdir="" resourceid="0" flags="HASDISKIMAGE" />
    ...COM Registry Entries...
</file>
...

It's exactly the same as ClickOnce except from the <typelib> part which is used by Reg-Free COM. ClickOnce treated this as any other ClickOnce manifest, and correctly stated that the file is about to be downloaded twice. The surprising part for me though was that the Reg-Free COM manifest was read at all. Since the deployment manifest is only linked to the application manifest...

So what's the solution? Just delete the file entry in the ClickOnce manifest and re-sign it! Deleting can be done like this:

ApplicationManifest manifest = (ApplicationManifest) ManifestReader.ReadManifest("ApplicationManifest", @"My.exe.manifest", false);
FileReference fileRef = manifest.FileReferences.FindTargetPath("My.dll");
manifest.FileReferences.Remove(fileRef);
ManifestWriter.WriteManifest(manifest);

Curious about how Visual Studio solves this? It merges all the manifest files into the application manifest and use the imported manifest entries instead (or something like that). At least that happened when I created a sample program to test this.

All comments require the approval of the site owner before being displayed.
Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, b, blockquote@cite, em, i, strike, strong, sub, sup, u) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Live Comment Preview
 
Aggregate Me!
Feed your aggregator (RSS 2.0)  Rss
  Comments
On this page....
Locations of visitors to this page