2

リモートサーバーからexeを更新したい。したがって、ボタンが私のwpfアプリケーションをクリックすると、リモートとリモートのtxtファイルがダウンロードされ、exeが実行されている同じフォルダー内の現在のファイルが置き換えられます。したがって、exeの実行中に現在のtxtおよびexeファイルが上書きされます。どうすればこれを達成できますか?

リモートホストはURLのようなものですwww.mydomain.com/MyAPP.exe

wpf アプリケーション、c# 4.0

4

3 に答える 3

2

解決策は、特定のケースによって異なります。ただし、アセンブリがメモリに読み込まれて使用されている間はアセンブリを更新できないため、直接的な解決策はありません。2 つの解決策を提案できます。シャドウ コピーを使用する方法と、何らかのヘルパー実行可能ファイルを使用する方法です。私はそれらの両方を使用しました。

シャドウコピー。

明らかな方法は、メインの実行可能ファイルをシャドウ コピーし、アプリの実行中に置き換えてから、アプリを再起動することです。ただし、既定のアプリ ドメインをシャドウ コピーすることはできません。セカンダリ アプリ ドメインのみをシャドウ コピーできます。ただし、すべてのコードを別のアセンブリ (MainAppLib.dll など) に移動し、メイン アプリの実行可能ファイル (MainApp.exe) を書き換えて、"ローダー コード" のみを含めることができます。このローダー コードは、別のアプリ ドメインを作成し、それをシャドウ コピーするように設定してから、セカンダリ アプリ ドメインでプログラム ロジックを実行する必要があります。メイン アプリ ドメインから MainAppLib.dll への直接参照を持たないように注意してください。これは、このアセンブリがシャドウ コピーされないメイン アプリ ドメインに読み込まれ、アセンブリ ファイルがロックされるためです。ほとんどの場合、あなたは一緒に行くことができますAppDomain.ExecuteAssembly()メソッド。

ヘルパー実行可能ファイル

アイデアは、ある種の更新フィニッシャーを使用することです。メインアプリは変更されず、少量のコードを追加するだけで、アプリが更新をダウンロードして一時フォルダーに配置し、メインアプリが更新フィニッシャーを開始して (別のプロセスで) 終了します。更新フィニッシャーは、アプリが閉じるまで待機し、新しいファイルを一時フォルダーからアプリ フォルダーにコピーして、すべてのファイルを置き換えます。更新フィニッシャーは、それ自体の実行可能ファイルを置き換えることはできませんが、更新フィニッシャーを開始する前に、メイン アプリケーションによって行うことができます。ファイルをコピーした後、フィニッシャーはアプリケーションを実行します。

ps個人的には、アプリドメイン、リフレクション、アセンブリなどを使用したある種のブードゥーマジックが含まれ、必要に応じてプラグインを使用するように進化できるため、前者のソリューションを好みます(たとえば、MEFフレームワーク経由)。ただし、特にアプリ ドメインや手動アセンブリの読み込みを行ったことがない場合は、後者の方が理解しやすく、非常に簡単です。

于 2011-12-07T02:24:15.090 に答える
2

この問題を解決した方法は、クライアント マシンに最初にインストールおよび展開されたシェル exe を作成することでした。

「実際の」実行可能プログラムは、この初期アプリのサブディレクトリに保存されます。シェル アプリが起動されると、実際のアプリの更新プログラムをダウンロードしてインストールした後、別の AppDomain で実際のアプリの実行可能ファイルを起動します。

シェル アプリ内から起動する「実際の」アプリのコアは次のとおりです。

        System.AppDomainSetup oSetup = new System.AppDomainSetup();
        string sApplicationFile = null;

        // Use this to ensure that if the application is running when the user performs the update, that we don't run into file locking issues.
        oSetup.ShadowCopyFiles = "true";
        oSetup.ApplicationName = sAppName;

        // Generate the name of the DLL we are going to launch
        sApplicationFile = System.IO.Path.Combine(sApplicationDirectory, sAppName + ".exe");

        oSetup.ApplicationBase = sApplicationDirectory;
        oSetup.ConfigurationFile = sApplicationFile + ".config";
        oSetup.LoaderOptimization = LoaderOptimization.MultiDomain;

        // Launch the application
        System.AppDomain oAppDomain = AppDomain.CreateDomain(sAppName, AppDomain.CurrentDomain.Evidence, oSetup);
        oAppDomain.SetData("App", sAppName);
        oAppDomain.SetData("User", sUserName);
        oAppDomain.SetData("Pwd", sUserPassword);

        oAppDomain.ExecuteAssembly(sApplicationFile);

        // When the launched application closes, close this application as well
        Application.Exit();

このバージョンでは、更新 Web サイトに正しくアクセスするために、シェル アプリがユーザーからユーザー名とパスワードを収集することに注意してください。SetDataこのデータは、AppDomainのメソッドを介して「実際の」アプリに渡されます。

于 2011-12-07T01:36:24.947 に答える
1

おそらくClickOnceを使用できます(上記のコメントに基づいて、別のアセンブリにexeを取得させる準備ができています....他のポスターが実行中のアセンブリを置き換えることはできないと述べています)。さまざまな時点 (起動時など) に新しいバージョンをチェックして、自動的にダウンロードするように構成できます。これは非常に堅牢なソリューションであり、展開アセンブリで多くのことができます。

于 2011-12-07T02:57:04.590 に答える