2011-07-22 29 views
17

¿ClickOnce solo mira el archivo de manifiesto de la aplicación para determinar qué archivos dll copiar en la máquina del cliente o también interroga las partes internas de un conjunto para determinar los archivos de dependencia?ClickOnce - El archivo ya existe - ¿Por qué un archivo DLL intenta copiarse dos veces con ClickOnce?

La razón por la que estoy pidiendo es porque me estoy haciendo el siguiente error ClickOnce cuando se trata de lanzar una aplicación de WPF 4 .NET que se ha publicado con ClickOnce: C:\Users\CNelson\AppData\Local\Temp\Deployment\PGX6P33A.35N\AJQL8AC8.D60\tx16_rtf.dll El archivo ya existe.

Este error comenzó después de que he incluido una referencia a dos dlls de .NET de terceros que hacen referencia a un archivo dll no administrado (tx16_rtf.dll). Quiero que tx16_rtf.dll se copie en la carpeta bin de la PC del cliente, así que lo he incluido en mi proyecto y configuré Build Action en 'Content' y el directorio Copy to Output en 'Copy Always'.

Sin embargo, por algún motivo, cuando intento iniciar la aplicación, ClickOnce intenta copiar el archivo 'tx16_rtf.dll' dos veces, lo que da como resultado un error.

Si miro el archivo de manifiesto de despliegue, puedo ver claramente una y solo una entrada para el archivo 'tx16_rtf.dll'. Entonces, mi pregunta es, ¿por qué ClickOnce intenta copiar el archivo 'tx16_rtf.dll' dos veces si solo existe una vez en el archivo de manifiesto de despliegue?

A continuación se muestra un fragmento de la implementación de archivos de manifiesto que ‘tx16_rtf.dll’ referencias:

<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

¿Cuál fue su solución a este problema? –

+0

Mi solución fue no hacer referencia a las dlls no administradas en mi proyecto. Por lo tanto, ClickOnce no los incluirá en el manifiesto. En cambio, lo que hice fue incluir los archivos dll no administrados en un archivo zip (estableciendo Build Action en 'Content') y cuando mi aplicación se inicia, descomprimirá los dlls no administrados en el directorio de ejecución actual ... y todo funcionó como un encanto. – ChrisNel52

Respuesta

10

En la solución de Visual Studio, cómo se añade el archivo? Por favor intenta lo siguiente.

Agregue el dll a su proyecto.

Si tiene una referencia a la dll en Referencias, establezca las propiedades en la dll como esta: Acción de compilación = ninguna, Copiar al directorio de salida = "no copiar". Luego borre la referencia y luego vuelva a agregar la referencia, pero apunte a esa dll en su carpeta de proyecto local. En la referencia, configure "copiar local" en verdadero.

Si no tiene una referencia para el dll, establezca las propiedades en el dll como esta: Build Action = "copy". Copiar al directorio de salida = "Copiar siempre".

Si tiene una referencia, desea que el motivo para que se incluya se base en la referencia y no en las propiedades de dll. Si no tiene una referencia, quiere configurar el dll específicamente para ser incluido.

También verifique el cuadro de diálogo Archivos de la aplicación y asegúrese de que el dll no esté marcado como Incluir (Requisito previo), sino que sea Incluir o Incluir (Requerido).

+1

Automatizo la creación del archivo de manifiesto usando mage.exe. Siento que tengo una buena comprensión general de ClickOnce y los archivos de manifiesto, pero hay algo secreto que ClickOnce está haciendo con dlls no administrados. Sin embargo, tratar de encontrar documentación detallada sobre el funcionamiento interno de ClickOnce parece imposible. – ChrisNel52

+0

RobinDotNet su explicación me llevó a una respuesta para mi problema duplicado dll clickonce, así que le subí. – TWood

+13

Lamento haberme unido a la fiesta tarde, pero para beneficio de los buscadores, tuve un problema similar con Automapper.Net4.dll. El problema era que estaba haciendo referencia tanto a 'Automapper.Net4.dll' como a 'Automapper.dll', (que más tarde descubrí que hacía referencia al propio Net4.dll). Siguió el consejo anterior. Se eliminó la referencia de la que se quejaba ClickOnce, se eliminó la carpeta bin y se rehizo el proyecto. El Net 4 dll volvió a aparecer mágicamente, por lo que la referencia directa no era necesaria. No hay problemas con ClickOnce después de eso. – HockeyJ

8

No menciona si está utilizando el maravilloso (tos) MAGE.EXE para generar su manifiesto de implementación. Sin embargo, he encontrado el mismo error 'El archivo x ya existe', y es causado por los ensamblados administrados que llaman a funciones en ensamblajes nativos a través de P/Invoke.

Para cada ensamblado administrado en el lugar especificado por el argumento -FromDirectory a MAGE.EXE, MAGE creará un conjunto de elementos <dependency><dependentAssembly>...</dependentAssembly></dependency> (incluyendo el código base de montaje, la identidad, tamaño, hachís, etc.). Para cada otro archivo (incluidos los ensamblados nativos no administrados) MAGE.EXE creará un elemento <file>...</file>.

Sin embargo, al momento de la instalación, parece que ClickOnce realmente inspecciona los metadatos del manifiesto de cada ensamblaje administrado.Entonces, si su aplicación tiene ManagedAssemblyA que P/Invoca el código en NativeAssemblyB (o tx16_rtf.dll en su caso), verá a través de ILDASM que el manifiesto para ManagedAssemblyA tiene una declaración .module extern NativeAssemblyB.dll.

Solo puedo suponer que ClickOnce, mientras procesa el elemento <dependentAssembly codebase="ManagedAssemblyA.dll">, inspecciona los metadatos del conjunto, ve que hay un ensamblado nativo al que se hace referencia, ve que también está en la misma ubicación de implementación y lo copia. Luego, cuando más tarde procesa el elemento <file name="NativeAssemblyB.dll">, se produce un error ya que ya se ha copiado este archivo y se asume que no se puede instalar es el curso de acción más seguro. No he encontrado este comportamiento documentado por Microsoft en ninguna parte.

Entonces la solución es, después de generar el manifiesto de implementación con MAGE.EXE, pero antes de firmarlo, eliminar los elementos <file> para cualquier ensamblado nativo. Los ensamblados nativos todavía deben estar disponibles en la misma ubicación de implementación que el resto de ensamblajes requeridos por la aplicación ClickOnce.

En nuestro caso automatizamos esto ya que también automatizamos la generación del manifiesto de implementación con cada compilación de integración continua (en lugar de usar el Asistente de publicación dentro de Visual Studio 2010 que le da un poco más de control); tenemos un script de Powershell que invoca MAGE.EXE para crear el manifiesto de implementación, más Powershell para manipular el XML y eliminar el elemento <file> (realmente fácil con Powershell ... ¡buena suerte hacerlo con un archivo de proceso por lotes!), luego invocamos MAGE.EXE para firmar el manifiesto

+0

¡Gran respuesta! Voy a ver cómo implementar su solución. – ChrisNel52

0

Consolide sus paquetes nuget, si tiene 2 referencias que dependen de diferentes versiones de un tercer paquete nuget, a veces puede tener 2 referencias a un mismo paquete nuget. Esto hará que Clickonce falle.

Cuestiones relacionadas