ユーザーが以前のバージョンの ClickOnce ネットワークにデプロイされたアプリケーションに戻ることを許可する方法(ハッキーは行います)はありますか?
私はドキュメントとAPIを調べましたが、方法がないようです。君は できる 更新するかどうかを選択的に選択しますが、更新すると、元に戻す方法がないようです。
ClickOnceは、送信したバージョンを使用します。古いバージョンを送信すると、古いバージョンにロールバックされます。
5月に、私の仲間のDavidがユーザーごとにこれを行う方法についての記事を書きました。文字通り、すべてのユーザーを異なるバージョンにすることができます。アプリケーションは、ユーザーが必要とするバージョンをデータベースに通知することもできるため、理論的にはユーザーがバージョンを変更してから、アプリケーションを再起動するだけで済みます。
サーバーマニフェストファイルを変更することにより、サーバー側で以前のバージョンに戻すことができます。クライアントがアプリケーションを再起動すると、サーバーの「現在の」バージョンとは異なるバージョンであることがわかり、新しいバージョンがダウンロードされます。通常、このサーバーマニフェストファイルは常に最新バージョンを指しますが、そうである必要はありません。
これを変更する方法は次のとおりです(Visual Studio 2008を使用して公開しました。他のバージョンでは公開フォルダーの構造が異なる場合があります)。
Publish.htmと同じフォルダーに[appName].application
と呼ばれる [〜#〜] xml [〜#〜] ドキュメントがあります。これは、クライアントが現在のバージョンと比較するために使用するサーバー側のマニフェストファイルです。このドキュメントには、クライアントが実行する必要がある「現在の」バージョンと、デプロイメントファイルを見つけることができるサーバー上の場所が含まれています。
publish.htm
と同じ場所に、「アプリケーションファイル」というフォルダもあります。このフォルダーには、以前の各発行のサブフォルダーが含まれています。これらの各サブフォルダー内には、前述の[appName].application
と同じ名前の別のXMLドキュメントがあります。このファイルを(元に戻すバージョンが含まれている任意のフォルダーから)コピーし、publish.htm
と同じフォルダー(2つ上のレベル)に貼り付けます。クライアントアプリケーションが再起動すると、新しいバージョンが利用できるように表示され、ダウンロードして実行します。クライアントは以前のバージョンを実行します。
アプリケーションの追加と削除に移動し、アプリケーションを選択して、代わりに最後のインストールを取得することを選択できます。
[〜#〜] mageui [〜#〜] を使用して、サーバー上の以前のマニフェストバージョンにロールバックできます。 これをチェックしてください 。
これを使用して、Visual Studio 2017で開発されたクリックワンスアプリケーションをロールバックしました。私の場合、ルートフォルダーには2つのファイルしかありませんでした。 1つは[applicationName] .manifest、もう1つはsetup.exeです。
[applicationName] .manifestには、現在のバージョン番号への番号参照が含まれていましたが、それぞれがpublicKeyToken値にリンクされていたため、手動で編集するのは嫌でした。
したがって、Application Filesフォルダーで、ロールバックしたいバージョンが含まれているサブフォルダーの下に、別の[applicationName] .manifestが見つかりました。これをルートフォルダーにコピーしました(元のファイルをバックアップしています)。
そして、それはそれでした。それは私にとってはうまくいき、本当に簡単な解決策でした。ただし、最低限必要なバージョンを使用していないため、それが影響するかどうかはわかりません。
デプロイメントの場所を見ると、バージョン番号が追加された個別のフォルダー内のすべての以前のバージョンと、バージョン番号が追加されたデプロイメントマニフェストが表示されます。
それらのいずれか1つを現在のデプロイメントに名前変更することができ、次にそのアプリケーションを更新するときに、ロールバックしたバージョンがプルされます。
ClickOnceバージョンチェックのアルゴリズムを次のように理解しています。
これは、発行元 [〜#〜] uri [〜#〜] と、デプロイメントとアプリケーションの両方の名前、バージョン言語の公開鍵トークン、およびプロセッサアーキテクチャがわかっている場合に、リフレクションを介して実行できます。
以下のコードは "coolapp.app" ClickOnce アプリケーションをロールバックしようとします。ロールバックできない場合は、アンインストールを試みます。
using System;
using System.Deployment.Application;
using System.Reflection;
namespace ClickOnceAppRollback
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
string appId = string.Format("{0}#{1}, Version={2}, Culture={3}, PublicKeyToken={4}, processorArchitecture={5}/{6}, Version={7}, Culture={8}, PublicKeyToken={9}, processorArchitecture={10}, type={11}",
/*The URI location of the app*/@"http://www.Microsoft.com/coolapp.exe.application",
/*The application's assemblyIdentity name*/"coolapp.app",
/*The application's assemblyIdentity version*/"10.8.62.17109",
/*The application's assemblyIdentity language*/"neutral",
/*The application's assemblyIdentity public Key Token*/"0000000000000000",
/*The application's assemblyIdentity processor architecture*/"msil",
/*The deployment's dependentAssembly name*/"coolapp.exe",
/*The deployment's dependentAssembly version*/"10.8.62.17109",
/*The deployment's dependentAssembly language*/"neutral",
/*The deployment's dependentAssembly public Key Token*/"0000000000000000",
/*The deployment's dependentAssembly processor architecture*/"msil",
/*The deployment's dependentAssembly type*/"win32");
var ctor = typeof(ApplicationDeployment).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(string) }, null);
var appDeployment = ctor.Invoke(new object[] { appId });
var subState = appDeployment.GetType().GetField("_subState", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(appDeployment);
var subStore = appDeployment.GetType().GetField("_subStore", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(appDeployment);
try
{
subStore.GetType().GetMethod("RollbackSubscription").Invoke(subStore, new object[] { subState });
}
catch
{
subStore.GetType().GetMethod("UninstallSubscription").Invoke(subStore, new object[] { subState });
}
}
}
}
私はライブの本番サーバーでこれらの1つを実行する必要があり、これらすべてのメモを用意できてよかったです。私のソリューションは少し異なっていたので、これも修正として追加したかったのです。本番環境での展開を行う前に、常に、含まれているフォルダ全体を常に事前にバックアップします。フォルダ構造全体を元の状態にコピーでき、すべてが正常に機能しました。
この方法での注意事項: