ClickOnce - File Already Exists Error - Why is a DLL File Trying to be Copied Twice by ClickOnce?

In your Visual Studio solution, how is the file added? Please try the following.

Add the dll to your project.

If you have a reference to the dll in References, set the properties on the dll like this: Build Action = none, Copy to output directory = "do not copy". Then delete the reference and then re-add the reference, but point to that dll in your local project folder. On the REference, set "copy local" to true.

If you don't have a Reference for the dll, set the properties on the dll like this: Build Action = "copy". Copy to Output Directory = "Copy always".

If you have a reference, you want the reason for it to be included to be based on the reference, and not on the dll properties. If you don't have a reference, you want to set the dll specifically to be included.

Also check the Application Files dialog and make sure the dll is not marked as Include(Prerequisite), but is Include or Include(Required).


You don't mention if you are using the wonderful (cough) MAGE.EXE to generate your deployment manifest. However I have encountered the same 'The file x already exists' error, and it is caused by managed assemblies that call functions in native assemblies via P/Invoke.

For each managed assembly in the location specified by the -FromDirectory argument to MAGE.EXE, MAGE will create a <dependency><dependentAssembly>...</dependentAssembly></dependency> set of elements (including the assembly codebase, identity, size, hash, etc). For each other file (including non-managed native assemblies) MAGE.EXE will create a <file>...</file> element.

However at install-time, it appears that ClickOnce actually inspects the manifest metadata of each managed assembly. So if your application has ManagedAssemblyA which P/Invokes code in NativeAssemblyB (or tx16_rtf.dll in your case), you will see via ILDASM that the manifest for ManagedAssemblyA has a .module extern NativeAssemblyB.dll statement.

I can only assume that ClickOnce, whilst processing the <dependentAssembly codebase="ManagedAssemblyA.dll"> element, inspects the assembly's metadata, sees that there is a native assembly referenced, sees that it is also in the same deployment location and copies it down. Then, when later processing the <file name="NativeAssemblyB.dll"> element, it errors as it has already copied this file and assumes failing to install is the safest course of action. I haven't found this behaviour documented by Microsoft anywhere.

So the solution is, after generating the deployment manifest with MAGE.EXE, but before signing it, remove the <file> elements for any native assemblies. The native assemblies still need to be available in the same deployment location as the rest of the assemblies required by the ClickOnce app.

In our case we automated this since we also automate the generation of the deployment manifest with each continuous integration build (as opposed to using the Publishing Wizard inside Visual Studio 2010 which gives you a bit more control); we have a Powershell script that invokes MAGE.EXE to create the deployment manifest, some more Powershell to manipulate the XML and remove the <file> element (really easy with Powershell... good luck doing it with a batch file!), then we invoke MAGE.EXE to sign the manifest.