c# - tutorial - La actualización del manifiesto de implementación para una aplicación ClickOnce resulta programáticamente en el elemento faltante<compatibleFrameworks>, requerido en 4.0
clickonce vb net 2010 (2)
Me imaginé a mí mismo. El culpable es ManifestReader.ReadManifest ("DeployManifest", sPathMft, true ) .
MSDN dice que [el argumento preserveStream] "especifica si se preservará la secuencia de entrada en la propiedad InputStream del objeto manifiesto resultante. Utilizado por ManifestWriter para reconstituir la entrada que no está representada en la representación del objeto".
Dejando a un lado la redacción, la configuración verdadera no es suficiente por sí misma: dm.CompatibleFrameworks.Count
seguirá siendo 0, ¡pero ahora la adición de los elementos de CompatibleFramework
tendrá un efecto!
Para alguien más en el mismo barco, lo hago antes de dm.ResolveFiles( )
:
if( dm.CompatibleFrameworks.Count <= 0 )
{
CompatibleFramework cf= new CompatibleFramework( );
cf.Profile= "Client"; cf.Version= "4.0"; cf.SupportedRuntime= "4.0.30319";
dm.CompatibleFrameworks.Add( cf ); // cf= new CompatibleFramework( );
cf.Profile= "Full"; // cf.Version= "4.0"; cf.SupportedRuntime= "4.0.30319";
dm.CompatibleFrameworks.Add( cf ); /// no need for separate object
}
@davidair, ¡gracias por tu sugerencia! De acuerdo, aunque prefiero trabajar con objetos API (en comparación con XML).
Otra alternativa es llamar a mage
(directamente o desde un archivo .cmd), ya que parece que podemos redistribuirlo.
También agregué la siguiente porción, que no afecta la pregunta en sí misma, pero puede ser bastante importante para cualquiera que siga la misma ruta ( / client es la raíz de implementación y se puede personalizar):
dm.DeploymentUrl= string.Format( "http://{0}/{1}/client/{1}.application",
Dns.GetHostName( ), Context.Parameters[ scTokVirtDir ] );
dm.UpdateMode= UpdateMode.Background;
dm.UpdateUnit= UpdateUnit.Weeks;
dm.UpdateInterval= 1;
dm.UpdateEnabled= true;
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 aplicaciones y manifiestos de implementación) y ahora estoy tratando de automatizarlo para la instalación.
Opté por usar la extensión .deploy para minimizar los problemas con los mecanismos de seguridad de IIS / Internet Explorer, así que básicamente el algoritmo es el siguiente (basado en Firmar y volver a firmar manifiestos en ClickOnce (Saurabh Bhatia) y Actualizar configuración de una aplicación ClickOnce WPF usando Mago o MageUI , como fuentes primarias entre otras):
- Vaya a la carpeta
/Application Files/App_%HighestVersion%/
- Retire la extensión .deploy para los archivos que lo tienen
- Ejecutar
mage -u %app%.exe.manifest -cf cert.pfx
- Restaure la extensión .deploy
- Ejecutar
mage -u %app%.application -appm %app%.exe.manifest -cf cert.pfx
- Copie
%app%.application
2 niveles hacia arriba (a../..
- raíz de despliegue)
Eso funciona perfectamente si se hace manualmente. Puedo ejecutar un archivo .cmd , personalizado para detalles del entorno (rutas, etc.), pero luego necesitaría 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 realizar 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í está el pateador . 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.
- El manifiesto de implementación falta <compatibleFrameworks>.
De hecho, esta sección ya no está presente (¡ sin embargo, estaba en la aplicación original% app% !). Un resultado similar se describe en ClickOnce - Errores de .NET 4.0: "El manifiesto de implementación no es semánticamente válido" y "El manifiesto de implementación falta <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). ¿Lo que da?
En lugar de una respuesta hasta el momento, traté de agregar la sección faltante 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 coloque este código, antes de dm.ResolveFiles () , dm.UpdateFileInfo () o ManifestWriter.WriteManifest (..) !
Mi resultado es similar a las preguntas de desbordamiento de pila. MageUI.exe elimina el elemento compatibleFrameworks o ¿Por qué Mage.exe no genera un atributo compatible FrameFrameworks? o MageUI.exe no incluye un elemento compatible FrameFramework , ¡pero no estoy usando mageui
, mage
o incluso msbuild
en absoluto!
¿Que esta pasando?
También necesitaba agregar CompatibleFrameworks. También intenté agregar el CompatibleFrameworks como este (que no funciona)
dm.CompatibleFrameworks.Add(...);
Mi solución fue establecer:
dm.TargetFrameworkMoniker = ".NETFramework,Version=v4.0";
Después de esto, la generación Manifiesto fue correcta.
Tenga cuidado Si configura TargetFrameworkMoniker antes de WriteManifest tiene <compatibleFrameworks> dos veces y su archivo de aplicación está dañado. Aquí está mi solución para esto:
DeployManifest dm = ManifestReader.ReadManifest("DeployManifest", applicationFileName, false) as DeployManifest;
dm.ResolveFiles();
//doing stuff..
dm.UpdateFileInfo();
ManifestWriter.WriteManifest(dm, applicationFileName);
dm.TargetFrameworkMoniker = ".NETFramework,Version=v4.0";
ManifestWriter.WriteManifest(dm, applicationFileName);