pythonwindowspyinstaller

What does a "version file" look like?


I've been googling this for ages now without results. The PyInstaller manual says:

--version-file=FILE
    add a version resource from FILE to the exe

That sounds nice. I want to put version information in my executables. The problem is that I have no clue what a "version file" looks like and I can't find a single example of one that I can use. I would consider an example of a version file as an acceptable answer to this question.


What I've tried

The manual also says:

version
Windows NT family only. version='myversion.txt'. Use GrabVersion.py to steal a version resource from an executable, and then edit the ouput to create your own. (The syntax of version resources is so arcane that I wouldn't attempt to write one from scratch.)

I have attempted this with countless executable files from my system now. I just keep getting these errors:

Traceback (most recent call last):
  File "C:\pyinstaller-2.0\utils\GrabVersion.py", line 42, in 
    vs  = versioninfo.decode(sys.argv[1])
  File "C:\pyinstaller-2.0\PyInstaller\utils\versioninfo.py", line 33, in decode
    nm = win32api.EnumResourceNames(h, RT_VERSION)[0]
IndexError: list index out of range

on executables that has no version information, and:

Traceback (most recent call last):
  File "C:\pyinstaller-2.0\utils\GrabVersion.py", line 43, in 
    print vs
  File "C:\pyinstaller-2.0\PyInstaller\utils\versioninfo.py", line 147, in __repr__
    % (indent, self.ffi.__repr__(indent), indent,
  File "C:\pyinstaller-2.0\PyInstaller\utils\versioninfo.py", line 251, in __repr__
    "filevers=%s," % fv,
TypeError: not all arguments converted during string formatting

On the rest.


Solution

  • Just had a quick look at the sources. It appears that the version file is expected to be Python source itself as the provided version file with be read and then eval'ed.

    The GrabVersion.py script appears to generate errors as you've already found, so I modified the __repr__ function of FixedFileInfo to manually convert tuple arguments to strings.

    The Windows cmd.exe has a Windows version resource embedded, here's the output from GrabVersion.py which you would save to a file and feed to PyInstaller.

    VSVersionInfo(
      ffi=FixedFileInfo(
        filevers=(6, 1, 7601, 17514),
        prodvers=(6, 1, 7601, 17514),
        mask=0x3f,
        flags=0x0,
        OS=0x40004,
        fileType=0x1,
        subtype=0x0,
        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.7601.17514 (win7sp1_rtm.101119-1850)'),
            StringStruct(u'InternalName', u'cmd'),
            StringStruct(u'LegalCopyright', u'\xa9 Microsoft Corporation. All rights reserved.'),
            StringStruct(u'OriginalFilename', u'Cmd.Exe'),
            StringStruct(u'ProductName', u'Microsoft\xae Windows\xae Operating System'),
            StringStruct(u'ProductVersion', u'6.1.7601.17514')])
          ]), 
        VarFileInfo([VarStruct(u'Translation', [1033, 1200])])
      ]
    )
    

    I haven't tried setting a version resource with PyInstaller so I'm not sure if this will work, I'd be interested in your feedback.