職場で作っているアプリを、他の自社製アプリから起動させる時に引数を付けたいな~...
...という事で、ClickOnceアプリを引数を付けて起動する話ですが、
前提条件が弊社環境依存でキツ目なので、汎用性としてはイマイチかもしれません...(;^_^A
実現したいこと
- 外部アプリから引数を付けて起動できる事
- 新バージョンが存在する場合もバージョンアップ後に起動して引数を受け取れる事
今回の前提条件
- .NET Frameworkのアプリ ※WinForms/4.7.2で確認
- ClickOnce発行のアプリで、
- 公開のインストールモードが"アプリケーションはオフラインでも利用できる"である事
- マニフェスト"デスクトップショートカットを作成する"がON
- 更新オプション"アプリケーションの更新プログラムを確認する"がONで、"アプリケーションの開始前に行う"を選択
※"URLパラメータをアプリケーションに渡す事を許可する"はOFFで大丈夫です。
実装
※VisualStudio2019で検証しています。
先ずは.NET FrameworkのWinFormsアプリを作成。 ※"FWWinFormsClickOnce1"としています。
Form1にListBoxを1つ配置(listBox1)、Form1のLoadイベントを下記の通り記述します。
////usingは下記が必要
//using System.Deployment.Application; //必要
//using System.Diagnostics; //バージョン取得に必要
//using System.Reflection; //バージョン取得に必要
private void Form1_Load(object sender, EventArgs e)
{
//バージョン情報取得&表示
//(後に、ちゃんとバージョンアップされたかの確認用)
FileVersionInfo ver = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
listBox1.Items.Add($"<Ver.{ver.ProductVersion}>");
if (ApplicationDeployment.IsNetworkDeployed)
{
//ClickOnceで起動した場合
listBox1.Items.Add("<<< ClickOnceで起動 >>>");
if (AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData != null
&& AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData.Count() > 0)
{
//(第2引数以降は来ない模様)
listBox1.Items.AddRange(AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData);
}
}
else
{
//EXEを直接起動した場合(デバッガで動かしている時とか)
listBox1.Items.Add("<<< EXEを直接起動 >>>");
string[] args = Environment.GetCommandLineArgs();
listBox1.Items.AddRange(args);
}
}
上記が実行できる事を確認("EXEを直接起動"が動いて表示されるハズ)して、アプリを公開します。
※アプリケーションのアセンブリ情報を公開するバージョンと合わせておきます。
その他"今回の前提条件"に内容を揃えます。
公開後、公開フォルダに作成された"setup.exe"を実行してインストールします。
→上手く行けばデスクトップにショートカット"FWWinFormsClickOnce1.appref-ms"が作成されます。
実行&検証
さて、先ずはデスクトップのショートカットで起動してみましょう。
→バージョン情報と"ClickOnceで起動"だけが表示されているはずです。
続いて引数を付けて起動して見ましょう。
お手軽にコマンドプロンプトを開いて、ショートカットを落として引数2つを足しましょう。
C:\Users\xxxxx>C:\MyDesktop\FWWinFormsClickOnce1.appref-ms hoge1 hoge2
第1引数は無事に表示されました。
(もうソースのコメントには書いちゃっていますがw)
しかしAppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData には第2引数以降は入らないようです。
そこは工夫で何とかするという事で、空白を含めたい場合は呼び出し側で引数をダブルクォーテーションで括り、(ここでは扱いませんが)受け取り側で都合の良いように加工します。
C:\Users\xxxxx>C:\MyDesktop\FWWinFormsClickOnce1.appref-ms "hoge1 hoge2"
残るはバージョンアップ後に起動して引数を受け取れる事の確認。
アプリケーションのアセンブリ情報のバージョンを上げて、もう一度"公開"します。
(※手元の環境では公開バージョンを自動インクリメントにしています)
公開後に再度、コマンドプロンプトから以下を実行します。
C:\Users\xxxxx>C:\MyDesktop\FWWinFormsClickOnce1.appref-ms "hoge1 hoge2"
アプリケーションのバージョンアップと共に、無事に引数も渡せました!
最後に、呼び元のアプリケーション側のコードです。
//ターゲットアプリ起動
string app = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + @"\FWWinFormsClickOnce1.appref-ms";
if (!File.Exists(app))
{
//インストールされていない
MessageBox.Show("アプリをインストールして下さい");
return;
}
Process.Start(app, "\"hoge1 hoge2 hoge3!\"");
こちらは単純に、デスクトップのショートカットの存在有無でインストール判定、存在すれば引数を付けて実行します。
以上、使える前提は厳しめですが上手くハマるケースなら比較的お手軽に引数付き実行可能でした。
少しでも参考になれば幸いです!
参考サイト
ApplicationDeployment.IsNetworkDeployedについて、Kazzz's diaryさんの記事を、
スペシャルフォルダの取得方法について、DOBON.NETさんのページ
...を参考にさせて頂きました。多謝!