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>
答案 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