1

在 Windows 上,我使用以下内容来获取可执行文件版本。

FileVersionInfo.GetVersionInfo("filepath.exe").FileVersion

但是当我在 Mac 上对 unix 可执行文件类型使用相同的文件时,它返回 null

4

2 回答 2

3

(重新发布我的评论作为答案):

最短的答案:

你不能

简短的回答:

  • FileVersionInfo.GetVersionInfo()方法尝试VERSIONINFO从 Win32 PE 二进制可执行映像中读取资源数据。

    • 在 Windows 上,大多数可执行文件是 PE 映像,可能包含也可能不包含VERSIONINFO结构。
    • 在 macOS 和 Linux 上,大多数(但不是全部)可执行文件分别是 Mach-O 和 ELF 映像,它们根本不包含结构VERSIONINFO
      • 但是,.NET 程序集始终使用 PE 格式,这意味着它们可以VERSIONINFO在其资源部分中包含一个结构。
  • 这意味着在 Mac 或 Linux 上,您可以使用FileVersionInfo.GetVersionInfo()仅读取 PE 可执行文件,另外需要注意的是(截至 2021 年 4 月)只能读取特定的 .NET 程序集,而非非 .NET 程序集 PE 可执行文件)可以读取. 因为 ELF 和 Mach-O 可执行文件不包含 Win32 资源部分,所以您不能FileVersionInfo.GetVersionInfo()在这些类型的可执行文件上使用。

更长的答案:

Windows 的*.exe文件使用“PE”可执行映像格式:https ://docs.microsoft.com/en-us/windows/win32/debug/pe-format - .NET 程序集也使用这种格式。

这种格式能够将“资源”存储在文件的专用部分中,该部分可以选择包含VERSIONINFO记录结构在内存中表示为VS_VERSIONINFO)。请注意,这VERSIONINFO是 Microsoft/Win32 特定的数据结构。

其他操作系统使用不同的可执行映像格式:Linux 和大多数 Unix 使用 ELF,而 macOS 使用“Mach-O”格式——两者都不使用VERSIONINFO.

请注意,在非 Windows 操作系统上使用 .NET Core 时,“.NET 程序集”文件仍然 是使用 PE 可执行格式*.exe*.dll文件,但它们不会由非 Windows 操作系统直接执行:相反,它们将有一个加载程序,它启动 .NET 运行时,然后将 .NET 程序集加载到其中(就像您*.jar通过运行从 Windows 上的文件运行 Java 程序的方式一样java.exe yourJar.jar)。

因此,由于 .NET Core 始终对 .NET 程序集使用 PE 格式,即使在非 Windows 平台上,该FileVersionInfo.GetVersionInfoAPI 仍可用于从其他 .NET 程序集中提取版本信息,但不适用于非 PE可执行图像文件。

于 2020-09-09T04:46:34.787 回答
0

最短的答案

你不能(目前)。

简短的回答

正如 Dai 在他们的回答中解释的那样,版本信息 Api 依赖于底层的原生 Api,而后者又期望版本信息出现在 PE(可移植可执行文件)标头中。由于 Unix/macOS 可执行文件使用不同的可执行文件头,因此它们不受支持。

简答

由于 Unix(和 macOS)可执行文件不使用 PE 标头格式,因此您不能FileVersionInfo在这些文件上使用,因为此 Api 当前依赖于 PE 标头格式。

遗憾的是,当 .net Core 在 Unix/maxOS 系统上运行时,也不可能在所有 PE 文件上使用,因为它是支持.net 程序集FileVersionInfo的实现决定。这更容易实现,因为它不需要基于资源的 PE 标头所需要的完整 PE 标头支持。VERSIONINFO

完整的答案

.net core 上的实现FileVersionInfo不支持 Unix/macOS 可执行文件使用的可执行文件头格式。 FileVersionInfo仅支持包含 CLI 元数据的 PE 文件。也就是说,.net 程序集

源代码中有一些注释FileVersionInfo讨论了即使在这种级别的支持下的一些问题/限制。这说明这些问题应该很少出现,但如果有必要,可能会实现完整的 PE 资源解析器并且这也将提供对本机(非 .net)Windows 可执行文件中的版本信息的支持。

评论继续认为,对此的需求预计也将极为罕见,因此我认为优先级不会很高。

令人沮丧的是,除了在这些源注释中之外没有记录,并且尝试在本机 EXE 图像上使用 Api 会默默地“失败”,产生一个基本上是空的FileVersionInfo对象,这可能与任何数量的失败相混淆。

为了完整起见,以下是相关FileVersionInfo.Unix.cs来源和评论:

private FileVersionInfo(string fileName)
{
  _fileName = fileName;

  // For managed assemblies, read the file version information from the assembly's metadata.
  // This isn't quite what's done on Windows, which uses the Win32 GetFileVersionInfo to read
  // the Win32 resource information from the file, and the managed compiler uses these attributes
  // to fill in that resource information when compiling the assembly.  It's possible
  // that after compilation, someone could have modified the resource information such that it
  // no longer matches what was or wasn't in the assembly.  But that's a rare enough case
  // that this should match for all intents and purposes.  If this ever becomes a problem,
  // we can implement a full-fledged Win32 resource parser; that would also enable support
  // for native Win32 PE files on Unix, but that should also be an extremely rare case.
  if (!TryLoadManagedAssemblyMetadata())
  {
    // We could try to parse Executable and Linkable Format (ELF) files, but at present
    // for executables they don't store version information, which is typically just
    // available in the filename itself.  For now, we won't do anything special, but
    // we can add more cases here as we find need and opportunity.
  }
}
于 2021-04-25T01:30:02.600 回答