====== インストーラーの作成 ======
Visual Studio Installer (インストーラー プロジェクト) は Visual Studio 2012 からサポートされなくなっていて、無償で手軽にインストーラーを作成するには Flexera 社の InstallShield LE をダウンロードして使う必要がありました。\\
しかし、Visual Studio Installer が復活しました。
※InstallShield LEについては、Visual Studio 2015 communityはサポートしていません。
===== Visual Studio Installer の入手方法 =====
ツール - 拡張機能と更新プログラム で、installer を検索し、Microsoft Visual Studio Installer Projects Extension をダウンロード
* [[http://typea.info/blg/glob/2016/04/visual-studio-2015-community-edition-windows.html|Visual Studio 2015 Community Edition で Windowsインストーラを作成する]]
* [[https://www.osadasoft.com/visual-studio-2017%E3%81%A7%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%A9%E4%BD%9C%E6%88%90/|Visual Studio 2017でインストーラ作成]]
===== インストーラープロジェクトの作成 =====
インストールが完了したら、対称のソリューションをVisual Studio で開き、ファイル - 新規作成 - プロジェクト を実行し、その他のプロジェクトの種類を展開。WindowsSetup プロジェクトをソリューションに追加する。
===== インストールのシナリオ =====
* 標準の「Program Files」フォルダではなく「C:\CrimpHelper」にインストールする。\\
* プロダクト名とタイトル名およびショートカット名は「得意先別圧着規格値対応(暫定)ツール」とする。\\
* 専用のアイコンを設定する。
* 配下のフォルダ(Dataやlogs等)はインストール時に作成させる。\\
* アンインストール時にインストールフォルダを確認後に完全削除させる。
* 設定ファイルのユーザー情報の格納場所(AppData)の削除はしない。
DefaultLocationプロパティを固定フォルダにしてしまうとセットアップ時にフォルダ選択画面が表示されない。その場合、DefaultLocationプロパティを[WindowsVolume]\[ProductName]にする。\\
※ProductNameとフォルダ名が一致している場合\\
[[https://blog.yuizi.com/2012/04/program-files.html|インストーラーでProgram Files 以外のフォルダをデフォルトにする]]
===== プロパティの設定 =====
【画像挿入】\\
^InstallAllUsers|True:すべてのユーザー / False:このユーザーのみ|
===== ファイルシステムの設定 =====
Setupプロジェクトにて右クリックメニューにある「View」から「ファイルシステム」を選択します。\\
{{:it技術:dotnet:ファイルシステム.png|}}\\
下記のファイルシステムが表示されます。\\
{{:it技術:dotnet:ファイルシステム3.png|}}\\
===== プライマリ出力 =====
「Application Folder」を選択して右クリックメニューにある「Add」から「プロジェクト出力」を選択します。\\
{{:it技術:dotnet:プロジェクト出力.png|}}\\
プライマリ出力を選択し、構成を「アクティブ」のまま「OK」ボタンをクリックします。\\
{{:it技術:dotnet:プロジェクト出力2.png|}}\\
プライマリ出力のファイルと関連したdllが出力されます。\\
===== フォルダやファイルの追加 =====
「Application Folder」を選択して右クリックメニューにある「Add」から「Folder」や「ファイル」を選択します。\\
その後に必要なフォルダを作成しつつ必要なファイルを選択します。\\
【画像挿入】\\
フォルダを作成した場合、プロパティの「AlwaysCreate」を「True」にしておかないとインストール時に作成されません。\\
【画像挿入】\\
===== ショートカットの作成 =====
「プライマリ出力 from XXXX」の右クリックメニューにある「Create Shortcut to プライマリ出力 from XXXX」をクリックします。\\
【画像挿入】\\
===== ショートカットのコピー =====
デスクトップ画面にショートカットを作成します。\\
先程作成した「Create Shortcut to プライマリ出力 from XXXX」をドラッグ&ドロップして、「User's Desktop」に持ってきます。\\
【画像挿入】\\
※「User's Desktop」の右クリックによるショートカット作成は、フォルダが開くだけのショートカットになってしまいます。\\
プログラムメニューも同様にします。先にフォルダを作成します。\\
「Create Shortcut to プライマリ出力 from XXXX」をドラッグ&ドロップして、「User's Program Menu」の配下に作成したフォルダに持ってきます。\\
【画像挿入】\\
※どちらのショートカットともプロパティの「Icon」を設定して変更します。
===== カスタム動作の作成 =====
今回、アンインストール時にログファイル等が1つでもあるとフォルダが残るため、フォルダを完全削除するような仕組みとする。\\
CustomActionプロジェクトを作成します。\\
そして、カスタムアクション用にInstallクラスを継承する「MyInstall.vb」を作成し「CustomAction.dll」を出力します。\\
【画像挿入】\\
削除するか確認し、「はい」を選択したらテンポラリフォルダにコピーしたフォルダ削除バッチ(removeDir.bat)を動作させる。\\
※単純にフォルダ削除APIを実行するだけだと「CustomAction.dll」が削除できずにアンインストールエラーとなってしまう\\
Imports System.ComponentModel
Imports System.Configuration.Install
Imports System.Windows.Forms
Public Class MyInstaller
Inherits Installer
'''
''' コンストラクタ
'''
Public Sub New()
MyBase.New()
End Sub
'''
''' アンインストール
'''
'''
Public Overrides Sub Uninstall(savedState As IDictionary)
MyBase.Uninstall(savedState)
' CustomAction.dllがあるパス取得
Dim path As String = Me.Context.Parameters("assemblypath")
' 親ディレクトリを取得
Dim parentPath As String = System.IO.Path.GetDirectoryName(path)
If parentPath.IndexOf("CrimpHelper", StringComparison.OrdinalIgnoreCase) >= 0 Then
If System.IO.Directory.Exists(parentPath + "\Data") OrElse
System.IO.Directory.Exists(parentPath + "\logs") Then
Dim result As DialogResult =
MessageBox.Show(parentPath + "フォルダを10秒後に削除します。" + vbCrLf + "先に必要なデータは退避してください。", "削除確認",
MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2, MessageBoxOptions.DefaultDesktopOnly)
If result = DialogResult.Yes Then
' 単純にフォルダ削除するとCustomAction.dllが削除できずにアンインストールエラーとなるため
' バッチファイルをテンポラリフォルダにコピーして実行させる。
Dim tmpPath As String = System.IO.Path.GetTempPath()
Const REMOVE_BAT As String = "removeDir.bat"
System.IO.File.Copy(parentPath + "\" + REMOVE_BAT, tmpPath + REMOVE_BAT, True)
Dim ps As New System.Diagnostics.ProcessStartInfo
ps.FileName = "Cmd.exe"
ps.Arguments = " /c " + tmpPath + REMOVE_BAT + " " + parentPath
ps.WindowStyle = System.Diagnostics.ProcessWindowStyle.Minimized
System.Diagnostics.Process.Start(ps)
End If
End If
End If
End Sub
End Class
timeout 10
rmdir /S /Q %1
eixt
===== カスタム動作のプライマリ出力 =====
「Application Folder」を選択して右クリックメニューにある「Add」から「プロジェクト出力」を選択します。\\
【画像挿入】\\
プロジェクトを「CustomAction」に変更しプライマリ出力を選択し、構成を「アクティブ」のまま「OK」ボタンをクリックします。\\
【画像挿入】\\
この際に「removeDir.bat」のファイルも「Application Folder」に追加しておきます。
===== カスタム動作のセット =====
Setupプロジェクトにて右クリックメニューにある「View」から「カスタム動作」を選択します。\\
【画像挿入】\\
「Custom Action」の右クリックメニューにある「カスタム動作の追加」で「プライマリ出力 from CustomAction」を選択します。\\
【画像挿入】
==== カスタム動作にデータを渡す ====
Installの「プライマリ出力 from CustomAction」のプロパティに「CustomActionData」があります。\\
{{:it技術:dotnet:customactiondata.png|}}
CustomActionDataプロパティに「/name=value」という形式で指定します。ここで「name」は名前で、「value」はその値を示します。複数のデータを渡す場合は、スペース文字で区切ります。\\
[[https://dobon.net/vb/dotnet/deployment/customaction.html|カスタム動作にデータを渡す]]
例 /TargetDir="[TARGETDIR]\"
==== Error 1001 ====
=== インストール ===
インストール時に「Error 1001」によりインストールできない。\\
原因としてCustomActionDataプロパティに「/TargetDir="[TARGETDIR]"」と末尾の"\"を除外したため。※二重引用符を外して末尾の"\"を除外した場合はエラーにならない。\\
* [[https://stackoverflow.com/questions/1682532/msi-error-1001-usage-installutil-error-on-production-server|MSI Error. 1001. Usage: InstallUtil .. error on production server]]
* [[https://stackoverflow.com/questions/5008675/msi-installer-cannot-find-installstate-when-using-custom-action-with-parameters|MSI Installer cannot find InstallState when using custom action with parameters]]
=== アンインストール ===
アンインストール時に「Error 1001 savedState 適合しないデータが含まれており...」によりインストールできない。\\
原因は不明、[[https://forest.watch.impress.co.jp/library/software/geekuninst/|GeekUninstallerツール]]で強制的にアンインストールしたことで整合性が一致しないのかも。\\
下記の方法でログを出力することはできる。[[https://docs.lansa.com/14/ja/lansa022/content/lansa/vldtool19_0030.htm|msiexec.exe コマンドライン・オプション]]\\
エラー箇所 returned actual error code 1603
msiexec.exe /X "Setup.msi" /L*V "C:\Temp\msilog.log"
対応として、例外エラーが出ても先に進めることを利用して例外エラーをスキップさせる。
Public Overrides Sub Uninstall(savedState As IDictionary)
Try
MyBase.Uninstall(savedState)
Catch ex As Exception
'MessageBox.Show(ex.Message + vbCrLf & ex.StackTrace)
End Try
Dim path As String = Context.Parameters("TargetDir")
ProcessBatch(path, "DelService.bat")
End Sub
===== Setup.msiとSetup.exeの違い =====
setup.exeは同梱のsetup.msiを実行するように作られており、msi からはフォローアップできないいくつかの処理(必須コンポーネントの.NET Framework のランタイムやWindowsInstallerの特定バージョンのインストールなど)をexe側で行う仕組みになっている。
Windows Installer がインストールされてないとmsiファイルが認識できないので、その場合はsetup.exeからの実行が必要となります。\\
現状Windows OSではWindows Installerが標準でインストールされているので、Setup.msiのみで良い。
* [[http://bbs.wankuma.com/index.cgi?mode=al2&namber=42432&KLOG=73|setup.exeとxxx.msiの違いは何なんでしょうか?]]
* [[http://nhiron.blog.jp/archives/1017697672.html|msiとsetup.exeのはなし]]
* [[https://kaorun.hatenablog.com/entry/20151219/1450511313|今、あらためて確認するWindows Installer(MSI)の基本]]
===== アップグレードインストール =====
Product CodeとProduct Versionは変更して、Upgrade Codeへ変更しない。\\
RemovePreviousVersionsプロパティをTrueにして、以前のバージョンを削除するようにしておく。
* [[https://dobon.net/vb/dotnet/deployment/upgrades.html#section4|セットアッププロジェクトによるアップデート]]\\
* [[https://www.civil-design.net/index.html?main=https%3A%2F%2Fwww.civil-design.net%2Ffree%2Fcoach%2Fdev%2Fwi%2Fwi_upgrade.html|Windows インストーラ講座 - アップグレード(バージョンアップ)の考え方]]
visualstudioinstallerでは、PackageCodeは見当たらない。 PackageCode = ProductCodeが既定と考える。
===== サービスのインストール =====
何も設定しない場合、「サービス ログインの設定」のダイアログ画面が表示される。\\
{{:it技術:dotnet:サービスログインの設定画面.png|}}
これを表示しないようにするには下記の設定を行います。これによりサービスがインストールされローカルサービスアカウントで実行されます。
- ProjectInstallerを開きます
- ServiceProcessInstaller1を右クリックして、プロパティを選択します
- [アカウント]ドロップダウンの[その他]で、サービスを実行するアカウントを選択します。 例 LocalSystem
[[https://stackoverrun.com/ja/q/466194|Windowsサービスのインストール時の資格情報]]
===== 補足 =====
違うバージョンをインストールする際に以前のバージョンをアンインストールしなくても上書きしてインストールしてくれる。
===== 参照 =====
* [[http://typea.info/blg/glob/2016/04/visual-studio-2015-community-edition-windows.html|Visual Studio 2015 Community Edition で Windowsインストーラを作成する]]
* [[http://pb-times.jp/P_524bcaba4908d|VisualStudio インストーラーの作成方法]]
* [[http://wiki.tk2kpdn.com/visual-studio-installer-tips/|Visual Studio Installer (インストーラー プロジェクト) に関するあれこれ]]
* [[http://blog.yuizi.com/2012/05/2.html|インストーラーで環境変数を設定する(その2)]]
* [[http://manbou404.hatenablog.com/entry/2016/02/09/114250|Visual Studio Installer (VS2015) カスタムアクション]]
* [[http://jehupc.exblog.jp/9073239/|Visual Studioセットアッププロジェクトのカスタム動作]]
* [[http://dobon.net/vb/dotnet/deployment/customaction.html#installer2|カスタム動作エディタの使い方]]