# 35.1. `msilib` --- Microsoft インストーラーファイルの読み書き

バージョン 2.5 で追加.

`msilib` モジュールは Microsoft インストーラー(`.msi`)の作成を支援します。このファイルは大抵の場合埋め込まれた「キャビネット」ファイル (`.cab`) を含むので、CAB ファイル作成用の API も公開されています。現在のところ `.cab` ファイルの読み出しは現時点では実装されていませんが、 `.msi` データベースの読み出しは可能です。

このパッケージの目的は `.msi` ファイルにある全てのテーブルへの完全なアクセスの提供であり、提供されているものは非常に低レベルな API です。このパッケージの二つの主要な使用目的は `distutils` の `bdist_msi` コマンドと、Python インストーラーパッケージそれ自体(と言いつつ現在は別バージョンの `msilib` を使っているのですが)です。

パッケージの内容は大きく四つのパートに分けられます。低レベル CAB ルーチン、低レベル MSI ルーチン、少し高レベルの MSI ルーチン、標準的なテーブル構造、の四つです。

`msilib.``FCICreate`(cabname, files)

  新しい CAB ファイルを cabname という名前で作ります。files はタプルのリストで、それぞれのタプルはディスク上のファイル名と CAB ファイルで付けられるファイル名で構成されなければなりません。

  ファイルはリストに現れた順番で CAB ファイルに追加されます。全てのファイルは MSZIP 圧縮アルゴリズムを使って一つの CAB ファイルに追加されます。

  MSI 作成の様々なステップに対する Python コールバックは現在公開されていません。

`msilib.``UuidCreate`()

  新しい一意な識別子の文字列表現を返します。この関数は Windows API の関数 `UuidCreate()` と `UuidToString()` をラップしたものです。

`msilib.``OpenDatabase`(path, persist)

  MsiOpenDatabase を呼び出して新しいデータベースオブジェクトを返します。path は MSI ファイルのファイル名です。persist は五つの定数 `MSIDBOPEN_CREATEDIRECT`, `MSIDBOPEN_CREATE`, `MSIDBOPEN_DIRECT`, `MSIDBOPEN_READONLY`, `MSIDBOPEN_TRANSACT` のどれか一つで、フラグ `MSIDBOPEN_PATCHFILE` を含めても構いません。これらのフラグの意味は Microsoft のドキュメントを参照してください。フラグに従って、既存のデータベースを開いたり新しいデータベースを作成したりします。

`msilib.``CreateRecord`(count)

  `MSICreateRecord()` を呼び出して新しいレコードオブジェクトを返します。 count はレコードのフィールドの数です。

`msilib.``init_database`(name, schema, ProductName, ProductCode, ProductVersion, Manufacturer)

  name という名前の新しいデータベースを作り、schema で初期化し、プロパティ ProductName, ProductCode, ProductVersion, Manufacturer をセットして、返します。

  schema は `tables` と `_Validation_records` という属性をもったモジュールオブジェクトでなければなりません。大抵の場合、 `msilib.schema` を使うべきです。

  データベースはこの関数から返された時点でスキーマとバリデーションレコードだけが収められています。

`msilib.``add_data`(database, table, records)

  全ての records を database の table テーブルに追加します。

  table 引数は MSI スキーマで事前に定義されたテーブルでなければなりません。例えば、`'Feature'`, `'File'`, `'Component'`, `'Dialog'`, `'Control'`, などです。

  records はタプルのリストで、それぞれのタプルにはテーブルのスキーマに従ったレコードの全てのフィールドを含んでいるものでなければなりません。オプションのフィールドには `None` を渡すことができます。

  フィールドの値には、整数・長整数・文字列・Binary クラスのインスタンスが使えます。

class `msilib.``Binary`(filename)

  Binary テーブル中のエントリーを表わします。 `add_data()` を使ってこのクラスのオブジェクトを挿入するときには filename という名前のファイルをテーブルに読み込みます。

`msilib.``add_tables`(database, module)

  module の全てのテーブルの内容を database に追加します。module は tables という内容が追加されるべき全てのテーブルのリストと、テーブルごとに一つある実際の内容を持っている属性とを含んでいなければなりません。

  この関数は典型的にシーケンステーブルをインストールするために使われます。

`msilib.``add_stream`(database, name, path)

  database の `_Stream` テーブルに、ファイル path を name というストリーム名で追加します。

`msilib.``gen_uuid`()

  新しい UUID を、MSI が通常要求する形式(つまり、中括弧で囲み、16進数は大文字)で返します。

参考

FCICreateFile UuidCreate UuidToString

## 35.1.1. データベースオブジェクト

`Database.``OpenView`(sql)

  `MSIDatabaseOpenView()` を呼び出して取得したビューオブジェクトを返します。 sql は実行される SQL ステートメントです。

`Database.``Commit`()

  `MSIDatabaseCommit()` を呼び出して現在のトランザクションで保留されている変更をコミットします。

`Database.``GetSummaryInformation`(count)

  `MsiGetSummaryInformation()` を呼び出して新しいサマリー情報オブジェクトを返します。 count は更新された値の最大数です。

参考

MSIDatabaseOpenView MSIDatabaseCommit MSIGetSummaryInformation

## 35.1.2. ビューオブジェクト

`View.``Execute`(params)

  `MSIViewExecute()` を通してビューに対する SQL 問い合わせを実行します。 params が `None` でない場合、クエリ中のパラメータトークンの実際の値を与えるものです。

`View.``GetColumnInfo`(kind)

  `MsiViewGetColumnInfo()` の呼び出しを通してビューのカラムを説明するレコードを返します。 kind は `MSICOLINFO_NAMES` または `MSICOLINFO_TYPES` です。

`View.``Fetch`()

  `MsiViewFetch()` の呼び出しを通してクエリの結果レコードを返します。

`View.``Modify`(kind, data)

  `MsiViewModify()` を呼び出してビューを変更します。 kind は `MSIMODIFY_SEEK`, `MSIMODIFY_REFRESH`, `MSIMODIFY_INSERT`, `MSIMODIFY_UPDATE`, `MSIMODIFY_ASSIGN`, `MSIMODIFY_REPLACE`, `MSIMODIFY_MERGE`, `MSIMODIFY_DELETE`, `MSIMODIFY_INSERT_TEMPORARY`, `MSIMODIFY_VALIDATE`, `MSIMODIFY_VALIDATE_NEW`, `MSIMODIFY_VALIDATE_FIELD`, `MSIMODIFY_VALIDATE_DELETE` のいずれかです。

  data は新しいデータを表わすレコードでなければなりません。

`View.``Close`()

  `MsiViewClose()` を通してビューを閉じます。

参考

MsiViewExecute MSIViewGetColumnInfo MsiViewFetch MsiViewModify MsiViewClose

## 35.1.3. サマリー情報オブジェクト

`SummaryInformation.``GetProperty`(field)

  `MsiSummaryInfoGetProperty()` を通してサマリーのプロパティを返します。 field はプロパティ名で、定数 `PID_CODEPAGE`, `PID_TITLE`, `PID_SUBJECT`, `PID_AUTHOR`, `PID_KEYWORDS`, `PID_COMMENTS`, `PID_TEMPLATE`, `PID_LASTAUTHOR`, `PID_REVNUMBER`, `PID_LASTPRINTED`, `PID_CREATE_DTM`, `PID_LASTSAVE_DTM`, `PID_PAGECOUNT`, `PID_WORDCOUNT`, `PID_CHARCOUNT`, `PID_APPNAME`, `PID_SECURITY` のいずれかです。

`SummaryInformation.``GetPropertyCount`()

  `MsiSummaryInfoGetPropertyCount()` を通してサマリープロパティの個数を返します。

`SummaryInformation.``SetProperty`(field, value)

  `MsiSummaryInfoSetProperty()` を通してプロパティをセットします。 field は `GetProperty()` におけるものと同じ値をとります。 value はプロパティの新しい値です。許される値の型は整数と文字列です。

`SummaryInformation.``Persist`()

  `MsiSummaryInfoPersist()` を使って変更されたプロパティをサマリー情報ストリームに書き込みます。

参考

MsiSummaryInfoGetProperty MsiSummaryInfoGetPropertyCount MsiSummaryInfoSetProperty MsiSummaryInfoPersist

## 35.1.4. レコードオブジェクト

`Record.``GetFieldCount`()

  `MsiRecordGetFieldCount()` を通してレコードのフィールド数を返します。

`Record.``GetInteger`(field)

  field の値を可能なら整数として返します。field は整数でなければなりません。

`Record.``GetString`(field)

  field の値を可能なら文字列として返します。field は整数でなければなりません。

`Record.``SetString`(field, value)

  `MsiRecordSetString()` を通して field を value にセットします。 field は整数、 value は文字列でなければなりません。

`Record.``SetStream`(field, value)

  `MsiRecordSetStream()` を通して field を value という名のファイルの内容にセットします。 field は整数、 value は文字列でなければなりません。

`Record.``SetInteger`(field, value)

  `MsiRecordSetInteger()` を通して field を value にセットします。 field も value も整数でなければなりません。

`Record.``ClearData`()

  `MsiRecordClearData()` を通してレコードの全てのフィールドを 0 にセットします。

参考

MsiRecordGetFieldCount MsiRecordSetString MsiRecordSetStream MsiRecordSetInteger MsiRecordClear

## 35.1.5. エラー

All wrappers around MSI functions raise `MSIError`; the string inside the exception will contain more detail.

## 35.1.6. CAB オブジェクト

class `msilib.``CAB`(name)

  `CAB` クラスは CAB ファイルを表わすものです。MSI 構築中、ファイルは `Files` テーブルと CAB ファイルとに同時に追加されます。そして、全てのファイルを追加し終えたら、CAB ファイルは書き込まれることが可能になり、MSI ファイルに追加されます。

  name は MSI ファイル中の CAB ファイルの名前です。

  `append`(full, file, logical)

    パス名 full のファイルを CAB ファイルに logical という名で追加します。logical という名が既に存在したならば、新しいファイル名が作られます。

    ファイルの CAB ファイル中のインデクスと新しいファイル名を返します。

  `commit`(database)

    CAB ファイルを作り、MSI ファイルにストリームとして追加し、`Media` テーブルに送り込み、作ったファイルはディスクから削除します。

## 35.1.7. ディレクトリオブジェクト

class `msilib.``Directory`(database, cab, basedir, physical, logical, default[, componentflags])

  新しいディレクトリを Directory テーブルに作成します。ディレクトリには各時点で現在のコンポーネントがあり、それは `start_component()` を使って明ら様に作成されたかまたは最初にファイルが追加された際に暗黙裡に作成されたものです。ファイルは現在のコンポーネントと cab ファイルに追加されます。ディレクトリを作成するには親ディレクトリオブジェクト(`None` でも可)、物理的ディレクトリへのパス、論理的ディレクトリ名を指定する必要があります。 default はディレクトリテーブルの DefaultDir スロットを指定します。 componentflags は新しいコンポーネントが得るデフォルトのフラグを指定します。

  `start_component`([component[, feature[, flags[, keyfile[, uuid]]]]])

    エントリを Component テーブルに追加し、このコンポーネントをこのディレクトリの現在のコンポーネントにします。もしコンポーネント名が与えられなければディレクトリ名が使われます。feature が与えられなければ、ディレクトリのデフォルトフラグが使われます。keyfile が与えられなければ、Component テーブルの KeyPath は null のままになります。

  `add_file`(file[, src[, version[, language]]])

    ファイルをディレクトリの現在のコンポーネントに追加します。このとき現在のコンポーネントがなければ新しいものを開始します。デフォルトではソースとファイルテーブルのファイル名は同じになります。src ファイルが与えられたならば、それば現在のディレクトリから相対的に解釈されます。オプションで version と language を File テーブルのエントリ用に指定することができます。

  `glob`(pattern[, exclude])

    現在のコンポーネントに glob パターンで指定されたファイルのリストを追加します。個々のファイルを exclude リストで除外することができます。

  `remove_pyc`()

    アンインストールの際に `.pyc` / `.pyo` を削除します。

参考

Directory Table File Table Component Table FeatureComponents Table

## 35.1.8. 機能

class `msilib.``Feature`(database, id, title, desc, display[, level=1[, parent[, directory[, attributes=0]]]])

  id, parent.id, title, desc, display, level, directory, attributes の値を使って、新しいレコードを `Feature` テーブルに追加します。出来上がったフィーチャーオブジェクトは `Directory` の `start_component()` メソッドに渡すことができます。

  `set_current`()

    このフィーチャーを `msilib` の現在のフィーチャーにします。フィーチャーが明ら様に指定されない限り、新しいコンポーネントが自動的にデフォルトのフィーチャーに追加されます。

参考

Feature Table

## 35.1.9. GUI クラス

`msilib` はMSIデータベースにあるGUIテーブルをラップしたいくつかのクラスを提供します。しかし、標準的なユーザーインタフェースは提供されません。ユーザーインタフェースを備えたPythonパッケージをインストールするMSIを作成するには `bdist_msi` を使用してください。

class `msilib.``Control`(dlg, name)

  ダイアログコントロールの基底クラス。dlg はコントロールの属するダイアログオブジェクト、name はコントロールの名前です。

  `event`(event, argument[, condition=1[, ordering]])

    このコントロールの `ControlEvent` テーブルにエントリを作ります。

  `mapping`(event, attribute)

    このコントロールの `EventMapping` テーブルにエントリを作ります。

  `condition`(action, condition)

    このコントロールの `ControlCondition` テーブルにエントリを作ります。

class `msilib.``RadioButtonGroup`(dlg, name, property)

  name という名前のラジオボタンコントロールを作成します。property はラジオボタンが選ばれたときにセットされるインストーラープロパティです。

  `add`(name, x, y, width, height, text[, value])

    グループに name という名前で、座標 x, y に大きさが width, height で text というラベルの付いたラジオボタンを追加します。 value が省略されると、デフォルトは name になります。

class `msilib.``Dialog`(db, name, x, y, w, h, attr, title, first, default, cancel)

  新しい `Dialog` オブジェクトを返します。 `Dialog` テーブルを以下の引数に渡された情報を元に作成します: 座標、ダイアログ属性、タイトル、first・default・cancelという三つのコントロールに対する名前。

  `control`(name, type, x, y, width, height, attributes, property, text, control_next, help)

    新しい `Control` オブジェクトを返します。 `Control` テーブルに指定されたパラメータのエントリが作られます。

    これは汎用のメソッドで、特定の型に対しては特化したメソッドが提供されています。

  `text`(name, x, y, width, height, attributes, text)

    `Text` コントロールを追加して返します。

  `bitmap`(name, x, y, width, height, text)

    `Bitmap` コントロールを追加して返します。

  `line`(name, x, y, width, height)

    `Line` コントロールを追加して返します。

  `pushbutton`(name, x, y, width, height, attributes, text, next_control)

    `PushButton` コントロールを追加して返します。

  `radiogroup`(name, x, y, width, height, attributes, property, text, next_control)

    `RadioButtonGroup` コントロールを追加して返します。

  `checkbox`(name, x, y, width, height, attributes, property, text, next_control)

    `CheckBox` コントロールを追加して返します。

参考

Dialog Table Control Table Control Types ControlCondition Table ControlEvent Table EventMapping Table RadioButton Table

## 35.1.10. 事前に計算されたテーブル

`msilib` はスキーマとテーブル定義だけから成るサブパッケージをいくつか提供しています。現在のところ、これらの定義は MSI バージョン 2.0 に基づいています。

`msilib.``schema`

  これは MSI 2.0 用の標準 MSI スキーマで、テーブル定義のリストを提供する tables 変数と、MSI バリデーション用のデータを提供する _Validation_records 変数があります。

`msilib.``sequence`

  このモジュールは標準シーケンステーブルのテーブル内容を含んでいます。AdminExecuteSequence, AdminUISequence, AdvtExecuteSequence, InstallExecuteSequence, InstallUISequence が含まれています。

`msilib.``text`

  このモジュールは標準的なインストーラーのアクションのための UIText および ActionText テーブルの定義を含んでいます。