'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