I want to call a Process from C# with multiple parameters.
When i call:
ProcessStartInfo info = new ProcessStartInfo();
...
info.Arguments = "argument";
Process.Start(info);
i can only set a String as attribute. (Same to all types of the Start method)
Is there a way to set a String[] as arguments or how does this String getting interpreted?
Because on the other side
static void Main(string[] args)
i am getting a String[].
Thanks in advance.
Technically you can do it like that:
string[] args = new String[] {"argument1", "argument2", "argument3"};
...
info.Arguments = String.Join(" ", args);
the restriction is that args should not have arguments with spaces
Is there a way to set a String[] as argument?
No you can't do this, since the type of ProcessStartInfo.Arguments is string. Hence you can assign to it an array of strings.
You could pass to this string the parameters as follows:
info.Arguments = "argument1 argument2 argument3";
and your .exe will be executed as you were passing an array of strings with elements (argument1,argument2,argument3).
Related
I'm trying to start a process which contains multiple spaces within the arguments. The arguments that are passed are dynamically built. For example:
// These three strings will be built dynamically
string consolePath = "C:\\My Path\\nunit3-console.exe"
string dll = "C:\\My Path\\My.Test.dll"
string where = "--where \"test == My.Test.Example \""
string cmdText = $" \"{consolePath }\" \"{dll}\" {where}";
//cmdText = "\"C:\\My Path\\nunit3-console.exe\" \"C:\\My Path\\My.Test.dll\" --where \"test == My.Test.Example \""
var processInfo = new ProcessStartInfo("cmd.exe", $"/c {cmdText}");
processInfo.CreateNoWindow = false;
Process process = Process.Start(processInfo);
process.WaitForExit();
process.Close();
This does not work as any text beyond the first space will be ignored. I will get a message such as 'C:\My' is not recognized as an internal or external command, operable program or batch file.
I tried adding parentheses around the arguments, as noted here, but it didn't work. What is the correct way to do this?
You probably have to add a further double-quote around anything that may include spaces within one single argument. Usually a space means the end of an argument. So to preserve this, you´d have to put the string into double-quotes.
So consolePath should actually be this:
var consolePath = "\"C:\\My Path....exe\"";
In addition to previous answer, # could be used to avoid \\ like this:
#"""C:\My Path\nunit3-console.exe"""
or:
"\"" + #"C:\My Path\nunit3-console.exe" + "\""
More about # here:
What's the # in front of a string in C#?
After searching two days for working string I finally found it.
Just wrap string like this:
string Arguments = "/c ""path" --argument "";
string Arguments = "/c \""path" --argument \"";
Notice bold quotes from first string.
I have this code to start a command line app:
private void LaunchCommandLineApp(string latestStudents, string latestTopics)
{
// Use ProcessStartInfo class
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "ConsoleApplication2.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments =
try
{
// Start the process with the info we specified.
// Call WaitForExit and then the using statement will close.
using (Process exeProcess = Process.Start(startInfo))
{
exeProcess.WaitForExit();
}
}
catch
{
// Log error.
}
}
What is the correct syntax for passing latestStudents & latestTopics at the line startInfo.Arguments = as arguments? I've tried everything I can think of and some but I still don't get it!
Arguments is a string, which the documentation unhelpfully says is interpreted entirely by the target application. It does say now .NET applications will interpret it, so it really depends on what process you're launching.
The only way to know how to make that arguments string do the right thing for the process you're trying to pass it to is to find out how that process handles its arguments (try running it from the command line if you need to experiment). Mostly you can expect it to expect them to be separated with spaces. It's possible that you can just do something like (assuming C# 6):
$"{latestStudents} {latestTopics}"
But that might not work, depending on what's inside those variables. They may need to be quoted, especially if they contain spaces themselves.
There really is no definitive answer I can give you.
It depends on the program that is interpreting the arguments, but generally if you separate the arguments with spaces then they will be presented to the program as an array of strings.
For example, if you specify the argument string as:
startInfo.Arguments = "one two three \"fo ur\" \"\\\"fi ve\"\\\""
Then if the program is a C# console application, the Main(string[] args) method will receive an args array as follows:
args[0] == "one"
args[1] == "two"
args[2] == "three"
args[3] == "fo ur"
args[4] == "\"fi ve\""
Note that consecutive spaces such as those between "two" and "three" in my example are ignored.
Also note that the quotes around "fo ur" cause that to be passed as a single argument.
Finally, note that if you want to pass quotes as part of a parameter, you have to escape them with a backslash. In C#, of course, you have to escape the backslash and the quotes, so instead of "\"fi ve\"" in my example, I have to write the even-more unwieldy \"\\\"fi ve\"\\\""
ProcessStartInfo arguments are passed as a string, similar to if you were running ConsoleApplication2.exe via a command line.
For example if you had a command window open in Windows and were to run something like ConsoleApplication2.exe /help, that would be passing "/help" in as a command argument.
So for your case (and it depends how ConsoleApplication2.exe is coded), you'll want to do something like:
startInfo.Arguments = latestStudents + " " latestTopics;
...assuming ConsoleApplication2.exe accepts those two parameters in that order.
Examples:
ProcessStartInfo startInfo = new ProcessStartInfo("argsecho.exe");
startInfo.WindowStyle = ProcessWindowStyle.Normal;
// Start with one argument.
// Output of ArgsEcho:
// [0]=/a
startInfo.Arguments = "/a";
Process.Start(startInfo);
// Start with multiple arguments separated by spaces.
// Output of ArgsEcho:
// [0] = /a
// [1] = /b
// [2] = c:\temp
startInfo.Arguments = "/a /b c:\\temp";
Process.Start(startInfo);
// An argument with spaces inside quotes is interpreted as multiple arguments.
// Output of ArgsEcho:
// [0] = /a
// [1] = literal string arg
startInfo.Arguments = "/a \"literal string arg\"";
Process.Start(startInfo);
// An argument inside double quotes is interpreted as if the quote weren't there,
// that is, as separate arguments. Equivalent verbatim string is #"/a /b:""string with quotes"""
// Output of ArgsEcho:
// [0] = /a
// [1] = /b:string
// [2] = in
// [3] = double
// [4] = quotes
startInfo.Arguments = "/a /b:\"\"string in double quotes\"\"";
Process.Start(startInfo);
// Triple-escape quotation marks to include the character in the final argument received
// by the target process. Equivalent verbatim string: #"/a /b:""""""quoted string""""""";
// [0] = /a
// [1] = /b:"quoted string"
startInfo.Arguments = "/a /b:\"\"\"quoted string\"\"\"";
Process.Start(startInfo);
It is amazing what you can find while Googling for something...
This is the link I used as source for this above code samples.
I had look this question about Passing command line arguments in C#.
But in my case I have to pass array of parameters to the calling .exe file.
e.g.
var arr = new string[] {"Item title","New task","22","High Priority"}
Is it possible to use Process.Start() with exe path along with the array
I have the .exe path
const string path = #"C:\Projects\Test\test.exe";
Thanks
One option is to put the array in one string so it is viewed as one argument by the method. In your method, you can then parse that one argument. Something like:
"Item title, New task, 22, High Priority"
You can use your existing array by doing:
var arrAsOneString = string.Join(", ", arr);
Inside your method, do:
var values = argument.Split(',').Select(x => x.Trim());
I added the trim to do away with spaces.
Its not possible to pass array as argument, you can pass a string with Comma Separator:
ProcessStartInfo info = new ProcessStartInfo();
info.Arguments = "Item title,New task,22,High Priority"
Please try this:
var arr = new string[] {"Item title", "New task", "22", "High Priority"};
const string path = #"C:\Projects\Test\test.exe";
const string argsSeparator = " ";
string args = string.Join(argsSeparator, arr);
Process.Start(path, args);
How can I pass multiple arguments to a newly created process in C#?
Also which class (Process or ProcessStartInfo or MyProcess) in should I use in executing a program, with the condition of passing multiple arguments to the newly created/executed process?
As is I have the equivalent (Borland) C++ code for the same task, which is as follows:
spawnv(P_NOWAITO,Registry->ReadString("Downloader").c_str(),arglist);
where arglist is a char pointer array and
Registry->ReadString("Downloader").c_str(), is the program to execute.
In order to pass multiple command line arguments you should separate each with a space and surround it in quotes in case the argument itself contains a space.
string[] args = { "first", "second", "\"third arg\"" };
Process.Start("blah.exe", String.Join(" ", args));
Process.Start( "program.exe", "arg1 arg2 arg3" );
I have a C# command-line application that I need to run in windows and under mono in unix. At some point I want to launch a subprocess given a set of arbitrary paramaters passed in via the command line. For instance:
Usage: mycommandline [-args] -- [arbitrary program]
Unfortunately, System.Diagnostics.ProcessStartInfo only takes a string for args. This is a problem for commands such as:
./my_commandline myarg1 myarg2 -- grep "a b c" foo.txt
In this case argv looks like :
argv = {"my_commandline", "myarg1", "myarg2", "--", "grep", "a b c", "foo.txt"}
Note that the quotes around "a b c" are stripped by the shell so if I simply concatenate the arguments in order to create the arg string for ProcessStartInfo I get:
args = "my_commandline myarg1 myarg2 -- grep a b c foo.txt"
Which is not what I want.
Is there a simple way to either pass an argv to subprocess launch under C# OR to convert an arbitrary argv into a string which is legal for windows and linux shell?
Any help would be greatly appreciated.
MSDN has a description of how the MS Visual C Runtime parses the string returned by GetCommandLine() into an argv array.
You might also be interested in the list2cmdline() function from the Python standard library that is used by Python's subprocess module to emulate the Unix argv behavior in a Win32 environment.
In windowsland, it's simple really...add extra quotation marks in the string you pass to the System.Diagnostics.ProcessStartInfo object.
e.g. "./my_commandline" "myarg1 myarg2 -- grep \"a b c\" foo.txt"
Thanks to all for the suggestions. I ended up using the algorithm from shquote (http://www.daemon-systems.org/man/shquote.3.html).
/**
* Let's assume 'command' contains a collection of strings each of which is an
* argument to our subprocess (it does not include arg0).
*/
string args = "";
string curArg;
foreach (String s in command) {
curArg = s.Replace("'", "'\\''"); // 1.) Replace ' with '\''
curArg = "'"+curArg+"'"; // 2.) Surround with 's
// 3.) Is removal of unnecessary ' pairs. This is non-trivial and unecessary
args += " " + curArg;
}
I've only tested this on linux. For windows you can just concatenate the args.
You will need to run a new subprocess using grep and all arguments that grep will be needing.
void runProcess(string processName, string args)
{
using (Process p = new Process())
{
ProcessStartInfo info = new ProcessStartInfo(processName);
info.Arguments = args;
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
p.StartInfo = info;
p.Start();
string output = p.StandardOutput.ReadToEnd();
// process output
}
}
then make a call to runProcess("grep", "a", "b", "c", "foo.txt");
Edit: Updated args handling.
Just use a Regex to check if a string has spaces of any kind, and replace the original string with a new one with quotes:
using System.Text.RegularExpressions;
// ...
for(int i=0; i<argv.Length; i++) {
if (Regex.IsMatch(i, "(\s|\")+")) {
argv[i] = "\"" + argv[i] + "\"";
argv[i].Replace("\"", "\\\"");
}
}