Reputation: 11062
I want to run some cmd
command from c#
code. I followed some blogs and tutorial and got the answer, but I am in little bit confused i.e how should I pass multiple arguments?
I use follow code:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
startInfo.FileName = "cmd.exe";
startInfo.Arguments =
...
What will be the startInfo.Arguments
value for the following command line code?
makecert -sk server -sky exchange -pe -n CN=localhost -ir LocalMachine -is Root -ic MyCA.cer -sr LocalMachine -ss My MyAdHocTestCert.cer
netsh http add sslcert ipport=127.0.0.1:8085 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF} clientcertnegotiation=enable
Upvotes: 39
Views: 143958
Reputation: 518
.NetStandard 2.1
includes a nice feature called ArgumentList
that automatically escapes arguments for you when given a Collection<string>
. But (like in my case) if you cannot target .NetStandard 2.1
you are out of luck...BUT! I dug into the ProcessStartInfo
source code for .NetStandard 2.1
and was able to extract this class:
internal static class PasteArguments {
internal static void AppendArgument(StringBuilder stringBuilder, string argument) {
// from https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/PasteArguments.cs
if (stringBuilder.Length != 0) {
stringBuilder.Append(' ');
}
// Parsing rules for non-argv[0] arguments:
// - Backslash is a normal character except followed by a quote.
// - 2N backslashes followed by a quote ==> N literal backslashes followed by unescaped quote
// - 2N+1 backslashes followed by a quote ==> N literal backslashes followed by a literal quote
// - Parsing stops at first whitespace outside of quoted region.
// - (post 2008 rule): A closing quote followed by another quote ==> literal quote, and parsing remains in quoting mode.
if (argument.Length != 0 && ContainsNoWhitespaceOrQuotes(argument)) {
// Simple case - no quoting or changes needed.
stringBuilder.Append(argument);
} else {
stringBuilder.Append(Quote);
int idx = 0;
while (idx < argument.Length) {
char c = argument[idx++];
if (c == Backslash) {
int numBackSlash = 1;
while (idx < argument.Length && argument[idx] == Backslash) {
idx++;
numBackSlash++;
}
if (idx == argument.Length) {
// We'll emit an end quote after this so must double the number of backslashes.
stringBuilder.Append(Backslash, numBackSlash * 2);
} else if (argument[idx] == Quote) {
// Backslashes will be followed by a quote. Must double the number of backslashes.
stringBuilder.Append(Backslash, numBackSlash * 2 + 1);
stringBuilder.Append(Quote);
idx++;
} else {
// Backslash will not be followed by a quote, so emit as normal characters.
stringBuilder.Append(Backslash, numBackSlash);
}
continue;
}
if (c == Quote) {
// Escape the quote so it appears as a literal. This also guarantees that we won't end up generating a closing quote followed
// by another quote (which parses differently pre-2008 vs. post-2008.)
stringBuilder.Append(Backslash);
stringBuilder.Append(Quote);
continue;
}
stringBuilder.Append(c);
}
stringBuilder.Append(Quote);
}
}
Example Usage:
static string GetArgumentStr(List<string> argList) {
if(argList == null || argList.Count == 0) {
return string.Empty;
}
var sb = new StringBuilder();
foreach(var arg in argList) {
PasteArguments.AppendArgument(sb, arg);
}
return sb.ToString();
}
Upvotes: 1
Reputation: 21
StartInfo.Arguments = @"/C cd C:\Users\yoooo\Desktop && echo This is a sample text file > sample.txt"
Upvotes: 2
Reputation: 81
Remember to include System.Diagnostics
ProcessStartInfo startInfo = new ProcessStartInfo("myfile.exe"); // exe file
startInfo.WorkingDirectory = @"C:\..\MyFile\bin\Debug\netcoreapp3.1\"; // exe folder
//here you add your arguments
startInfo.ArgumentList.Add("arg0"); // First argument
startInfo.ArgumentList.Add("arg2"); // second argument
startInfo.ArgumentList.Add("arg3"); // third argument
Process.Start(startInfo);
Upvotes: 7
Reputation: 13217
It is purely a string:
startInfo.Arguments = "-sk server -sky exchange -pe -n CN=localhost -ir LocalMachine -is Root -ic MyCA.cer -sr LocalMachine -ss My MyAdHocTestCert.cer"
Of course, when arguments contain whitespaces you'll have to escape them using \" \", like:
"... -ss \"My MyAdHocTestCert.cer\""
See MSDN for this.
Upvotes: 57
Reputation: 647
startInfo.Arguments = "/c \"netsh http add sslcert ipport=127.0.0.1:8085 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF} clientcertnegotiation=enable\"";
and...
startInfo.Arguments = "/c \"makecert -sk server -sky exchange -pe -n CN=localhost -ir LocalMachine -is Root -ic MyCA.cer -sr LocalMachine -ss My MyAdHocTestCert.cer\"";
The /c
tells cmd to quit once the command has completed. Everything after /c
is the command you want to run (within cmd
), including all of the arguments.
Upvotes: 3
Reputation: 4785
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = @"/c -sk server -sky exchange -pe -n CN=localhost -ir LocalMachine -is Root -ic MyCA.cer -sr LocalMachine -ss My MyAdHocTestCert.cer"
use /c as a cmd argument to close cmd.exe once its finish processing your commands
Upvotes: 4