'How to remove the exe part of the command line
This is my code. The input command line is var1 val1 var2 val2
:
var rawCmd = Environment.CommandLine;
// Environment.CommandLine adds the .exe info that I don't want in my command line:
// rawCmd = "path\to\ProjectName.vshost.exe" var1 val1 var2 val2
// A. This correction makes it work, although it is pretty ugly:
var cleanCmd = rawCmd.Split(new string[] { ".exe\" " }, StringSplitOptions.None)[1];
// B. This alternative should be cleaner, but I can't make it work:
var exePath = System.Reflection.Assembly.GetCallingAssembly().Location;
cleanCmd = rawCmd.Replace(string.Format($"\"{exePath}\" "), "");
So to make B work, I should be able to find the .vhost.exe
info (which I am not able to find).
But also I would like to know if there is a cleaner way to do all this.
As for the reason why I want to achieve this, here is the explanation (tl;dr: parsing a json from the command line): https://stackoverflow.com/a/36203572/831138
Solution 1:[1]
Instead of using
var rawCmd = Environment.CommandLine;
You can use:
var rawCmd = Environment.CommandLine;
var argsOnly = rawCmd.Replace("\"" + Environment.GetCommandLineArgs()[0] + "\"", "");
This will return "var1 val1 var2 val2" in your example. And it should work with the JSON example in the other post.
Solution 2:[2]
This only strips the command invocation part, no matter you write it as program
, program.exe
, .\program
, c:program
, "c:\Program Files\program"
, "\Program Files\program.exe"
, etc. or your path separator.
var exe = Environment.GetCommandLineArgs()[0]; // Command invocation part
var rawCmd = Environment.CommandLine; // Complete command
var argsOnly = rawCmd.Remove(rawCmd.IndexOf(exe),exe.Length).TrimStart('"').Substring(1);
It will leave double quotes, carets, and spaces between arguments untouched, even spaces at the beginning i.e., just after program name. Note there's an extra space at the beginning, don't ask me why. If that bothers you, remove first character, it should be easy. Hence the final .Substring(1)
. I define the two variables to make it more readable.
Edit:
Takes account of quoted invocation and the case where the program name string happens to appear as part of an argument (e.g., if your program is me.exe
and you run me "Call me Ishmael"
, .Replace
would trim the second me
too). Now I also take out that extra space.
Solution 3:[3]
This is a very old question, but as of Windows 10 20H2 and .NET Framework 4.8, all of the above solutions appear to be broken in one way or another (eg. double-quote delimited exe paths).
I needed to remove the exe from Environment.CommandLine
in a more generally robust way, so I decided to try a regex based approach. (Then I had 2 problems, lol.) Hope this helps somebody!
internal static string GetRawCommandLineArgs( )
{
// Separate the args from the exe path.. incl handling of dquote-delimited full/relative paths.
Regex fullCommandLinePattern = new Regex(@"
^ #anchor match to start of string
(?<exe> #capture the executable name; can be dquote-delimited or not
(\x22[^\x22]+\x22) #case: dquote-delimited
| #or
([^\s]+) #case: no dquotes
)
\s* #chomp zero or more whitespace chars, after <exe>
(?<args>.*) #capture the remainder of the command line
$ #match all the way to end of string
",
RegexOptions.IgnorePatternWhitespace|
RegexOptions.ExplicitCapture|
RegexOptions.CultureInvariant
);
Match m = fullCommandLinePattern.Match(Environment.CommandLine);
if (!m.Success) throw new ApplicationException("Failed to extract command line.");
// Note: will return empty-string if no args after exe name.
string commandLineArgs = m.Groups["args"].Value;
return commandLineArgs;
}
Testing done:
- exe paths with/without doublequote
- args containing doublequotes and also referencing the exe name
- invoking exe with no args returns empty string
[Edit] Testing NOT done:
- .NET 5 or any other runtime or OS
Solution 4:[4]
I have found a way to get the vhost path:
var exePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, System.AppDomain.CurrentDomain.FriendlyName);
...although I am afraid it could lead to inconsistencies depending on where the code is executed (Debug / production ...). I hope not, I'll have to keep testing.
Solution 5:[5]
If the number of spaces between elements is not important, you can just Join
the argument array, which is split on unquoted space characters, and doesn't contain the executable:
void Main(string[] args)
{
var cleanCmd = string.Join(" ", args);
// etc
}
Solution 6:[6]
Actually, the command invocation part is always enclosed in double quotes, even if the path doesn't contain any spaces. And it is always followed by a space character, even if no command line params are specified. So this should be enough in any case:
string args = Environment.CommandLine
.Substring(Environment.GetCommandLineArgs()[0].Length + 3);
But if you're like me and want to make it 100% waterproof, you can use:
string args = Environment.CommandLine
.TrimStart('"')
.Substring(Environment.GetCommandLineArgs()[0].Length)
.TrimStart('"')
.TrimStart(' ');
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | |
Solution 4 | Xavier Peña |
Solution 5 | RoadieRich |
Solution 6 | Kim Homann |