“版本文件”是啥样的?

Posted

技术标签:

【中文标题】“版本文件”是啥样的?【英文标题】:What does a "version file" look like?“版本文件”是什么样的? 【发布时间】:2013-01-15 11:07:37 【问题描述】:

我已经在谷歌上搜索了很长时间,但没有结果。 PyInstaller 手册说:

--版本文件=文件 将版本资源从 FILE 添加到 exe

听起来不错。我想将版本信息放在我的可执行文件中。问题是我不知道“版本文件”是什么样的,而且我找不到一个可以使用的示例。我会考虑一个版本文件的示例作为这个问题的可接受答案。


我尝试过的

手册还说:

版本 仅限 Windows NT 系列。版本='myversion.txt'。采用 GrabVersion.py 从可执行文件中窃取版本资源,以及 然后编辑输出以创建您自己的。 (版本的语法 资源太神秘了,我不会尝试从 划痕。)

我现在已经尝试使用我系统中的无数可执行文件进行此操作。我只是不断收到这些错误:

Traceback(最近一次调用最后一次):
  文件“C:\pyinstaller-2.0\utils\GrabVersion.py”,第 42 行,在
    vs = versioninfo.decode(sys.argv[1])
  解码中的文件“C:\pyinstaller-2.0\PyInstaller\utils\versioninfo.py”,第 33 行
    nm = win32api.EnumResourceNames(h, RT_VERSION)[0]
IndexError: 列表索引超出范围

在没有版本信息的可执行文件上,并且:

Traceback(最近一次调用最后一次):
  文件“C:\pyinstaller-2.0\utils\GrabVersion.py”,第 43 行,在
    打印与
  文件“C:\pyinstaller-2.0\PyInstaller\utils\versioninfo.py”,第 147 行,在 __repr__
    %(缩进,self.ffi.__repr__(缩进),缩进,
  文件“C:\pyinstaller-2.0\PyInstaller\utils\versioninfo.py”,第 251 行,在 __repr__
    "filevers=%s," % fv,
TypeError:字符串格式化期间并非所有参数都转换了

剩下的。

【问题讨论】:

【参考方案1】:

刚刚快速浏览了一下来源。看来版本文件应该是 Python 源代码本身作为提供的版本文件,然后被读取然后eval'ed。

GrabVersion.py 脚本似乎会产生您已经发现的错误,因此我修改了FixedFileInfo__repr__ 函数以手动将元组参数转换为字符串。

Windows cmd.exe 嵌入了 Windows 版本资源,这是来自 GrabVersion.py 的输出,您可以将其保存到文件并提供给 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])])
  ]
)

我没有尝试使用 PyInstaller 设置版本资源,所以我不确定这是否可行,我会对您的反馈感兴趣。

【讨论】:

太棒了!除了一件小事之外,这非常有效 - 生成的可执行文件中的“产品版本”是空白的。不过对我来说没什么大不了的。 有趣的是,产品版本对我来说很好用。确保你得到这一行(大约第 4 行):prodvers=(0, 0, 1, 0), 并使用逗号而不是句点。我不知道它有什么区别,但产品版本再次出现在字符串表中(大约第 24 行):StringStruct(u'ProductVersion', u'0.0.1.0')]) 使用句点的地方。 ProductVersion 在 .exe 中对我来说也是空白的。 请注意,字符串必须(双)以空值结尾,否则您可能会遇到可怕的问题。另请参阅Compiler error when using GetStringFileInfo in InnoSetup on application created with PyInstaller。 我发现了 ProductVersion 问题。它的格式必须与 prodvers 完全相同。您不能使用句点,必须使用逗号,并且它们之间必须有空格。另一方面,FileVersion 可以使用您自己的格式。【参考方案2】:

我可能在之前的答案中遗漏了这一点,或者 PyInstaller 可能在最初提供这些答案后已经更新,但是 PyInstaller 的当前文档使用 PyInstaller 提供的命令行工具教授 fairly simple method for this(虽然我错过了这部分是我最初几次查看文档的时候)。

将此工具指向您系统上具有“好看”版本信息的 .exe 文件,它将创建一个可供您用作起点的可读、注释、可编辑的版本资源文件。

pyi-grab_version executable_with_version_resource

默认情况下将文件file_version_info.txt 写入工作目录。

在我的本地 svn.exe 副本上运行上述内容会产生:

# 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, 9, 7, 30920),
prodvers=(1, 9, 7, 30920),
# 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=0x4,
# 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'Apache Software Foundation'),
    StringStruct(u'FileDescription', u'svn'),
    StringStruct(u'FileVersion', u'1.9.7'),
    StringStruct(u'InternalName', u'SVN'),
    StringStruct(u'LegalCopyright', u'Copyright (c) The Apache Software Foundation'),
    StringStruct(u'OriginalFilename', u'svn.exe'),
    StringStruct(u'ProductName', u'Subversion'),
    StringStruct(u'ProductVersion', u'1.9.7 (r1800392)')])
  ]), 
VarFileInfo([VarStruct(u'Translation', [1033, 1200])])
  ]
)

根据您的目的编辑它,并将其作为 --version-file 反馈给 PyInstaller,例如

pyinstaller [options] myscript.py --version-file file_version_info.txt

【讨论】:

您的链接已损坏 链接更新:pyinstaller.readthedocs.io/en/stable/…【参考方案3】:

使用较早的答案创建您的版本文件,并将其保存为version.rc

找到filename.spec 文件打开它。 接下来在该脚本中,找到:

exe = EXE(pyz,...)

在整个部分的末尾添加这段代码以自动将版本信息嵌入到您的 exe 文件中

version='version.rc'

保存它,然后再次启动 pyinstaller,这次使用以下代码运行安装程序:

pyinstaller filename.spec 

这不仅会创建 exe 文件本身,还会包含您的所有版本信息。

如果您可能没有考虑过,请将filename 替换为您的程序文件名

【讨论】:

【参考方案4】:

我在 Python 3 中遇到了 Pyinstaller --version-file 选项的问题,我使用 Simple Version Resource Tool 解决了它。

使用此工具,您可以显示任何版本资源的内容,只需将 /vo 选项与任何可执行文件一起使用:verpatch.exe /vo c:\Windows\System32\cmd.exe

要向可执行文件添加 版本资源,只需按照以下示例:

verpatch.exe script.exe 1.0.0.0 /va /pv 1.0.0.0 /s description "Your product description" /s product "Your product name" /s copyright "Your company name, 2016" /s company "Your company name"

【讨论】:

从我测试此工具后的经验分享,它似乎添加了信息,但如果您打算在之后使用工具signtool.exe 添加数字签名,那么verpatch.exe 会搞砸并导致签名错误。提供--version-file 的另一个答案为我成功使用了signtool【参考方案5】:

请注意,版本文件使用 Python 代码,因此您可以将其扩展名为 .py 而不是 .rc

这将允许您在 IDE 中查看它的格式,检查错误(当然,忽略“未解析的引用”),以及执行 Python 允许您执行的任何其他操作。

【讨论】:

【参考方案6】:

我在网上找到了一个用于创建版本文件的简单包:https://pypi.org/project/pyinstaller-versionfile/#description。根据链接中的信息安装后,应用一个简单易读的代码就足够了:

import pyinstaller_versionfile

pyinstaller_versionfile.create_versionfile(
    output_file="versionfile.txt",
    version="1.2.3.4",
    company_name="My Imaginary Company",
    file_description="Simple App",
    internal_name="Simple App",
    legal_copyright="© My Imaginary Company. All rights reserved.",
    original_filename="SimpleApp.exe",
    product_name="Simple App"
)

作为其操作的结果,我们获得了一个文件,例如正如@mac 的回答一样。该文件已准备好在 pyinstaller 中使用。

【讨论】:

以上是关于“版本文件”是啥样的?的主要内容,如果未能解决你的问题,请参考以下文章

Unity 项目的 .gitignore 文件是啥样的?

图像通用文件扩展名的正则表达式是啥样的?

SynonymType.entities 的映射是啥样的?

云原生时代的分布式文件系统是啥样的?

频率为随机变量的正弦曲线 - FFT 脉冲是啥样的?

是啥样的测试?巢穴