Search code examples
c#comclickoncemanifest

ClickOnce manifest file - duplicate "file" entries being generated


I've had all sorts of fun and games with my ClickOnce application, and despite working my way around those problems, I've fallen at the final hurdle.

I need to my WPF (.Net 4.0) app include a COM component and 3 DLL's in my project. The COM component is:

enter image description here

and the 3 DLLs, which need to be in the executable directory:

enter image description here

The COM component also needs a custom .manifest file, which my project is set to use: here's a sample section from it, referencing one of those DLLs:

  <file name="BytescoutVideoMixerFilter.dll" asmv2:size="203368" xmlns="urn:schemas-microsoft-com:asm.v1">
<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>JYpOccueoR7YDchdz+iCMPquHtg=</dsig:DigestValue>
</hash>
<comClass clsid="{4407F28D-97C2-41C5-A23F-2FAE465CE7BB}" threadingModel="Both" tlbid="{8EDAD3BB-AE5F-43B4-A2F1-B04F4130F2E0}" description="Bytescout Video Mixer Filter" />

The full manifest file is here.

Now the application runs fine locally, both from Visual Studio and running the .exe. However, I need to deploy the app via ClickOnce, including those 3 DLLs.

The only way I can get the DLLs included in the publisher package is to set the build action to "Content". However, if I do this, the published manifest has a duplicate section for each file added: as an example, I set BytescoutVideoMixerFilter.dll's Build Action to Content, and the above manifest snippet becomes:

  <file name="BytescoutVideoMixerFilter.dll" asmv2:size="203368" xmlns="urn:schemas-microsoft-com:asm.v1">
    <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>JYpOccueoR7YDchdz+iCMPquHtg=</dsig:DigestValue>
    </hash>
    <comClass clsid="{4407F28D-97C2-41C5-A23F-2FAE465CE7BB}" threadingModel="Both" tlbid="{8EDAD3BB-AE5F-43B4-A2F1-B04F4130F2E0}" description="Bytescout Video Mixer Filter" />
  </file>
  <file name="BytescoutVideoMixerFilter.dll" size="203368">
    <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>JYpOccueoR7YDchdz+iCMPquHtg=</dsig:DigestValue>
    </hash>
  </file>

... so two sections for the one file; the first one is the settings from my manifest, and the other seemingly auto-generated without the comClass line. And of course, as both are referencing the same DLL, Windows complains and refuses to run the application.

So I'm stuck between a rock and a hard place:

  • If I set the DLL Build Actions to Resource (or anything else), they aren't included in the published package. As the published .manifest file references those files, the ClickOnce package won't deploy - it complains about "missing files" (e.g. BytescoutVideoMixerFilter.dll.deploy).
  • If I set the DLL Build Actions to Content, they're included in the published package - but the published manifest now has duplicate entries.

If I can solve either of those issues, I'm done, and I'm never touching COM again. However, I've tried everything: I cannot get the files included in the published package without also breaking the manifest file.


Solution

  • I've managed to hack a sort-of workaround. It's horrible, but I:

    • Changed the Build Action of the DLLs in the project to "None"
    • Created a folder called "Resources" in the project, and put separate copies of the DLL in there. The Build Action on those is "Content".
    • Publishing the project now includes those DLLs in the Resources folder, with .deploy extensions
    • I copy those .deploy files to the parent directory
    • I can now download/update the application via ClickOnce

    I've knocked together a script to copy the files into the right place. It's a pain, and certainly not something I'd have to expect to do - but it works!