Windows Installer手引書 Part.19 カスタムアクションとインストールログ

[**前の記事へ**](https://qiita.com/tohshima/items/cfab9e289c7b1e190ad9)　　[**目次へ**](https://qiita.com/tohshima/items/dc4c4721d50a2ad70c7a)　　[**次の記事へ**](https://qiita.com/tohshima/items/d08ab298e57fd56e7bde)

## Windows Installerのインストールログ

特に自作のカスタムアクションを使っていなくても、インストールログは不具合の特定に役立ちます。インストールログを出力するには、msiexec.exeの引数にオプションを指定する[^1]必要があるため、コマンドプロンプトでインストーラーを起動するか、バッチファイル等でセットアップランチャーを作っておく必要があります。

msiexec.exeのコマンドラインオプションは[ここにまとめられて](https://docs.microsoft.com/en-us/windows/win32/msi/command-line-options)おり、ログに関するオプションは`/L`になります。多くのオプションがあって戸惑いますが、どのような情報を出力するか細かくフィルタできるため、複雑に見えるだけです[^2]。私はいつも。ログにすべての情報を出力しています。そうすると、下記のセンテンスを使用するだけで済みます。

```
msiexec /L*v [ログファイル名] /i [MSIファイル名]
```

インストーラの開発中には、これを適当な名前のバッチファイルに保存しておけば簡単にログファイルを得られるので便利です。

## カスタムアクションからログに文字列を出力する

[前回説明した](https://qiita.com/tohshima/items/cfab9e289c7b1e190ad9#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8ui)ように、「レコード」という形式で送るべきメッセージを作成し、MsiProcessMessage()関数でレコードをWindows Installerに送るだけです。ただ気を付けておきたいのは、膨大なログ情報の中に自分が出力したログ情報を埋もれさせないために、簡単に検索できるような特定の文字列を埋め込んでおくことをお勧めします（ここでは`=tohshima=`をキーワードに使用します）。例えば、下記のようにすれば、ログにメッセージを埋め込むことができます。

```C++:CustomAction.cpp
#pragma comment(lib, "msi.lib")
#include <windows.h>
#include <msiquery.h>

extern "C" __declspec(dllexport) UINT showMessages(MSIHANDLE hInstall) {
    PMSIHANDLE hRecord = MsiCreateRecord(1);
    MsiRecordSetString(hRecord, 0, "=tohshima= This is test message.");
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_INFO), hRecord);
    return ERROR_SUCCESS;
}
```

`MsiProcessMessage()`関数の第２引数に`INSTALLMESSAGE(INSTALLMESSAGE_INFO)`を指定するだけです。

これをいつものwxsファイルから利用します。

```xml:Product.wxs
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
	<Product Id="0818500A-4E07-406F-8A10-FAFE90B8261E" Name="Part19_01" Language="1033" Version="1.0.0" Manufacturer="tohshima" UpgradeCode="b01d7db9-7628-45d0-a235-a3710813a49f">
		<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />

		<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
		<MediaTemplate />

        <Binary Id="CA" SourceFile="CA\CustomAction.dll"/>
        <CustomAction Id="cShowMsg" BinaryKey="CA" DllEntry="showMessages" Execute="immediate"/>
        <InstallExecuteSequence>
            <Custom Action="cShowMsg" After="InstallInitialize">NOT Installed</Custom>
        </InstallExecuteSequence>

        <Feature Id="ProductFeature" Title="Part19_01" Level="1">
			<ComponentGroupRef Id="ProductComponents" />
		</Feature>
	</Product>

	<Fragment>
		<Directory Id="TARGETDIR" Name="SourceDir">
			<Directory Id="ProgramFilesFolder">
				<Directory Id="INSTALLFOLDER" Name="Part19_01" />
			</Directory>
		</Directory>
	</Fragment>

	<Fragment>
		<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
            <Component Id="cExe" Guid="{55D7B01C-16E0-4C2E-97D7-5E399D187D89}">
                <File Id="fExe" Source="C:\Windows\System32\calc.exe" KeyPath="yes"/>
            </Component>
		</ComponentGroup>
	</Fragment>
</Wix>
```

これを使ってMSIファイルを作成後、MSIファイルが出力されたディレクトリで下記のコマンドを実行します。

```go.bat
msiexec /L*v install.log /i Part19_01.msi
```
install.logファイルが出来上がっているはずなので、テキストエディタ等で開き、`=tohshima=`で検索するとログに出力された行を見つけることができます。

```
:
:
Action start 19:14:11: cShowMsg.
MSI (s) (E4:54) [19:14:11:832]: Invoking remote custom action. DLL: C:\Windows\Installer\MSICF99.tmp, Entrypoint: showMessages
MSI (s) (E4:50) [19:14:11:833]: Generating random cookie.
MSI (s) (E4:50) [19:14:11:843]: Created Custom Action Server with PID 11060 (0x2B34).
MSI (s) (E4:38) [19:14:11:885]: Running as a service.
MSI (s) (E4:38) [19:14:11:889]: Hello, I'm your 32bit Impersonated custom action server.
=tohshima= This is test message.
Action ended 19:14:11: cShowMsg. Return value 1.
:
:
```

[^1]: インストールログの出力を指定する方法は他にもありますが、まず使わないので、説明を割愛します。
[^2]: 日本語の情報として、InstallShieldのヘルプファイルが役に立ちます。UserGuideのPDFファイルが公開されていますので、ダウンロードしておくと役に立ちます。今回の例で言うと、msiexec.exeのコマンドラインオプションの解説が翻訳されています。InstallShield、UserGuideといったキーワードで検索してみてください。

[**前の記事へ**](https://qiita.com/tohshima/items/cfab9e289c7b1e190ad9)　　[**目次へ**](https://qiita.com/tohshima/items/dc4c4721d50a2ad70c7a)　　[**次の記事へ**](https://qiita.com/tohshima/items/d08ab298e57fd56e7bde)