7

app.configファイルにいくつかの項目を設定する必要がある .NET 4.0 ClickOnce WPF アプリケーションのインストーラーの自動化に取り組んでいます。Mage.exeを使用して従わなければならない特定の手順(つまり、アプリケーション マニフェストと配置マニフェストの更新と再署名)を見つけるという厄介なプロセスを経て、現在、インストールのために自動化しようとしています。

IIS / Internet Explorer セキュリティ メカニズムの問題を最小限に抑えるために.deploy拡張子を使用することを選択したため、基本的にアルゴリズムは次のとおりです ( ClickOnce でマニフェストに署名および再署名する (Saurabh Bhatia)およびMage を使用した ClickOnce WPF アプリケーションの構成の更新に基づく)。または MageUI、とりわけ主要なソースとして):

  1. \Application Files\App_%HighestVersion%\フォルダに移動
  2. .deploy拡張子を持つファイルの拡張子を削除します
  3. 走る  mage -u %app%.exe.manifest -cf cert.pfx
  4. .deploy拡張子を復元する
  5. 走る  mage -u %app%.application -appm %app%.exe.manifest -cf cert.pfx
  6. %app%.application2 レベル上 ( ..\..- デプロイメント ルート)にコピーします。

手動で行うと完全に機能します。環境の詳細 (パスなど) に合わせてカスタマイズされた.cmdファイルを実行できますmage.exeが、展開に含める必要があり、Microsoft がそれを許可するかどうかは未解決の問題です。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);

さて、キッカーです。ステップ 5 を除いて、すべてが完全に機能します。アプリケーションがユーザーのマシンにダウンロードされると、配置マニフェストに問題があります。

  • 配置マニフェストが意味的に有効ではありません。
  • 配置マニフェストに <compatibleFrameworks> がありません。

実際、このセクションはもう存在しません (ただし、元の %app%.application にはありました!)。同様の結果がClickOnce - .NET 4.0 エラー: "配置マニフェストがセマンティックに有効ではありません" および "配置マニフェストに <compatibleFrameworks> がありません"で説明されていますが、これは別のプロセス (msbuild) の結果です。このセクションは 4.0 マニフェストの新しい (そして必須の) セクションなので、私の唯一の推測では、ManifestWriter が変更をディスクに永続化するときに、3.5 の方法でそれを行うのではないでしょうか? 正しいライブラリが使用されていることを 3 回確認しました (C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0\Microsoft.Build.Tasks.v4.0.dll)。 何を与える?

これまでの回答の代わりに、不足しているセクションを手動で追加しようとしました:

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

しかし、このコードをdm.ResolveFiles( )dm.UpdateFileInfo( )またはManifestWriter.WriteManifest(..)の前のどこに配置しても効果はありません。

私の結果は、スタック オーバーフローの質問に似てますまたはMageUI.exe には compatibleFrameworks 要素が含まれていませんが、私は を使用していない かmageui、まったく使用していません!magemsbuild

どうしたの?

4

2 に答える 2

9

自分でそれを理解しました。犯人はManifestReader.ReadManifest( "DeployManifest", sPathMft, true )です。

MSDNによると、[preserveStream 引数] は、「結果のマニフェスト オブジェクトの InputStream プロパティで入力ストリームを保持するかどうかを指定します。オブジェクト表現で表されない入力を再構成するために ManifestWriter によって使用されます。」

言い回しはさておき、trueを設定するだけでは十分ではありません dm.CompatibleFrameworks.Count。0 のままですが、CompatibleFrameworkアイテムを追加すると効果があります!

同じボートに乗っている他の誰かのために、私は前にそれをします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、あなたの提案をありがとう!同意しますが、私は (XML よりも) API オブジェクトを使用する方が好きです。
もう 1 つの方法は、mage(直接または .cmd ファイルから)呼び出すことです。再配布が許可されているようです。


次の部分も追加しました。これは質問自体には影響しませんが、同じパスをたどる人にとっては非常に重要かもしれません ( /clientは展開ルートであり、カスタマイズできます)。

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;

2019-Oct-08展開中に:要素のあるセクションが取り除かれる
という問題に遭遇しました。app.manifest
compatibilitysupportedOS

同じ根本原因; それを読んでいる行はtruepreserveStreamに設定する必要があります:

ApplicationManifest am = ManifestReader.ReadManifest( "ApplicationManifest", sPathMft, true ) as ApplicationManifest;
于 2012-06-21T19:29:17.367 に答える