ClickOnce - ошибка файла уже существует. Почему DLL-файл дважды копируется с помощью ClickOnce? - PullRequest
19 голосов
/ 22 июля 2011

ClickOnce только просматривает файл манифеста приложения, чтобы определить, какие dll-файлы следует скопировать на компьютер клиента, или же запрашивает внутренние компоненты сборки для определения файлов зависимостей?

Причина, по которой я спрашиваю, состоит в том, что я получаю приведенную ниже ошибку ClickOnce при попытке запустить приложение WPF .NET 4, которое было опубликовано с ClickOnce: Файл C:\Users\CNelson\AppData\Local\Temp\Deployment\PGX6P33A.35N\AJQL8AC8.D60\tx16_rtf.dll уже существует.

Эта ошибка началась после того, как я включил ссылку на две сторонние DLL-библиотеки .NET, которые обе ссылаются на неуправляемый файл DLL (tx16_rtf.dll). Я хочу, чтобы файл tx16_rtf.dll был скопирован в папку bin на компьютере клиента, поэтому я включил его в свой проект и установил для параметра «Действие сборки» значение «Содержимое», а для параметра «Копировать в выходной каталог» - «Всегда копировать».

Однако по какой-то причине при попытке запустить приложение 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 ]

11 голосов
/ 02 августа 2011

Как добавляется файл в вашем решении Visual Studio?Пожалуйста, попробуйте следующее.

Добавьте dll в ваш проект.

Если у вас есть ссылка на dll в References, установите свойства на dll следующим образом: Build Action = none, Copyна выходной каталог = "не копировать".Затем удалите ссылку, а затем повторно добавьте ссылку, но укажите на эту DLL в вашей локальной папке проекта.В разделе «Ссылка» установите для «copy local» значение true.

Если у вас нет ссылки на dll, установите свойства на dll следующим образом: Build Action = "copy".Copy to Output Directory = "Копировать всегда".

Если у вас есть ссылка, вы хотите, чтобы причина ее включения основывалась на ссылке, а не на свойствах dll.Если у вас нет ссылки, вы хотите установить dll специально для включения.

Также проверьте диалоговое окно «Файлы приложения» и убедитесь, что dll не помечен как «Включить» (Prerequisite), но имеет значение «Включить» илиВключите (обязательно).

8 голосов
/ 21 декабря 2011

Вы не упоминаете, используете ли вы замечательный ( кашель ) MAGE.EXE для генерации манифеста развертывания. Однако я столкнулся с той же ошибкой «Файл x уже существует», и она вызвана управляемыми сборками, которые вызывают функции в собственных сборках через P / Invoke.

Для каждой управляемой сборки в местоположении, указанном аргументом -FromDirectory в MAGE.EXE, MAGE создаст набор <dependency><dependentAssembly>...</dependentAssembly></dependency> элементов (включая кодовую базу сборки, идентификатор, размер, хэш и т. Д.). Для каждого другого файла (включая неуправляемые собственные сборки) MAGE.EXE создаст элемент <file>...</file>.

Однако во время установки, похоже, что ClickOnce фактически проверяет метаданные манифеста каждой управляемой сборки. Поэтому, если в вашем приложении есть ManagedAssemblyA, которая вызывает P / вызывает код в 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, чтобы подписать манифест.

0 голосов
/ 17 января 2019

Это также может произойти, если вы иногда ссылаетесь на .csproj, а иногда и на компиляцию .dll

например:.

Main.csproj:
  ref A.csproj
  ref B.csproj
A.csproj
  ref B.dll
0 голосов
/ 06 марта 2017

Консолидация ваших пакетов Nuget, если у вас есть 2 ссылки, которые зависят от разных версий третьего пакета Nuget, иногда вы можете иметь 2 ссылки на один и тот же пакет Nuget. Это приведет к сбою Clickonce.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...