通过bash获取已编译/发布的dotnet应用程序的版本信息

6
我是一名有用的助手,可以为您进行文本翻译。
我正在开发一个ASP.Net Core项目,其中.csproj文件如下所示:
<PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>netcoreapp2.0</TargetFramework>
    <PreserveCompilationContext>true</PreserveCompilationContext>
    <AssemblyName>dummyapp</AssemblyName>
        <Version>17.12.1</Version>
    <RuntimeIdentifiers>centos.7-x64;win7-x64</RuntimeIdentifiers>
</PropertyGroup>

当这个应用程序发布到Windows系统时,我可以从其属性中获取版本信息。如上所述,显示为17.12.1。
或者,我可以在命令提示符中运行wmic datafile where name="filepath/app.exe" get Version /value命令,以获取相同的版本信息。

但是在Linux发行版中有没有标准的方法来获取相同的内容呢?

我已经研究过:

经过所有的尝试,似乎我需要在.csproj文件中实现其他内容,以便使用bash获取版本信息。有人可以指出需要做什么,或者给出一个提示吗。


Main 方法:

public static void Main(string[] args)
{
    var root = new Root();
    var config = new ConfigurationBuilder()
                     .SetBasePath(Directory.GetCurrentDirectory())
                     .AddJsonFile(SettingsFilename, optional: false,
                                  reloadOnChange: true)
                     .AddEnvironmentVariables()
                     .Build();

    config.Bind(root);

    //some codes

    var host = new WebHostBuilder()
                    .UseKestrel()
                    .UseUrls(root.AppUrl)
                    .UseConfiguration(config)
                    .UseContentRoot(Directory.GetCurrentDirectory())
                    .UseIISIntegration()
                    .ConfigureServices(s =>
                                     s.AddRouting().DetectTokenChange(config))
                    .UseSetting(WebHostDefaults.ApplicationKey, "dummyapp")
                    .Configure(app => app.UseRouter(r => r.MapPost("dumptoqueue", 
                                      async (context) => 
                                      await Task.Run(() => AddtoQueue(context)))))
                    .Build();
     host.Run();
}

使用命令行构建的应用程序:

dotnet publish -c release -r centos.7-x64

你尝试使用strings(1)了吗?这可能已经足够了。 - Basile Starynkevitch
@BasileStarynkevitch 看了链接的文档,--version 不是 strings 的一部分吗?我之前尝试过并在帖子中也提到了。如果您指的是其他内容,请明确指出。 - boop_the_snoot
你应该改进你的问题,也许通过展示你的 Main 代码(如果它是用 C# 编写的)并解释你的构建过程来实现。你需要更好地了解你的编译过程,并在你的问题中提供它。因此,请编辑你的问题以改进它。更多地介绍你在 Linux 上使用的编译器,并解释如何从源代码构建可执行文件。你用什么命令进行构建? - Basile Starynkevitch
似乎你的 Main 没有使用 args?为什么呢? - Basile Starynkevitch
让我们在聊天中继续这个讨论 - Basile Starynkevitch
显示剩余6条评论
3个回答

7

如果您只需要通过bash找到dll文件的版本,使用exiftool可能更容易。

$ exiftool Foo.dll | grep -i Version
ExifTool Version Number         : 10.55
Linker Version                  : 48.0
OS Version                      : 4.0
Image Version                   : 0.0
Subsystem Version               : 4.0
File Version Number             : 17.12.1.0
Product Version Number          : 17.12.1.0
File Version                    : 17.12.1.0
Product Version                 : 17.12.1
Assembly Version                : 17.12.1.0

甚至只需要这样:
$ exiftool -"ProductVersion" Foo.dll 
Product Version                 : 17.12.1

2

首先,让我们假设您的Linux程序已经编译成可执行文件yourprog(链接1:可执行文件),并且您正在从源代码构建它(因此您可以轻微更改源代码和构建过程)。无论您的构建过程是什么,或者您用什么编程语言编写它,都没有关系。那个yourprog文件可能是一些 ELF可执行文件或其他可通过 execve(2)系统调用理解的东西(例如脚本)。使用file(1)命令,例如file yourprog,查找它的文件格式。另请参见binfmt_misc并阅读有关#!(shebang)的内容。请注意,每个应用程序都是使用一些execve启动的(通常由您的Unix shell完成,但可能由其他某些东西完成,例如systemd)。
您可以使用strings ./yourprog命令,在可执行文件上运行strings(1),然后您将得到其中大多数的多字节字符串。可能有一些(很多)字符串包含版本信息(如果在编译阶段已经放置在其中)。
关于--version,这应该是您的程序遵循的一个惯例。请参见this的答案。因此,您应该改进您的源代码,使您的程序处理--version--help程序参数。这并没有什么神奇的,您需要编写代码(也许您的构建自动化可以生成一些包含版本字符串的C#代码;如何完成这项任务是不同的问题,并且取决于您使用的特定构建实用程序;如果您使用makeninja,您只需添加一些特定规则,例如在您的Makefilebuild.ninja中)。因此,您需要了解和改进您的构建过程。如果您使用C#编码,您需要从您的Main中处理它,因此您需要改进您的Main以解析args并适当地处理--help--version(在Windows上,可能是其他内容)。顺便说一句,在其他操作系统上,甚至能够传递一些程序参数来查询版本并获取帮助也是有帮助的(我不知道Windows,但也许它可以使用/version/help而不是--version--help)。
请注意,软件版本控制始终是人为约定的(即使使用某些版本控制系统,例如git,也很有帮助)。因此,获取该版本可能不是“标准”的,即使它非常容易(这也可能取决于您的项目惯例和编码习惯,以及您的版本控制系统)。我猜您可以在构建中生成一些_timestamp_version.cs生成的C#文件,并适当编译它,并使_timestamp_version.cs定义一些常量字符串以从您的Main中显示。在使用make的C语言中,这是一个非常简单的技巧,您只需要将其适应到您的编程语言和构建过程中(还可以参见this Makefile及其与git相关的_timestamp.c更详细的内容);在Unix哲学中,这是非常常见的做法,我很惊讶您会问这个问题!
也许有一些API可以在C#中查询一些版本元数据(可能与反射相关),但这是一个非常不同的问题。你只需要按照惯例编写代码以显示一些与版本相关的字符串,例如--version....
请记住,即使在Windows上,特别是在POSIX和Linux上,编译器(compilers)实际上与集成开发环境(IDEs)几乎不同。即使在Windows上,IDE只是一个能够运行外部程序(例如编译器、调试器、构建自动化工具等)的源代码编辑器。您可以(而且通常应该)在命令行中运行编译器,而不是在IDE中运行。因此,您可以通过生成一些C#代码(例如生成一个文件定义几个与版本相关的字符串常量)来进行基本的元编程。阅读Unix哲学(在我看来,这种哲学甚至在微软内部也得到了应用)。
请记住,据我所知,.csproj文件不是C#规范的一部分(这是一份用英文撰写的技术报告)。另请参见this

感谢您在这个答案中指出了这么多问题。我会研究所有提到的方面,是的,我的dotnet core应用程序是使用C#编译的。如果一切顺利,我会回来接受您的答案。由于我正在制作跨平台应用程序,Linux对我来说是一个新的领域。所以请耐心等待,直到我找到解决方案 :) - boop_the_snoot
C#应用程序并不是本机应用程序。这里提出的许多想法,例如ELF对象(它们是PE而不是ELF),都不适用。关于元编程的部分甚至更加没有意义,因为版本已经在csproj文件中定义(这填补了此处“Make”/“ninja”的角色)。 - omajid
据我所知,当我使用mono编译一些C#代码时,我没有任何csproj文件。因此,这些文件不是C#定义的一部分。 - Basile Starynkevitch
这个问题被标记为“.net core”。我认为可以安全地假设提问者正在使用.NET Core的默认构建系统。 - omajid

0
查看与您的 .exe 文件一起生成的 dummyapp.deps.json 文件。从这个文件中,您应该能够找到您的应用程序的版本。
查看(可能有点过时的)deps.json 文件的文档:runtime-configuration-file

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接