# `msilib` --- 读写 Microsoft Installer 文件

源代码: Lib/msilib/__init__.py

3.11 版后已移除: `msilib` 模块已被弃用（请参阅 PEP 594 了解详情）。

`msilib` 支持创建 Microsoft 安装程序 (`.msi`) 文件。 由于这种文件往往包含一个嵌入的 "cabinet" 文件 (`.cab`)，它也暴露了一个用于创建 CAB 文件的 API。 目前没有实现对读取 `.cab` 文件的支持；对于读取 `.msi` 数据库的支持则是可能的。

这个包的目标是提供对 `.msi` 文件中的全部表的完整访问，因此，它是一个相当低层级的 API。 这个包的两个主要应用是 `distutils` 命令 `bdist_msi`，以及创建 Python 安装程序包本身 (尽管它目前是使用不同版本的 `msilib`)。

这个包的内容可以大致分为四个部分：低层级 CAB 例程、低层级 MSI 例程、高层级 MSI 例程以及标准表结构。

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

  新建一个名为 cabname 的 CAB 文件。 files 必须是一个元组的列表，其中每个元组包含磁盘文件的名称，以及 CAB 文件内文件的名称。

  这些文件将按照它们在列表中出现的顺序被添加到 CAB 文件中。 所有文件都会被添加到单个 CAB 文件，使用 MSZIP 压缩算法。

  目前没有暴露 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)

  将文件 path 添加到 database 的 `_Stream` 表，使用流名称 name。

`msilib.``gen_uuid`()

  返回一个新的UUID, 符合MSI格式要求 (包含圆括号, 十六进制大写形式)

参见

FCICreate UuidCreate UuidToString

## 数据对象

`Database.``OpenView`(sql)

  通过调用 `MSIDatabaseOpenView()` 返回一个视图对象。 sql 是要执行的 SQL 语句。statement to execute.

`Database.``Commit`()

  通过调用 `MSIDatabaseCommit()` 提交当前事务中挂起的修改。

`Database.``GetSummaryInformation`(count)

  通过调用 `MsiGetSummaryInformation()` 返回一个新的概要信息对象。 count 为已更新值的最大数量。

`Database.``Close`()

  通过 `MsiCloseHandle()` 关闭数据库对象。

  3.7 新版功能.

参见

MSIDatabaseOpenView MSIDatabaseCommit MSIGetSummaryInformation MsiCloseHandle

## 视图对象

`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

## 对象总览

`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

## 记录对象

`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 MsiRecordClearData

## 错误

所有 MSI 函数的包装器都会引发 `MSIError`；异常内部的字符串将包含更多细节。

## CAB 对象

class `msilib.``CAB`(name)

  `CAB` 类代表一个 CAB 文件。 在 MSI 构建过程中，文件将被同时添加到 `Files` 表，以及 CAB 中。 然后，当所有文件添加完成时，即可写入 CAB 文件，再添加到 MSI 文件中。

  name 是 MSI 文件中 CAB 文件的名称。

  `append`(full, file, logical)

    将路径名为 full 的文件添加到 CAB 文件中，命名为 logical。 如果已存在名为 logical 的文件，则会创建一个新的文件名。

    返回文件在 CAB 文件中的索引，以及文件在 CAB 文件中的新名称。

  `commit`(database)

    生成一个 CAB 文件，以流方式添加到 MSI 文件，将其放入 `Media` 表，并从磁盘移除所生成的文件。

## 目录对象

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

  在目录表中创建一个新目录。 在每个时点上对于该目录都有一个当前组件，它或是通过 `start_component()` 显式创建，或是在文件首次被加入时隐式创建。 文件会被加入当前组件，并被加入到 cab 文件中。 要创建一个目录，必须指定一个基准目录对象 (可以为 `None`)，指向物理目录的路径，以及一个逻辑目录名称。 default 指明目录表中的 DefaultDir 槽位。 componentflags 指明新组件所获得的默认旗标。

  `start_component`(component=None, feature=None, flags=None, keyfile=None, uuid=None)

    向组件表添加一个条目，并将该组件设为此目录的当前组件。 如果未给出组件名称，则将使用目录名称。 如果未给出 feature，则将使用当前特征。 如果未给出 flags，则将使用目录的默认旗标。 如果未给出 keyfile，则组件表中的 KeyPath 将保持为空值。

  `add_file`(file, src=None, version=None, language=None)

    向目录的当前组件添加一个文件，如果没有当前组件则会新建一个。 在默认情况下，源中的文件名和文件表将保持一致。 如果指定了 src 文件，它将被解读为相对于当前目录。 作为可选项，可以为文件表中的条目指定 version 和 language。

  `glob`(pattern, exclude=None)

    向当前组件添加一个通过 glob 模式指定的文件列表。 单个文件可以在 exclude 列表中排除。

  `remove_pyc`()

    在卸载时移除 `.pyc` 文件。

参见

Directory Table File Table Component Table FeatureComponents Table

## 相关特性

class `msilib.``Feature`(db, id, title, desc, display, level=1, parent=None, directory=None, attributes=0)

  使用值 id, parent.id, title, desc, display, level, directory 和 attributes 向 `Feature` 表添加一条新记录。 结果特征对象可被传给 `Directory` 的 `start_component()` 方法。

  `set_current`()

    将此特征设为 `msilib` 的当前特征。 新组件会自动被添加到默认特征，除非显式指定了一个特征。

参见

特征表

## GUI 类

`msilib` provides several classes that wrap the GUI tables in an MSI database. However, no standard user interface is provided; use `bdist_msi` to create MSI files with a user-interface for installing Python packages.

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

  对话框控件的基类。 dlg 是控件所属的对话框对象，name 是控件的名称。

  `event`(event, argument, condition=1, ordering=None)

    在 `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=None)

    向分组添加一个名为 name 的单选钮，设置坐标为 x, y, width, height，标签为 text。 如果 value 为 `None`，则设置默认值 name。

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

  返回一个新的 `Dialog` 对象。 将在 `Dialog` 表中创建一个条目，设置指定的坐标，对话框属性，标题，首个、默认和取消控件的名称。

  `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

## 预计算的表

`msilib` 提供了一些仅包含结构模式和表定义的子包。 这些定义基于 MSI 2.0 版。

`msilib.``schema`

  这是基于 MSI 2.0 的标准 MSI 结构模式，其中 tables 变量提供了一个由表定义组成的列表，而 _Validation_records 提供了用于 MSI 验证的数据。

`msilib.``sequence`

  此模块包含针对标准序列表的表内容: AdminExecuteSequence, AdminUISequence, AdvtExecuteSequence, InstallExecuteSequence 和 InstallUISequence。

`msilib.``text`

  此模块包含 UIText 和 ActionText 表的定义，用于标准安装器动作。