6

I'm developing an ASP.Net Core project, where the .csproj file looks like this:

<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>

When this app is published for Windows, I can get the version info from its properties. Which shows 17.12.1 as mentioned.

Alternatively I can run wmic datafile where name="filepath/app.exe" get Version /value and get the same version using command prompt.


But is there a standard way to get the same in linux distro?

I've looked into:

After all the trials, it seems, I need to implement something else in the .csproj file so as to get the version info using bash. Can someone point out what needs to be done, or give a hint about the same.


Main method:

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();
}

App built using the command line:

dotnet publish -c release -r centos.7-x64
boop_the_snoot
  • 3,209
  • 4
  • 33
  • 44
  • Did you try to use [strings(1)](http://man7.org/linux/man-pages/man1/strings.1.html) ? It might be enough – Basile Starynkevitch Dec 23 '17 at 07:39
  • @BasileStarynkevitch Looking at the linked doc, isn't `--version` part of `strings` as I've tried it earlier and also mentioned in the post. If you were pointing something else, can you explicitly point that out? – boop_the_snoot Dec 23 '17 at 07:44
  • You should improve your question by perhaps showing the code of your `Main` (if it is coded in C#) and by explaining your build procedure. You need to understand more your [compilation](https://en.wikipedia.org/wiki/Compilation) process, and give it in your question. So please **edit your question** to improve it. Tell more about the compiler you are using on Linux, and explain how you build your executable from source code. What commands do you use for that build ? – Basile Starynkevitch Dec 23 '17 at 08:15
  • @BasileStarynkevitch Updated my question as suggested – boop_the_snoot Dec 23 '17 at 08:24
  • Notice that even in C# it is allowed to generate some C# source file from some external data in your build procedure. – Basile Starynkevitch Dec 23 '17 at 08:38
  • It looks like your `Main` is not using `args` ? Why? – Basile Starynkevitch Dec 23 '17 at 08:44
  • I reformatted the code to make it less wide. Could you please improve the formatting, I am not familiar with C# – Basile Starynkevitch Dec 23 '17 at 08:48
  • I did not pass any arguments because there was no need of any yet. It was the default format format set by the dotnet template. I'm going through all the links you posted in your answer. kindly wait – boop_the_snoot Dec 23 '17 at 08:58
  • If you want to (and I believe you should) handle `--version` and `--help` (or perhaps `/version` and `/help` on Windows) you need to handle `args` – Basile Starynkevitch Dec 23 '17 at 08:59
  • Yes I'm thinking about the same. In the meantime installing linux distro to work it out – boop_the_snoot Dec 23 '17 at 09:00
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/161849/discussion-between-basile-starynkevitch-and-o-o). – Basile Starynkevitch Dec 23 '17 at 09:01

2 Answers2

6

It might just be easier to use exiftool, if all you need to do via bash is to find the version of a dll file.

$ 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

Or even just:

$ exiftool -"ProductVersion" Foo.dll 
Product Version                 : 17.12.1
omajid
  • 14,165
  • 4
  • 47
  • 64
2

First, let's assume your Linux program is compiled into yourprog executable and that you are building it from its source code (so you can slightly change both the source code and the building procedure). It does not matter what is your build procedure, or in what programming language you are coding it. That yourprog file is probably some ELF executable or something else (e.g. a script) understandable by the execve(2) system call. Use file(1), e.g. as file yourprog, to find out what its file format. See also binfmt_misc and read about #! (shebang). Notice that every application program is started with some execve (generally done by your Unix shell, but perhaps by something else, for example systemd).

You could use strings(1) on that executable using strings ./yourprog; you'll then get most of the multibyte strings in it. Probably some of the (many) strings contain version information (if it has been put there at compile stage).

Regarding --version, it should be a convention followed by your program. See this answer. So you should improve your source code so that your program handle both --version and --help program arguments. There is no magic involved, you have to code that (perhaps your build automation could generate some C# code containing version string; how that should be done is a different question, and depend upon the particular build utility that you use; with make or ninja you'll just add some specific rules, e.g. in your Makefile or your build.ninja). So you need to understand and improve your build procedure. If you code in C#, you need to handle that from your Main, so you need to improve your Main to parse args and handle appropriately --help and --version (on Windows, it could be something else). BTW, IMHO even on other OSes it is helpful to be able to pass some program argument to query the version and to get help (I don't know Windows, but perhaps it might be /version and /help instead of --version and --help).

Notice that software versioning is always a human convention (even if using some version control system, e.g. git, is helpful). So getting that version cannot be "standard", even if it is very easy (it could also depend upon your project's conventions and coding habits, and perhaps your version control system). I guess that you could generate in your build some _timestamp_version.cs generated C# file and compile it appropriately and have that _timestamp_version.cs define some constant strings to be shown from your Main. In C with make that is a really easy trick and you just need to adapt it to your programming language and your build procedure (see also this Makefile and its _timestamp.c for a more elaborate thing related to git); in the Unix philosophy it is very common to do that, and I am surprised that you are asking that!

Maybe there is some API to query some version metadata in C# (probably related to reflection), but that is a very different question. And you just should conventionally code to display some version related string with --version....

Remember that (even on Windows, and certainly on POSIX & Linux) compilers are practically not the same as IDEs. An IDE -even on Windows- is just a source code editor capable of running external programs (e.g. compilers, debuggers, build automation tools ...). You can (and you often should) run a compiler outside of an IDE, on the command line. So you can do basic metaprogramming by generating some C# code (e.g. generating a file defining a few string constants related to version, etc). Read about the Unix philosophy (which IMHO is somehow even used inside Microsoft).

Remember that .csproj files are not, IIRC, part of the C# specification (a technical report written in English). See also this.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Appreciate your effort into pointing out so many things in this answer. Will look into all the mentioned aspects, and yes my dotnet core application is compiled using `C#`. I'll get back and accept your answer if everything works out. As I'm making a cross-platform applicaition, linux is a new turf for me. So bear with me until I found the solution :) – boop_the_snoot Dec 23 '17 at 08:02
  • C# applications are *not* native applications. A lot of ideas mentioned here - such as ELF objects (they are PE instead) - are just not applicable. The bit on metaprogramming makes even less sense, given that the version is already defined in the csproj file (which fills in the role of `Make`/`ninja` here). – omajid Feb 01 '18 at 23:17
  • IIRC, when I compile some C# code with mono, I don't have any `csproj` file. So these files are not part of the C# definitions. – Basile Starynkevitch Feb 02 '18 at 05:18
  • The question is tagged as ".net core".. I think it should be safe to assume that the individual asking the question is using the default build system from .NET Core. – omajid Feb 05 '18 at 14:51