PyInstallerで作ったWindowsアプリでバージョンを表示させたい(Version Resource Fileの作りかた)

Pocket

Windowsアプリケーションのバージョンは、そのプロパティから確認できる。
PyInstallerでWindowsアプリケーションを作るときにも、ぜひここに登録をしたい。

PyInstallerでは、あらかじめ用意しておいたVersion Resource Fileを読み込ませることで、バージョンなどの情報をアプリケーションに書き込むことができる。

しかし、その方法はちょっとトリッキーなので、ここにその方法を採録する。
トリッキーな内容は何かというと。
要するにVersion Resourceをスクラッチで書くのは大変なので、そのへんにあるWindowsアプリケーション(厳密には拡張子が.exeの実行ファイル)から抜き出してきてそれを使い回すというもの。
れっきとした公式手順である。
したがって全体の流れは以下のようになる。

全体の流れ

1.「既存の」WindowsアプリケーションからVersion Resourceを抜き出す。
2.抜き出したファイルを書き換え。
3.そのファイルを指定してPyInstallerを実行

Version Resourceファイルの抜き出し

PyInstallerには、pyi-grab_version.pyというスクリプトが含まれている。
PyInstallerを展開してできるutilsディレクトリの下にある。
お使いのWindows上にある実行ファイルを引数に与えてpy-grab_version.pyを実行すればよい。
結果はpy-grab_version.pyと同じディレクトリにfile_version_info.txtとして書き込まれる。

以下はWindows 7のcmd.exeを引数に与えた場合の実行例である。

C:\home\py\PyInstaller-2.1\utils>python grab_version.py "C:\Windows\winsxs\x86_microsoft-windows-commandprompt_31bf3856ad364e35_6.1.7600.16385_none_8ae31ce07bb01ee0\cmd.exe"
Version info written to: C:\home\py\PyInstaller-2.1\utils\file_version_info.txt

C:\home\py\PyInstaller-2.1\utils>

以下が書き出されたfile_version_info.txt。
UTF-8なので注意。

# UTF-8
#
# For more details about fixed file info 'ffi' see:
# http://msdn.microsoft.com/en-us/library/ms646997.aspx
VSVersionInfo(
  ffi=FixedFileInfo(
    # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
    # Set not needed items to zero 0.
    filevers=(6, 1, 7600, 16385),
    prodvers=(6, 1, 7600, 16385),
    # Contains a bitmask that specifies the valid bits 'flags'r
    mask=0x3f,
    # Contains a bitmask that specifies the Boolean attributes of the file.
    flags=0x0,
    # The operating system for which this file was designed.
    # 0x4 - NT and there is no need to change it.
    OS=0x40004,
    # The general type of file.
    # 0x1 - the file is an application.
    fileType=0x1,
    # The function of the file.
    # 0x0 - the function is not defined for this fileType
    subtype=0x0,
    # Creation date and time stamp.
    date=(0, 0)
    ),
  kids=[
    StringFileInfo(
      [
      StringTable(
        u'040904B0',
        [StringStruct(u'CompanyName', u'Microsoft Corporation'),
        StringStruct(u'FileDescription', u'Windows Command Processor'),
        StringStruct(u'FileVersion', u'6.1.7600.16385 (win7_rtm.090713-1255)'),
        StringStruct(u'InternalName', u'cmd'),
        StringStruct(u'LegalCopyright', u'© Microsoft Corporation. All rights reserved.'),
        StringStruct(u'OriginalFilename', u'Cmd.Exe'),
        StringStruct(u'ProductName', u'Microsoft® Windows® Operating System'),
        StringStruct(u'ProductVersion', u'6.1.7600.16385')])
      ]), 
    VarFileInfo([VarStruct(u'Translation', [1033, 1200])])
  ]
)

次は本ファイルを書き換える。

ファイルの書き換え

cmd.exeのプロパティ->詳細タブと見比べながら書き換えていけばよい。
それ以外は触らないこと。
cmdexeproperty
たとえばこんな感じ。

# UTF-8
#
# For more details about fixed file info 'ffi' see:
# http://msdn.microsoft.com/en-us/library/ms646997.aspx
VSVersionInfo(
  ffi=FixedFileInfo(
    # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
    # Set not needed items to zero 0.
    filevers=(1, 0, 0, 0),
    prodvers=(1, 0, 0, 0),
    # Contains a bitmask that specifies the valid bits 'flags'r
    mask=0x3f,
    # Contains a bitmask that specifies the Boolean attributes of the file.
    flags=0x0,
    # The operating system for which this file was designed.
    # 0x4 - NT and there is no need to change it.
    OS=0x40004,
    # The general type of file.
    # 0x1 - the file is an application.
    fileType=0x1,
    # The function of the file.
    # 0x0 - the function is not defined for this fileType
    subtype=0x0,
    # Creation date and time stamp.
    date=(0, 0)
    ),
  kids=[
    StringFileInfo(
      [
      StringTable(
        u'040904B0',
        [StringStruct(u'CompanyName', u'hoge Corporation'),
        StringStruct(u'FileDescription', u'hoge'),
        StringStruct(u'FileVersion', u'1.0.0'),
        StringStruct(u'InternalName', u'hoge'),
        StringStruct(u'LegalCopyright', u'© hoge Corporation. All rights reserved.'),
        StringStruct(u'OriginalFilename', u'hoge.exe'),
        StringStruct(u'ProductName', u'hoge'),
        StringStruct(u'ProductVersion', u'1.0.0')])
      ]), 
    VarFileInfo([VarStruct(u'Translation', [1033, 1200])])
  ]
)

ファイルの準備はおしまい。
あとはビルドの際にファイルを指定するだけ。

Version Resourceファイルを指定してビルド

単純に–version-file=<ファイル名>と指定するだけ。
だから実行例は省く。
pyhogeversion
無事に表示された。

補足

参考までに公式の宣言、つまりVersion Resourceは複雑すぎマジ無理、と言っている箇所を貼り付けておく。

because version resources are complex. Some elements are optional, others required. When you view the version tab of a Properties dialog, there’s no simple relationship between the data displayed and the structure of the resource. Using pyi-grab_version you can find an executable that displays the kind of information you want, copy its resource data, and modify it to suit your package.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください