Estoy trabajando en la automatización del instalador para una aplicación .NET 4.0 ClickOnce WPF, que necesita algunos elementos para establecerse en el archivo app.config. He pasado por el espinoso proceso de encontrar pasos específicos que debo seguir usando Mage.exe (es decir, actualizar y volver a firmar los manifiestos de implementación y aplicación) y ahora estoy tratando de automatizarlo para la instalación.Actualizando el manifiesto de despliegue para una aplicación ClickOnce programmatically resulta en un elemento faltante <compatibleFrameworks>, requerido en 4.0
he optado por utilizar .deploy extensión a minimizar los problemas con IIS/Internet mecanismos de seguridad Explorer, por lo que en esencia el algoritmo es el siguiente (basado en Signing and re-signing manifests in ClickOnce (Saurabh Bhatia) y Update Configuration of a ClickOnce WPF Application Using Mage or MageUI, como fuentes primarias entre otros):
- Ir a la carpeta
\Application Files\App_%HighestVersion%\
- Retire .deploy ext ensión de los archivos que tienen que
- Run
mage -u %app%.exe.manifest -cf cert.pfx
- Restaurar .deploy extensión
- Run
mage -u %app%.application -appm %app%.exe.manifest -cf cert.pfx
%app%.application
Copia 2 niveles arriba (a..\..
- raíz de implementación)
que las obras perfectamente si se hace manualmente. Puedo ejecutar un archivo .cmd, personalizado para detalles del entorno (rutas, etc.), pero luego tendría que incluir mage.exe
en la implementación, y si Microsoft nos permite hacer eso es una pregunta abierta para mí. Por lo tanto, estoy tratando de llevar a cabo acciones similares en la clase Installer
:
X509Certificate2 ct = new X509Certificate2(sPathCert);
// .. Remove .deploy extension (for files in the sPathApp folder).
sPathMft = Directory.GetFiles(sPathApp, "*.exe.manifest")[0];
ApplicationManifest am = ManifestReader.ReadManifest("ApplicationManifest", sPathMft, false) as ApplicationManifest;
if (am == null)
throw new ArgumentNullException("AppManifest");
am.ResolveFiles();
am.UpdateFileInfo();
ManifestWriter.WriteManifest(am, sPathMft);
SecurityUtilities.SignFile(ct, null, sPathMft);
// .. Restore .deploy extensions to files touched above.
sPathMft = Directory.GetFiles(sPathApp, "*.application")[0];
DeployManifest dm = ManifestReader.ReadManifest("DeployManifest", sPathMft, false) as DeployManifest;
if (dm == null)
throw new ArgumentNullException("DplManifest");
dm.ResolveFiles();
dm.UpdateFileInfo();
ManifestWriter.WriteManifest(dm, sPathMft);
SecurityUtilities.SignFile(ct, null, sPathMft);
File.Copy(sPathMft, sPathBin + "\\" + dm.AssemblyIdentity.Name, true);
Ahora, aquí viene lo bueno. Todo funciona perfectamente con excepción del paso 5. Cuando la aplicación se descarga a la máquina del usuario hay un problema con el manifiesto de implementación:
- El manifiesto de implementación no es semánticamente válido.
- manifiesto de implementación falta < compatibleFrameworks>.
De hecho, esta sección ya no está presente (Sin embargo, fue en la aplicación original%% .Application!). Se describe un resultado similar en ClickOnce - .NET 4.0 errors: "Deployment manifest is not semantically valid" and "Deployment manifest is missing <compatibleFrameworks>", pero es el resultado de un proceso diferente (msbuild). Esta sección es nueva (y obligatoria) para los manifiestos 4.0, así que mi única suposición es que, de alguna forma, cuando ManifestWriter persiste en los cambios al disco, ¿lo hace de forma 3.5? Comprueba tres veces que se utiliza una biblioteca correcta (C: \ Archivos de programa (x86) \ Reference Assemblies \ Microsoft \ Framework.NETFramework \ v4.0 \ Microsoft.Build.Tasks.v4.0.dll). ¿Qué ofrece?
En lugar de una respuesta hasta ahora tratado de agregar la sección que falta manualmente:
dm.CompatibleFrameworks.Clear(); // Unnecessary as dm.CompatibleFrameworks.Count == 0 indeed!
CompatibleFramework cf = new CompatibleFramework();
cf.Version= "4.0";
cf.SupportedRuntime = "4.0.30319";
cf.Profile= "Client";
dm.CompatibleFrameworks.Add(cf);
cf = new CompatibleFramework();
cf.Version = "4.0";
cf.SupportedRuntime = "4.0.30319";
cf.Profile = "Full";
dm.CompatibleFrameworks.Add(cf);
Pero eso no tiene ningún efecto, no importa dónde colocar este código, antes de dm.ResolveFiles() , dm.UpdateFileInfo() o ManifestWriter.WriteManifest (..)!
Mi resultado es similar al de la pila de desbordamiento preguntas MageUI.exe removes compatibleFrameworks element o Why does Mage.exe not generate a compatibleFrameworks attribute? o MageUI.exe is not including a compatibleFrameworks element, pero no estoy usando mageui
, mage
o incluso msbuild
en absoluto!
¿Qué está pasando?
Como solución, ¿ha intentado manipular directamente el manifiesto XML en lugar de utilizar las API? Funcionó para nosotros en el pasado: usted tiene control total sobre los contenidos, hace lo que quiera, y luego vuelve a firmar el archivo una vez que haya terminado. –
Astrogator: ¿hay alguna posibilidad de que puedas compartir tus scripts? Estoy a punto de comenzar un proceso muy similar. ¡Gracias! –
¡Hola @ErickT! Bueno, el algoritmo está bastante establecido aquí. Este código es ejecutado por msiexec.exe a través de una acción personalizada, que especifico en el proyecto de instalación de Visual Studio 2010 - no hay 'scripts' per se. Avíseme, si eso no es lo suficientemente claro, y trataré de exponer más. – Astrogator