How can we get argv[0] in C#?
Asked Answered
G

2

5

With C/C++, we can get argv[0]:

printf("%s\n",argv[0])

In C#, args begins with argv[1].

Non of bellow API gives exactly argv[0], at least under Linux:

AppDomain.CurrentDomain.FriendlyName: only gives the name, no path
Process.GetCurrentProcess().ProcessName: gives wrong result with symbol link, and no path
Process.GetCurrentProcess().MainModule.FileName:  gives wrong result with symbol link, and the path is always absolute

FYI: under Linux with the above C/C++ code (whose result is treated as the golden standard here), it prints the exact path (absolute or relative) that is used to invoke the program, and if you invoke the program through any symbol link, the symbol link's name is printed instead of the real program.

I ask this question since I try to write a wrapper program using C# under Ubuntu, which should pass argv[0] through to be fully transparent in case the wrapped program's behavior depends on argv[0].

Gynecoid answered 1/5, 2019 at 3:21 Comment(5)
C# is base 0. What's the error message when you printf("%s\n",argv[0])?Jeffreyjeffreys
@Jeremy Thompson ? Can't understand what you said.Gynecoid
If you want the path of the Assembly can you try: var dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location.Replace("bin\\Debug", string.Empty));Jeffreyjeffreys
Assembly.GetExecutingAssembly().Location will give you the full path to the assembly. In .Net Core this will be the DLL, for a .Net Framework console application this will be the .exeLinalinacre
Please read the question, I don't want to get the assembly which many API can provide. I need to get argv[0] exactly in a C/C++ program. which is often different than assembly name There should be a property of Program that just provide this.Gynecoid
Y
7

Environment.CommandLine and Environment.GetCommandLineArgs() should contain the full and unmodified command line.

Yehudi answered 1/5, 2019 at 3:34 Comment(6)
Ha, is that all he/she wanted.Jeffreyjeffreys
Tested on Ubuntu, works for most case, but still not working for relative command line, it get transfered to absolute command line, maybe this is considered to be a limitation/bug of the runtime?Gynecoid
A work around for this(if there is really no solution) is to wrap the C# wrapper within another wrapper written in language that support exact argv[0] such as C/C++ (or bash?) which pass argv[0] as argv[1] and so on and the C# program treat argv[1] as argv[0] and so on.Gynecoid
Huh, it works as expected on .NET Framework, but not on .NET Core. I'm guessing it's getting mangled to hide the dotnet/self-contained launcher executable. You may have to refer to platform-native APIs to obtain the original command line, if possible.Yehudi
@Yehudi Do you know how to pass exact argv[0] down to the started process with ProcessStartInfo? I don't like to ask another question just for this.Gynecoid
@Gynecoid That is a different question and should be asked as a different question ;-) (sorry if you already have, it just looks like your comment hasn’t been addressed).Bradawl
R
0

The accepted answer doesn't work for me on .NET 5 on Linux, I get $PROJECT_DIRECTORY/bin/Debug/net5.0/$PROJECT_NAME.dll. Further, this doesn't change if symlinks are used.

Instead I have to use this non-portable hack (taken from this comment):

(await File.ReadAllTextAsync("/proc/self/cmdline")).Split('\0')[0]

Result:

$ bin/Debug/net5.0/bpm
argv[0]: bin/Debug/net5.0/bpm
$ ln -s bin/Debug/net5.0/bpm foo
$ ./foo
argv[0]: ./foo
Retroflex answered 13/5, 2021 at 16:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.