【Windows】アプリのインストーラをゼロから作ってみる
Unityなどで作成したアプリをユーザに配布する際にインストーラを作りたくなって,色々なインストーラを作成するフレームワーク(?)などを使ってみた。
しかし,どれも痒いところに手が届かず,色々カスタマイズしたければ自分で0から作ったほうが自由にできそうだったので,作ってみた。
それのメモ。
こういう感じのインストーラ。
Env.
Windows10 64bit
Methods
Windows Form Applicationという選択
何が正解なのかは分からないが,今回はWindows Form Application(.NET Framework)をテンプレートとして使った。
Visual Studioで新規のプロジェクトを作成するときに,Windows フォームアプリケーション(.NET Framework)を選択した。
考えたインストーラの仕事の流れ
今回はサーバから必要に応じて最新版のアプリをDLし,それをローカルで展開して,ProgramFilesに配置し,レジストリにあれこれ登録,ショートカットを適宜作成という流れになるようにした。
Windowsのアプリのインストールのお作法が自分は分からなかったため,フリーソフトなどをDLしてきてインストールしたときに,こういう感じの挙動になるよなーってことを考えながら,実装することにした。
本当にそれが正しいのかは分からないので,詳しい方誰か教えて下さい….()
インストールに関係するディレクトリ
これのお作法が一番分からんのだが,今回は以下のようにディレクトリを使うことにした。
大きく3つ。
インストール開始部分
この先はメモ書きとしてこの機能を作るときに頭の中で考えていたことベースに書いていく。
まずはUI。VisualStudio内でツールボックスから適宜配置した。
背景には好きな画像。
インストールディレクトリを設定するところと,今インストーラが何をやっているかが分かるようにするためにLabelを配置。
あと何かしらインストール時に動いているとちゃんと仕事しているということがユーザに分かるので,ProgressBarを配置。
あとはボタン,強制的にインストールを途中で止めたくなったら押すボタン,インストールを開始するボタン。
などを配置した。
サーバからアプリをDL
ここを参考にした。
https://dobon.net/vb/dotnet/internet/downloadfile.html
非同期にzipファイルをDLし,その進捗がProgressBarとLabelに反映されるようにした。
DL機能を作り始めたときに,最後の機能をつくるまでに並行して考えなければならないのが,途中で強制停止する機能。これを忘れないようにプログラムを書いていく。
今回DL対象のファイルを置いておくwebサーバは,nginxで適宜作成した。
アプリを展開し配置
今回DLきたファイルはzipで圧縮されているので,それを展開する。
展開は以下のメソッドで行った。
1 |
ZipFile.ExtractToDirectory(zipFIlePath, extractPath) |
これを非同期で待ってあげて,完了するまでLabelのテキストをチカチカさせ,展開してるじょ感をだした。
配置先はデフォルトではC:\Program Files\{アプリ名}\
ユーザの指定したディレクトリでも可能だが,Program Filesに保存するときにはインストーラを管理者権限で実行している必要があるため,忘れないようにapp.manifestを設定しておく。
1 |
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> |
requireAdministratorにlebelを変更する。
参考にしたサイトは
https://www.atmarkit.co.jp/fdotnet/dotnettips/958uacmanifest/uacmanifest.html
レジストリ登録
これまたお作法が分からないが,今回ユーザがアンインストールを直感的にできるようにしておきたかったため,以下のようにアプリと機能からアンインストールを可能にしたかった。
ここに表示できるようにするためには,レジストリに値を追加する必要がある。
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{アプリ名}
に以下のように値を登録する必要がある。
DisplayIcon : アプリと機能のところに表示したいアイコンのパスを設定する。展開したアプリの実行ファイルのパスを書いた。
DisplayName : アプリの名前
DisplayVersion : アプリのバージョン
InstallLocation : インストールしたアプリの本体のパス
Publisher : パブリッシャー名
UninstallString : アンインストーラーのパス。コマンドライン引数も書ける。今回はインストーラにコマンドライン引数を与えることでアンインストールとして振る舞うようにした。
URLInfoAbout : アプリのサイトとか?
C#からレジストリの登録を行うサンプルは以下。レジストリをいじるので少しだけ緊張する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
private void SetRegistry(RegkeyData newRegkeyData) { try { RegistryKey regkey = Registry.CurrentUser.CreateSubKey(uninstallRegkey); regkey.SetValue("DisplayIcon", newRegkeyData.DisplayIcon, RegistryValueKind.String); regkey.SetValue("DisplayName", newRegkeyData.DisplayName, RegistryValueKind.String); regkey.SetValue("DisplayVersion", newRegkeyData.DisplayVersion, RegistryValueKind.String); regkey.SetValue("InstallLocation", newRegkeyData.InstallLocation, RegistryValueKind.String); regkey.SetValue("Publisher", newRegkeyData.Publisher, RegistryValueKind.String); regkey.SetValue("UninstallString", newRegkeyData.UninstallString, RegistryValueKind.String); regkey.SetValue("URLInfoAbout", newRegkeyData.URLInfoAbout, RegistryValueKind.String); regkey.Close(); } catch(Exception e) { Console.WriteLine($"SetRegistry Error : {e}"); } } |
ショートカットを作成
デスクトップとスタートメニューにショートカットを作成する。
デスクトップにショートカットを作るかユーザにダイアログで聞き,必要に応じて.lnkファイルを作成。
スタートメニューにショートカットを追加する場合は
C:\Users\USER_NAME\AppData\Roaming\Microsoft\Windows\Start Menu\Programs
にデスクトップ同様に.lnkファイルを作成すればよい。
.lnkファイルをC#から作成するサンプルは以下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
string desktopShortcutPath = Path.Combine(Environment.GetFolderPath(System.Environment.SpecialFolder.DesktopDirectory), $@"mypp.lnk"); DialogResult res = MessageBox.Show($"Create shortcut to desktop?", "Create shortcut", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (res == DialogResult.Yes) { IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell(); IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(desktopShortcutPath); shortcut.TargetPath = shortcutTargetPath; shortcut.IconLocation = shortcutTargetPath + ",0"; shortcut.Save(); } |
参考にしたサイト
https://dobon.net/vb/dotnet/file/createshortcut.html
地味にWindows Form Applicationの開発は楽しかった…