各種MSI展開ソフトについて


■プログラム内部の挙動

MSIファイルは単一ファイルにも拘らず、その中に複雑な構造を持っています。インターネットの動画配信で「ストリーミング」という用語がありますが、Windows インストーラ実行時には、MSIファイルの中から情報のストリームが流れ出てくるとイメージしてください。このストリームには、「フォルダを作れ」「レジストリに書き込め」「ファイルを配置しろ」などの命令が乗っており、それらが順に実行されていくことでインストールが完了するわけです。

一方【MSI2FILE】・【MSX2CAB】・【msix.exe】・【MSI2XML】などのソフトは、実際にWindows インストーラでインストールすることなく、中身を取り出すことができます。各々のプログラム内部でMSIに関連の深いWindows APIを利用して仮想的なストリームを生じさせ、そこからデータを抜き取って保存しているのです。このとき実際にストリームからデータを読み取るAPIはMsiRecordReadStreamというものですが、その前のMsiDatabaseOpenViewの段階で、どのようなストリームを生じさせるかという点がポイントです。

○【MSI2FILE】・【MSI2XML】の場合

MsiOpenDatabase
 ↓
MsiDatabaseOpenView (MediaテーブルのCabinet列を指定)
 ↓
MsiViewExecute
 ↓
MsiViewFetch
 ↓
MsiRecordGetString

という順序でAPIを実行し、内包されているCabinetファイル名を入手します。ちょうどOrcaでMediaテーブルのCabinet列を閲覧した時と同じ情報が得られます。この中でファイル名の先頭に#の付いた物のみを記録しておきます。(#の付いていないものは、外部に別個に存在するCabinetファイルだからです。) 続けて再び

MsiDatabaseOpenView (_Streamsの、上記Cabinetに関するDataのみを指定)
 ↓
MsiViewExecute
 ↓
MsiViewFetch
 ↓
MsiRecordReadStream

という順序でAPIを実行します。これによって、各Cabinetファイルのバイナリデータが得られます。ここで読み込んだデータをファイルに写し取るわけですが、【MSI2XML】は総データサイズに相当するメモリをヒープ領域から一気に確保し書き込みます。通常これで大丈夫だったのですが、最近はサイズが数百メガバイトにも及ぶCabinetファイルを含むMSIも登場してきたため、領域確保に失敗し、プログラム自体が落ちる場合が出てきました。そのため【MSI2FILE】は一気に書き込むのではなく、少しずつデータを積み重ねてファイルを完成させる方式に仕様変更しています(2009年5月)。展開速度はほんの少し落ちるかもしれませんが、確実性を重視した仕様に変更しました。

○【MSX2CAB】・【msix.exe】の場合

MsiOpenDatabase
 ↓
MsiDatabaseOpenView (_StreamsのName・Dataを指定)
 ↓
MsiViewExecute
 ↓
MsiViewFetch
 ↓
MsiRecordGetString (ここでSummaryInformation/DigitalSignatureを除外)
 ↓
MsiRecordReadStream

という手順で読み込んだデータをファイルに写し取ります。_StreamsのDataを限定せずに、MsiDatabaseOpenViewを実行する点が特徴です。このためCabinetファイル以外のデータも集まります。ただしSummaryInformation/DigitalSignatureは例外として処理します。少しずつデータを積み重ねてファイルを完成させる方式は【MSI2FILE】と同様で、【MSI2XML】のように巨大抽出ファイルで落ちる心配はありません。

○【msiexec.exe】の場合

上記のようなサードパーティのソフトを使うのではなく、Windows インストーラが導入されている環境ならばどのPCでも標準で存在している【msiexec.exe】を使う方法もあります。

参考リンク
@IT .MSIファイルを解凍して内部のファイルを取り出す(msiexec編)

この方法では、展開したファイルが擬似的にインストール後の階層構造を模したものになるという利点があります。ただし【MSI2XML】同様に、上述したメモリ確保に失敗する欠点があるようです。

【MSI2XML】や【msiexec.exe】では上手く行かない例としては、Microsoftのダウンロードセンターから【Windows XP MODE】を入手してテストしてみると良いでしょう。環境によって成功したり失敗したりするかもしれませんが、おそらく32bit版のOSではメモリ確保ができず、ほとんどの場合失敗すると思われます。ただし【MSI2XML】で落ちるとか落ちないとか言うのは、現段階で入手できるバージョンを基にしているので、今後は変わる可能性があります。【msiexec.exe】についても、当方で全てのバージョンでテストしたわけではないので、新しいバージョンや今後登場するバージョンでは改善されているかもしれません。