Visual Studioで作成したmsiは編集が必要
Visual Studio のセットアッププロジェクトで作成したmsiは編集が必要です。
(セットアッププロジェクトはVisual Studio 2012からサポートされなくなりました)
exeをバージョンアップするときは、既存のexeに上書きするのが普通です。
msiの編集は、上書きを可能にするために行います。
PowerShellでmsiを編集
orca.ps1
# MSIファイルのパス
$msiPath = Join-Path $PSScriptRoot "[ここにmsiのパスを描く]"
try {
# Windows Installerオブジェクトを作成
$installer = New-Object -ComObject WindowsInstaller.Installer
# データベースを開く
$database = $installer.OpenDatabase($msiPath, 1)
try {
# CustomActionテーブルに追加
$record = $installer.CreateRecord(4)
$record.StringData(1) = "fix_reinstall".Trim()
$record.IntegerData(2) = 51
$record.StringData(3) = "REINSTALL".Trim()
$record.StringData(4) = "{}".Trim()
$view = $database.OpenView("INSERT INTO CustomAction (Action, Type, Source, Target) VALUES (?, ?, ?, ?)")
$view.Execute($record)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($view) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($record) | Out-Null
# InstallExecuteSequenceテーブルに追加
$record = $installer.CreateRecord(3)
$record.StringData(1) = "fix_reinstall".Trim()
$record.StringData(2) = "NOT Installed".Trim()
$record.IntegerData(3) = 999
$view = $database.OpenView("INSERT INTO InstallExecuteSequence (Action, Condition, Sequence) VALUES (?, ?, ?)")
$view.Execute($record)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($view) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($record) | Out-Null
# InstallUISequenceテーブルに追加
$record = $installer.CreateRecord(3)
$record.StringData(1) = "fix_reinstall".Trim()
$record.StringData(2) = "NOT Installed".Trim()
$record.IntegerData(3) = 999
$view = $database.OpenView("INSERT INTO InstallUISequence (Action, Condition, Sequence) VALUES (?, ?, ?)")
$view.Execute($record)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($view) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($record) | Out-Null
$database.Commit()
# 確認クエリ
Write-Host "`n[結果]"
Write-Host "`nCustomAction:"
$view = $database.OpenView("SELECT * FROM CustomAction WHERE Action = 'fix_reinstall'")
$view.Execute()
$record = $view.Fetch()
while ($record -ne $null) {
Write-Host " Action: $($record.StringData(1))"
Write-Host " Type: $($record.IntegerData(2))"
Write-Host " Source: $($record.StringData(3))"
Write-Host " Target: $($record.StringData(4))"
$record = $view.Fetch()
}
Write-Host "`nInstallExecuteSequence:"
$view = $database.OpenView("SELECT * FROM InstallExecuteSequence WHERE Action = 'fix_reinstall'")
$view.Execute()
$record = $view.Fetch()
while ($record -ne $null) {
Write-Host " Action: $($record.StringData(1))"
Write-Host " Condition: $($record.StringData(2))"
Write-Host " Sequence: $($record.IntegerData(3))"
$record = $view.Fetch()
}
Write-Host "`nInstallUISequence:"
$view = $database.OpenView("SELECT * FROM InstallUISequence WHERE Action = 'fix_reinstall'")
$view.Execute()
$record = $view.Fetch()
while ($record -ne $null) {
Write-Host " Action: $($record.StringData(1))"
Write-Host " Condition: $($record.StringData(2))"
Write-Host " Sequence: $($record.IntegerData(3))"
$record = $view.Fetch()
}
}
finally {
Write-Host "`n"
if ($record -ne $null) {
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($record) | Out-Null
}
if ($view -ne $null) {
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($view) | Out-Null
}
if ($database -ne $null) {
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($database) | Out-Null
}
if ($installer -ne $null) {
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($installer) | Out-Null
}
}
}
catch {
Write-Host "エラーが発生しました: $_"
}
finally {
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
}
バッチからPowerShellのスクリプトを呼び出す
バッチからPowerShellのスクリプトを呼び出すときは、powershell [ps1ファイル名]
では動かないのでオプションを追加します。
msi.bat
powershell -NoProfile -ExecutionPolicy Bypass .\orca.ps1
顛末
Visual Studioで作成したmsiは、通常のmsiとは違うようです。
orcaを使って手動で編集する以外に、セットアッププロジェクトのプロパティPostBuildEvent
や、VBscriptを使用することで自動化することができるはずですが、うまくいきませんでした。
手動で編集して間違えるとインストーラが動きません。
自動化するのが一番です