Das programmgesteuerte Aktualisieren des Bereitstellungsmanifests für eine ClickOnce-Anwendung führt dazu, dass das in 4.0 erforderliche <compatibleFrameworks> -Element fehlt

Ich arbeite an der Automatisierung des Installationsprogramms für eine .NET 4.0-ClickOnce-WPF-Anwendung, für die einige Elemente in der festgelegt werden müssenapp.config Datei. Ich habe den schwierigen Prozess durchlaufen, bestimmte Schritte zu finden, denen ich folgen mussMage.exe (dh Aktualisieren und erneutes Signieren von Anwendungs- und Bereitstellungsmanifesten) und versuche nun, diese für die Installation zu automatisieren.

Ich habe mich für die Verwendung entschieden.deploy Erweiterung zur Minimierung von Problemen mitIIS/ Internet Explorer Sicherheitsmechanismen, so dass im Wesentlichen der Algorithmus wie folgt ist (basierend aufSignieren und erneutes Signieren von Manifesten in ClickOnce (Saurabh Bhatia) undAktualisieren Sie die Konfiguration einer ClickOnce WPF-Anwendung mit Mage oder MageUI, unter anderem als Hauptquelle):

Gehe zum\Application Files\App_%HighestVersion%\ MappeLöschen.deploy Erweiterung für Dateien, die es habenLaufmage -u %app%.exe.manifest -cf cert.pfxWiederherstellen.deploy ErweiterungLaufmage -u %app%.application -appm %app%.exe.manifest -cf cert.pfxKopieren%app%.application 2 Ebenen (bis..\.. - Bereitstellungsstamm)

Das funktioniert perfekt, wenn es manuell gemacht wird. Ich kann ein laufen.cmd Datei, angepasst für umgebungsspezifische Besonderheiten (Pfade usw.), aber dann müsste ich einschließenmage.exe Ob Microsoft dies zulässt, ist für mich eine offene Frage. Daher versuche ich, ähnliche Aktionen im Internet durchzuführenInstaller Klasse:

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);

Hier ist der Kicker. Mit Ausnahme von Schritt 5 funktioniert alles einwandfrei. Wenn die Anwendung auf den Computer des Benutzers heruntergeladen wird, liegt ein Problem mit dem Bereitstellungsmanifest vor:

Das Bereitstellungsmanifest ist semantisch nicht gültig.Bereitstellungsmanifest fehlt <compatibleFrameworks>.

In der Tat ist dieser Abschnitt nicht mehr vorhanden (Es befand sich jedoch in der ursprünglichen% app% .application!). Ein ähnliches Ergebnis wird in beschriebenClickOnce - .NET 4.0-Fehler: "Bereitstellungsmanifest ist nicht semantisch gültig" und "Bereitstellungsmanifest fehlt <compatibleFrameworks>", ist aber ein Ergebnis eines anderen Prozesses (msbuild). Dieser Abschnitt ist neu (und erforderlich) für 4.0-Manifeste. Meine einzige Vermutung ist also, dass ManifestWriter, wenn er Änderungen auf der Festplatte beibehält, diese auf 3.5-Art und Weise ausführt. Ich habe dreimal überprüft, ob eine richtige Bibliothek verwendet wird (C: \ Programme (x86) \ Reference Assemblies \ Microsoft \ Framework.NETFramework \ v4.0 \ Microsoft.Build.Tasks.v4.0.dll).Was gibt?

Anstelle einer Antwort habe ich bisher versucht, den fehlenden Abschnitt manuell hinzuzufügen:

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);

Aber das hat keine Auswirkung, egal wo ich diesen Code platzieredm.ResolveFiles (), dm.UpdateFileInfo () oderManifestWriter.WriteManifest (..)!

Mein Ergebnis ist ähnlich wie bei Fragen zum StapelüberlaufMageUI.exe entfernt das compatibleFrameworks-Element oderWarum generiert Mage.exe kein compatibleFrameworks-Attribut? oderMageUI.exe enthält kein compatibleFrameworks-Element, aber ich benutze nichtmageui, mage oder auchmsbuild überhaupt!

Was ist los?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage