Подтвердить что ты не робот

ClickOnce - Файл уже существует Ошибка - Почему DLL файл пытается скопировать дважды ClickOnce?

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

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

Эта ошибка началась после того, как Ive включил ссылку на две сторонние .NET-библиотеки DLL, которые ссылаются на неуправляемый 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>
4b9b3361

Ответ 1

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

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

Если у вас есть ссылка на dll в ссылках, установите свойства в dll следующим образом: Build Action = none, Copy to output directory = "do not copy". Затем удалите ссылку, а затем повторно добавьте ссылку, но укажите ее в локальной папке проекта. В REFER установите для параметра "copy local" значение true.

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

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

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

Ответ 2

Вы не упоминаете, если вы используете замечательный (кашель) 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 script, который вызывает MAGE.EXE, чтобы создать манифест развертывания, еще несколько Powershell, чтобы манипулировать XML и удалить элемент <file> (очень просто с Powershell... удачи, делая это с помощью командного файла!), затем мы вызываем MAGE.EXE, чтобы подписать манифест.

Ответ 3

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

Ответ 4

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

Например:

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