ClickOnce - 文件已存在错误 - 为什么 ClickOnce 尝试将 DLL 文件复制两次?

发布于 2024-11-26 02:05:15 字数 1130 浏览 5 评论 0原文

ClickOnce 是否仅查看应用程序清单文件来确定将哪些 dll 文件复制到客户端计算机,还是还询问程序集的内部结构以确定依赖文件?

我之所以问这个问题,是因为当我尝试启动已使用 ClickOnce 发布的 WPF .NET 4 应用程序时,出现以下 ClickOnce 错误: 文件 C:\Users\CNelson\AppData\Local\Temp\Deployment\PGX6P33A.35N\AJQL8AC8.D60\tx16_rtf.dll 已存在。

在我包含对两个第 3 方 .NET dll 的引用(这两个 DLL 均引用非托管 dll 文件 (tx16_rtf.dll))后,此错误开始出现。我希望将 tx16_rtf.dll 复制到客户端 PC 上的 bin 文件夹,因此我将其包含在我的项目中,并将“构建操作”设置为“内容”,将“复制到输出目录”设置为“始终复制”。

但是,由于某种原因,当我尝试启动应用程序时,ClickOnce 尝试复制文件“tx16_rtf.dll”两次,这会导致错误。

如果我查看部署清单文件,我可以清楚地看到文件“tx16_rtf.dll”的一个且仅有一个条目。所以,我的问题是,如果文件“tx16_rtf.dll”仅在部署清单文件中存在一次,为什么 ClickOnce 会尝试复制文件“tx16_rtf.dll”两次?

以下是引用“tx16_rtf.dll”的部署清单文件的片段:

  <file name="tx16_rtf.dll" size="839680">
    <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>V6i2QcARl3+1SJHCugoazb9zrOY=</dsig:DigestValue>
    </hash>
  </file>

Does ClickOnce only look at the application manifest file to determine which dll files to copy to the client’s machine or does it also interrogate the internals of an assembly to determine dependency files?

The reason I’m asking is because I’m getting the below ClickOnce error when trying to launch a WPF .NET 4 application that has been published with ClickOnce:
The file C:\Users\CNelson\AppData\Local\Temp\Deployment\PGX6P33A.35N\AJQL8AC8.D60\tx16_rtf.dll already exists.

This error began after I’ve included a reference to two 3rd party .NET dlls that both reference an unmanaged dll file (tx16_rtf.dll). I want tx16_rtf.dll to be copied to the bin folder on the client’s PC so I have included it in my project and set the Build Action to ‘Content’ and the Copy to Output Directory to ‘Copy Always’.

However, for some reason when I try to launch the application ClickOnce is trying to copy the file ‘tx16_rtf.dll’ twice, which results in an error.

If I look at the deployment manifest file I can clearly see one and only one entry for file ‘tx16_rtf.dll’. So, my question is, why does ClickOnce try to copy file ‘tx16_rtf.dll’ twice if it only exists once in the deployment manifest file?

Below is a snippet of the deployment manifest file that references ‘tx16_rtf.dll’:

  <file name="tx16_rtf.dll" size="839680">
    <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>V6i2QcARl3+1SJHCugoazb9zrOY=</dsig:DigestValue>
    </hash>
  </file>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

沫雨熙 2024-12-03 02:05:15

在您的 Visual Studio 解决方案中,如何添加文件?请尝试以下操作。

将 dll 添加到您的项目中。

如果您在引用中有对该 dll 的引用,请像这样设置该 dll 的属性:构建操作 = 无,复制到输出目录 =“不复制”。然后删除引用,然后重新添加引用,但指向本地项目文件夹中的该 dll。在参考中,将“复制本地”设置为 true。

如果您没有 dll 的引用,请像这样设置 dll 的属性:Build Action =“copy”。复制到输出目录=“始终复制”。

如果您有一个引用,您希望包含它的原因是基于该引用,而不是基于 dll 属性。如果没有引用,则需要专门设置要包含的 dll。

另请检查“应用程序文件”对话框,并确保 dll 未标记为“包含(先决条件)”,而是“包含”或“包含(必需)”。

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

心房的律动 2024-12-03 02:05:15

您没有提及您是否正在使用精彩的(咳嗽)MAGE.EXE 来生成部署清单。但是,我遇到了相同的“文件 x 已存在”错误,这是由通过 P/Invoke 调用本机程序集中的函数的托管程序集引起的。

对于 MAGE.EXE 的 -FromDirectory 参数指定的位置中的每个托管程序集,MAGE 将创建一个 ...元素集(包括程序集代码库、身份、大小、哈希等)。对于每个其他文件(包括非托管本机程序集),MAGE.EXE 将创建一个 ... 元素。

但是在安装时,ClickOnce 似乎实际上检查每个托管程序集的清单元数据。因此,如果您的应用程序有 ManagedAssemblyA,它 P/Invokes NativeAssemblyB 中的代码(或者在您的情况下为 tx16_rtf.dll),您将通过 ILDASM 看到 ManagedAssemblyA 的清单有一个 .module extern NativeAssemblyB。 dll 语句。

我只能假设 ClickOnce 在处理 元素时,检查程序集的元数据,看到有引用的本机程序集,看到它也是位于同一部署位置并将其复制下来。然后,当稍后处理 元素时,它会出错,因为它已经复制了此文件,并假定失败安装是最安全的操作过程。我还没有发现微软在任何地方记录了这种行为。

因此,解决方案是,在使用 MAGE.EXE 生成部署清单之后,但在对其进行签名之前,删除任何本机程序集的 元素。本机程序集仍需要在与 ClickOnce 应用程序所需的其余程序集相同的部署位置中可用。

在我们的例子中,我们自动化了这一点,因为我们还在每个持续集成构建中自动生成部署清单(而不是使用 Visual Studio 2010 中的发布向导,这为您提供了更多的控制权);我们有一个 Powershell 脚本,它调用 MAGE.EXE 来创建部署清单,还有一些 Powershell 来操作 XML 并删除 元素(使用 Powershell 真的很容易......祝你好运)使用批处理文件!),然后我们调用 MAGE.EXE 来签署清单。

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.

零崎曲识 2024-12-03 02:05:15

整合你的 nuget 包,如果你有 2 个依赖于第三个 nuget 包的不同版本的引用,有时你可以有 2 个对同一个 nuget 包的引用。这将导致 Clickonce 失败。

Consolidate your nuget packages, if you have 2 references that depend on different versions of a 3rd nuget package, sometimes you can have 2 references to a same nuget package. This will cause Clickonce to fail.

盗梦空间 2024-12-03 02:05:15

如果您有时引用 .csproj,有时引用编译 .dll,也可能会发生这种情况,

例如:

Main.csproj:
  ref A.csproj
  ref B.csproj
A.csproj
  ref B.dll

This can also happen if you sometimes reference the .csproj and sometimes the compile .dll

E.g.:

Main.csproj:
  ref A.csproj
  ref B.csproj
A.csproj
  ref B.dll
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文