ClickOnce - 文件已经存在错误 - 为什么DLL文件试图被ClickOnce复制两次?

时间:2011-07-22 17:27:23

标签: .net clickonce manifest

ClickOnce是否仅查看应用程序清单文件以确定要复制到客户端计算机的DLL文件,还是查询程序集的内部以确定依赖项文件?

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

在我添加了两个引用非托管dll文件(tx16_rtf.dll)的第三方.NET dll的引用之后,这个错误就开始了。我希望将tx16_rtf.dll复制到客户端PC上的bin文件夹中,以便将其包含在我的项目中,并将Build Action设置为'Content',将Copy to Output Directory设置为'Always Always'。

但是,由于某种原因,当我尝试启动应用程序时,ClickOnce尝试将文件'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>

4 个答案:

答案 0 :(得分:11)

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

将dll添加到项目中。

如果在引用中有对dll的引用,请在dll上设置如下属性:Build Action = none,Copy to output directory =“do not copy”。然后删除引用,然后重新添加引用,但指向本地项目文件夹中的该DLL。在REFER上,将“copy local”设置为true。

如果您没有dll的参考,请在dll上设置如下属性:Build Action =“copy”。复制到输出目录=“始终复制”。

如果您有引用,则希望其包含的原因基于引用,而不是基于dll属性。如果您没有引用,则需要将dll专门设置为包含在内。

同时检查“应用程序文件”对话框,确保dll未标记为“包含”(前提条件),但包含或包括(必需)。

答案 1 :(得分:8)

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

对于由MAGE.EXE的-FromDirectory参数指定的位置中的每个托管程序集,MAGE将创建一组<dependency><dependentAssembly>...</dependentAssembly></dependency>元素(包括程序集代码库,标识,大小,哈希等)。对于其他每个文件(包括非托管的本机程序集),MAGE.EXE将创建一个<file>...</file>元素。

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

我只能假设ClickOnce在处理<dependentAssembly codebase="ManagedAssemblyA.dll">元素时检查程序集的元数据,发现有一个本机程序集被引用,看到它也在同一个部署位置并将其复制下来。然后,当稍后处理<file name="NativeAssemblyB.dll">元素时,它会因为已经复制了该文件而出错,并且假定无法安装是最安全的操作过程。我没有在任何地方发现Microsoft记录此行为。

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

如果您有时引用.csproj,有时甚至引用.dll,也会发生这种情况。

例如:

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