0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonのmsilibを使ってMSIファイルを作成する

Last updated at Posted at 2025-10-03

概要

WiX Toolset を使えばMSI形式のインストーラを作成できますが、最新の Ver.6 では「収益をあげている団体が使用する場合、保守料金を支払う必要がある」と謳われています。そこで、WiX Toolset を使わずにMSI形式のインストーラを作成する方法を模索しています。そんななか、Python Ver3.13 で廃止された msilib に興味が湧いたので、これを使ってMSI形式のインストーラを作成してみました。

最新のPythonでmsilibを利用する

msilib は Python 本体から切り離され、以下のリポジトリに保管されています。
https://github.com/TrevorHamm/msilib
そして、これ単独でパッケージ化されPyPIにアップされているので、以下のpipコマンドで導入できます。

pip install pymsilib

パッケージ名がmsilibからpymsilibに変わっているので、利用の際には注意が必要です。また、メンテナンスが止まったパッケージですので、時が経つにつれ色々と問題が出てくる可能性があります。私が気付いたところでは、tempfile モジュールの mktemp() 関数が使われており、これは現在非推奨になっています。いずれ廃止されるかもしれないので、運用を考えるなら自分でメンテナンスしていく必要があります。

最小のインストーラを実装する

Program Filesフォルダに製品名でフォルダを作りファイルを一つ配置する、シンプルな「インストーラビルドスクリプト」を作成しました。

make_msi.py
import os
import argparse
import pymsilib as msilib
from pymsilib import schema
from pymsilib import sequence

def make_msi(source_path, msi_path, product_name, version, manufacturer):
    # sanity
    source_path = os.path.abspath(source_path)
    out_dir = os.path.dirname(os.path.abspath(msi_path))
    if not os.path.exists(source_path):
        raise FileNotFoundError(f"source file not found: {source_path}")
    os.makedirs(out_dir, exist_ok=True)

    # ProductCode
    product_code = msilib.gen_uuid()  # 新規 UUID を生成

    # データベース初期化
    db = msilib.init_database(msi_path, schema, product_name, product_code, version, manufacturer)

    # シーケンスを追加
    msilib.add_data(db, 'InstallExecuteSequence', sequence.InstallExecuteSequence)
    msilib.add_data(db, 'InstallUISequence', sequence.InstallUISequence)
    msilib.add_data(db, 'AdminExecuteSequence', sequence.AdminExecuteSequence)
    msilib.add_data(db, 'AdminUISequence', sequence.AdminUISequence)
    msilib.add_data(db, 'AdvtExecuteSequence', sequence.AdvtExecuteSequence)

    # CAB を作ってファイルを追加する準備
    cab = msilib.CAB('data1.cab')  # 一時 CAB 名(最終的には MSI に埋め込まれる)

    # Directory ツリーを作る
    # ルート(TARGETDIR / SourceDir)
    targetdir = msilib.Directory(db, cab, None, "TARGETDIR", "TARGETDIR", "SourceDir")
    # ProgramFilesFolder の下に Product 用ディレクトリを作る
    programfiles = msilib.Directory(db, cab, targetdir, "ProgramFiles64Folder", "ProgramFiles64Folder", ".")
    app_dir = msilib.Directory(db, cab, programfiles, product_name, "INSTALLDIR", product_name)

    # Feature を作る(1つの Feature に Component を割り当てる)
    feature = msilib.Feature(db, "DefaultFeature", product_name, f"Install {product_name}", 1, directory=app_dir.logical)

    # Component にファイルを追加
    app_dir.start_component(feature=feature, keyfile=os.path.basename(source_path), flags=0)
    # ここでは絶対パスを渡してソースファイルを CAB に入れる
    app_dir.add_file(os.path.basename(source_path), src=source_path)

    # CAB をコミット(CAB を作成して MSI に組み込む)
    cab.commit(db)

    # Summary information を埋めて保存
    si = db.GetSummaryInformation(20)
    si.SetProperty(msilib.PID_TITLE, product_name)
    si.SetProperty(msilib.PID_AUTHOR, manufacturer)
    si.Persist()

    # データベースをコミットして閉じる
    db.Commit()
    db.Close()

    print(f"Created MSI: {msi_path}")

if __name__ == "__main__":
    p = argparse.ArgumentParser(description="Create a minimal MSI using msilib")
    p.add_argument("--source", required=True, help="File to package (single file)")
    p.add_argument("--msi", required=True, help="Output MSI path")
    p.add_argument("--product", default="MyProduct", help="Product name")
    p.add_argument("--version", default="0.0.1", help="Product version")
    p.add_argument("--manufacturer", default="Manufacturer", help="Manufacturer")
    args = p.parse_args()

    make_msi(args.source, args.msi, args.product, args.version, args.manufacturer)

このスクリプトと同じフォルダにファイルmyapp.exeを置いて、以下のコマンドを実行すると、MyAppSetup.msiが得られます。

py make_msi.py --source myapp.exe --msi out/MyAppSetup.msi --product "MyApp" --version "1.0.0" --manufacturer "YourName"

感想

ここまでくるのは、決して簡単ではありませんでした。msilib のソースを読みつつ、既存のちゃんと動くMSIのテーブルを確認しつつ、print 文デバッグを駆使しつつ、ようやく動くものになりました。msilib は Windows Installer の知識がないと使いこなせないでしょうね。とはいえ、このアプローチでツールやライブラリを自作するのも不可能ではないな、という感触を得ることができました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?