Visual studio(C#)でコンパイルした、  
Windows EXE実行ファイルのリリースについて質問です。

バッチシステムとしてタスクスケジューラーで起動させますが、  
頻繁にシステム改修があり、都度リリースが必要です。

しかし、システム実行中にリリース(EXEファイルの上書き)を行うと、  
起動中のため上書きエラーとなります。

実行中のEXEに対して、  
次回の実行分から最新のシステム改修を反映させるには、  
どのようにしたら良いでしょうか？

以下私の案がございますが、スマートではありませんし、  
実行開始に時間がかかるデメリットがございます。  
他にスマートな案はございますでしょうか？

起動に関するフレームワークなどあるのでしょうか。

<案>  
1.処理開始時に本体EXEファイルをコピーして実行版EXEファイルを作成する(同一のEXEファイル)  
2.実行版EXEファイルを起動する  
3.実行中でも本体EXEファイルは上書き可能なため、本体EXEファイルに対してリリース(EXEファイルの上書き)を行う
CC BY-SA 4.0
2019-03-18T23:30:38.587
53535
2019-06-26T02:45:44.077
2019-06-26T02:45:44.077
2238
31841
question
c# visual-studio winexe
Windows EXE実行ファイルのリリースについて
システムを起動したまま、該当プログラムだけ入れ替えたいなら、  
以下のいずれかで該当プログラムを明示的に終了させてから入れ替えて、  
該当プログラムの再起動を行う方法が考えられます。

  1. 該当プログラムに、WM_CLOSE メッセージを投げて終了させる。
  2. 該当プログラムに、プログラムを終了させる機能を示すユーザー定義メッセージ処理を組み込み、それを投げて終了させる。
  3. 該当プログラムに、名前付きイベント等の通知でプログラムを終了させる機能を組み込んでおき、それを実行する。
  4. [TaskKill](https://docs.microsoft.com/ja-jp/windows-server/administration/windows-commands/taskkill)コマンドや、[TerminateProcess](https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-terminateprocess)APIで、該当プログラムを強制終了させる。  
該当プログラムは、強制終了されても問題ないように設計/製作しておく。

あと、これは裏技的ですが、実行中のプログラムでもリネームは出来ます。  
[プログラム実行中のEXEファイルのファイル名変更ができる！](http://vbnettips.blog.shinobi.jp/other/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E5%AE%9F%E8%A1%8C%E4%B8%AD%E3%81%AEexe%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%90%8D%E5%A4%89%E6%9B%B4%E3%81%8C%E3%81%A7%E3%81%8D%E3%82%8B%EF%BC%81)

  * 現行プログラムをリネーム
  * 新しいプログラムを同じ場所にコピー
  * プログラム起動後にリネームした古いファイルがあったら削除

正統的には、システムの再起動まで待てるのならば、Windows Sysinternalsの[PendMoves と
MoveFile](https://technet.microsoft.com/ja-
jp/sysinternals/bb897556.aspx)ツールが使えるでしょう。  
ツールで使っている[MoveFileEx](https://docs.microsoft.com/en-
us/windows/desktop/api/winbase/nf-winbase-movefileexw)APIを使って自分でツールを作っても良いですし。

多数のファイルがあって、依存関係とか設定変更などがあるなら、Windows Installerに沿ったインストールパッケージを作成した方が良いでしょう。  
こんなツールがあります。[WiX チュートリアル 日本語訳](https://wix-tutorial-ja.github.io/)

* * *

@774RRさんコメントを見て検索したところ、確かにVisualStudioで簡単にできそうです。  
[アプリケーションを ClickOnce で発行する](https://sakapon.wordpress.com/2015/12/12/publish-
clickonce/)

ただしこんな情報もあって、今も適用されるか不明ですが、質問者さんの用途に合わないかも。  
[権限 -
ClickOnce](https://techinfoofmicrosofttech.osscons.jp/index.php?ClickOnce#ca961be1)

>
> 「ClickOnce」では、インターネット環境から不特定多数に向けて配信されるWebアプリケーションのような利用を可能とするために、インストールの垣根を下げる必要があり、管理者権限が無くてもインストールが可能となっている
> 。
>
>   * このため、インストール先（正確にはキャッシュ領域 ）は、”%USERPROFILE%\Local
> Settings\Apps”以下のディレクトリから変更することはできなくなっている（このためユーザ毎、別々にアプリケーションがストレージにキャッシュされることになる）。
>   *
> リソースやデータの保存先のストレージもこの環境変数「USERPROFILE」以下のディレクトリを使用するのが慣例となる（これは、セキュリティの関係上、他のユーザにデータを参照させないようにするためである。
>   * 「分離ストレージ」 を活用すれば、「ClickOnceアプリケーション」間のデータ保護も可能である）。
>

[UAC -
ClickOnce](https://techinfoofmicrosofttech.osscons.jp/index.php?ClickOnce#af95c055)

> 管理者権限を持つClickOnceアプリケーションを実行することはできない。  
>  ～途中省略～  
>  ここにはハックがあり、管理者権限を持つ新しいプロセスを開始することはできる。
CC BY-SA 4.0
2019-03-19T00:46:57.327
53537
2019-03-19T02:50:45.690
2019-03-19T02:50:45.690
26370
26370
53535
answer
正攻法としては[Windows Installer](https://docs.microsoft.com/en-
us/windows/desktop/msi/windows-installer-portal)です。ファイルが使用中の場合、[Restart
Manager](https://docs.microsoft.com/en-us/windows/desktop/msi/using-windows-
installer-with-restart-manager)を用いて再起動後の置き換えを試みます。再起動を好まないということでしたら選択肢から外れます。

774RRさんの提案されたClickOnceには自動更新機能があります。しかし、ClickOnceはデスクトップ画面での対話操作を前提としているので、タスクスケジューラーからの起動では正しく動作しない可能性があります。少なくともサービスとしての起動はサポートされていません。

これ以外となると起動に関するフレームワークは用意されていないと思います。

順当にローダープログラムと本体を分離することでしょうか。

  * インストーラーは本体プログラムを連番など一定のファイル名で配置する
  * ローダープログラムは最新を残して不要なファイルを削除する
  * ローダープログラムは最新の本体を起動する

といったところです。ローダープログラムは分かり易くPowerShellなどのスクリプト言語で記述するのもいいかもしれません。
CC BY-SA 4.0
2019-03-19T02:15:47.597
53538
2019-03-19T02:15:47.597
4236
53535
answer