19

In .NET, we can easily access split command line arguments in a string array from the argument of Main(string[]) or Environment.GetCommandLineArgs(). However, is there a way to get the unparsed command line as one string?

Background: my app is adding itself to FileExplorer context menu (like Notepad++ does). When it's launched this way, the filename is passed in without quoting, which means if there are spaces in the path, it's broken down. I know I can fix this by embrace %1 in quotation marks in the registry like myapp.exe "%1", but when I check other application's registry they didn't do so. They are plain like notepad.exe %1 - they got the complete command line. I want to know if it is possible in .NET and how.

NS.X.
  • 2,072
  • 5
  • 28
  • 55

2 Answers2

26

Try using: Environment.CommandLine

J. Scott Elblein
  • 4,013
  • 15
  • 58
  • 94
JMC
  • 910
  • 7
  • 11
6

To get the unparsed, raw, unmodified command line you have to P/Invoke GetCommandLine from kernel32. Some parsing will take place by the operating system. For example, an IO redirection such as >foo.txt will be excluded from the command line text regardless of the technique used.

Environment.CommandLine may be sufficient, but be aware that it removes interstitial spaces between arguments (unless the argument itself is enclosed in quotes) and it removes the quotes from quoted arguments.

For example, for the command line:

test.exe this is "a test"

Environment.CommandLine equals: "this is a test"

But GetCommandLine yields: "test.exe this is "a test"" with the spaces and quotes intact, along with the path of the exe.

Note that when using this technique, you have to parse the command line text manually, which may involve stripping off the path to the exe, which may itself be enclosed in quotes if the path contains spaces.

Wyck
  • 10,311
  • 6
  • 39
  • 60
  • 1
    Huh, don't show the behavior you describe. `Environment.CommandLine` matches the `PInvoke` in all cases I try. – Christopher King Sep 08 '16 at 21:02
  • I also get the same result from `Environment.CommandLine` as from the PInvoke in .NET 4.5.2. – DeCaf Sep 13 '16 at 12:43
  • You're right. Both are giving the same results on my current system setup. I haven't tracked down the sample app and system I used to test this (it was a year ago), but if it was ever broken, it must have been from an older OS+.NET+Compiler version set than what's current today. This may apply to only an older update of VS, for example. Not sure which versions. When I get a chance, I'll try to figure out which versions I used. Regardless, you're right that it's not evident in current software. Maybe there was a bug fix at some point? I can't conclude it wasn't true at some point. Thx. – Wyck Sep 15 '16 at 04:35
  • 1
    I can reproduce a difference with command `dotnet run p1=123 p2="one two"`. It converts to: `dotnet run p1=123 "p2=one two"`. – Crouching Kitten Jan 13 '20 at 17:38