The issue lies with the space between Test & Program. How do I get around this so Process.Start(Info); works as intended. I could change Test Program.exe to TestProgram.exe and this would work perfectly. Ive looked at similar questions but non seem to answer my question. Most mention String Replace or altering the string. I dont want to alter the string but regognise there is a space and process as normal.
Apoligies if this has been asked before but I cant seem to find it so please post the link if this has. Thanks
My code
private string program_name = "Test Program.exe";
ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = "/C choice /C Y /N /D Y /T 0 & start " + program_name;
Info.WindowStyle = ProcessWindowStyle.Hidden;
Info.CreateNoWindow = true;
Info.FileName = "cmd.exe";
Process.Start(Info);
In your specific example - which seems a little odd, if you don't mind me saying - the program you are executing is part of the argument list and needs to be wrapped in double quotes like so:
Info.Arguments = "/C choice /C Y /N /D Y /T 0 & start \"" + program_name + "\"";
Or, just in case program_name is already quoted:
var quoted_name = $"\"{program_name.Trim('"')}\"";
Info.Arguments = "/C choice /C Y /N /D Y /T 0 & start " + quoted_name;
If that's really what you're using rather than a contrived example (which is perfectly fine as an example) then it would be simpler to just run the program directly rather than passing it as a commandline to cmd.exe, in which case you don't need the quotes at all:
ProcessStartInfo Info = new ProcessStartInfo();
Info.WindowStyle = ProcessWindowStyle.Hidden;
Info.CreateNoWindow = true;
Info.FileName = program_name; // or program_name.Trim('"')
Process.Start(Info);
Since you're hiding the console window anyway there doesn't seem much point explicitly invoking cmd.exe and having it wait around for the program to complete.
Try this:
Info.Arguments = "/C choice /C Y /N /D Y /T 0 & start \"" + program_name + "\"";
Related
I have been trying to run a Windows command, utilising Atmel Studios atprogram utility, which is not exactly relevant but helps for context.
The following is my code, and the idea is that the output from the command is pushed into a rich text box. This is completed within the "AddTestJigString(output)" section.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string command = cmd();
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.FileName = "CMD.exe";
startInfo.Arguments = "/c cd " + ((char)34) + Path.GetDirectoryName(Properties.Settings.Default.Preferredatprogram) + ((char)34) + " && atprogram.exe - t avrispmk2 - i isp - d ATtiny26 - v chiperase program -f 30 - 5004_U21_V0.7.hex write - fs--values 61F6";
process.StartInfo = startInfo;
process.Start();
string output = process.StandardOutput.ReadToEnd();
AddTestJigString(output);
process.WaitForExit();
}
Key line being;
startInfo.Arguments = "/c cd " + ((char)34) + Path.GetDirectoryName(Properties.Settings.Default.Preferredatprogram) + ((char)34) + " && atprogram.exe - t avrispmk2 - i isp - d ATtiny26 - v chiperase program -f 30 - 5004_U21_V0.7.hex write - fs--values 61F6";
If i change this to just;
startInfo.Arguments = "/c cd " + ((char)34) + Path.GetDirectoryName(Properties.Settings.Default.Preferredatprogram) + ((char)34) + " && atprogram.exe";
I get the output of the help / list of available commands within my rich text box from atprogram.exe, so i am doing something right. However as soon as any parmeters are added, the output is totally blank.
Thanks for the above responses.
In response, the arguments for this command are defintitly correct, as it is in use in a production environment as a batch script.
The issue is actually down to outputting the command to a rich text box or more basically redirecting the command output.
The following solution I managed to get working:
{
string comhex = Path.GetFullPath(Properties.Settings.Default.PreferredComHex);
return "/c atprogram -t avrispmk2 -i isp -d ATtiny26 -v chiperase program -f " + ((char)34) + comhex + ((char)34) + " write -fs --values 61F6 2>&1";
}
The key part being the "2>&1" that I have added to the end of the command string. This effectively tells the command to redirect both Standard Output (stdout) and Standard Error (stderr). With 2 being stderr and 1 being stdout.
For further reading / reference:
In the shell, what does " 2>&1 " mean?
https://support.microsoft.com/en-gb/help/110930/redirecting-error-messages-from-command-prompt-stderr-stdout
I need to write the serial number (text) from a textBox to cmd command using startInfo.Arguments.
The main point is, all searches I did here pointed to replace the text in the beggining or in the end of the arguments.
But I need to insert the text from textBox to the middle of the argument, like this:
string input1 = textBox1.Text;
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.FileName = "CMD.exe";
startInfo.Arguments = "/c adb -s "textBox1.Text" shell dumpsys battery";
Any help will be appreciated. Thank you.
The content of the textbox has already been stored in the input1 variable.
Now we have multiple options to do this in C#:
startInfo.Arguments = String.Format(#"/c adb -s ""{0}"" shell dumpsys battery", input1);
(in the # string notation, double quotes are preserved in the resulting string by doubling them)
or with concatenation:
startInfo.Arguments = "/c adb -s \"" + input1 + "\" shell dumpsys battery";
(the backslash-escaped double quotes will preserve the double quote in the resulting string)
or, recently, we can use string interpolation:
startInfo.Arguments = $#"/c adb -s ""{input1}"" shell dumpsys battery";
Either way, consider to validate the value before you execute anything you obtained from a user, especially when it is started with administrative privileges.
I've seen similar examples, but can't find something exactly like my problem.
I need to run a command like this from C#:
C:\FOLDER\folder with spaces\OTHER_FOLDER\executable.exe p1=hardCodedv1 p2=v2
I'm setting v2 at runtime, so I need to be able to modify the string in C# before calling Process.Start. Does anyone know how to handle this, since I have spaces between my parameters?
Even when you use the ProcessStartInfo Class, if you have to add spaces for arguments, then the above answers won't solve the problem. There's a simple solution. Just add quotes around arguments. That's all.
string fileName = #"D:\Company Accounts\Auditing Sep-2014 Reports.xlsx";
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "Excel.exe";
startInfo.Arguments = "\"" + fileName + "\"";
System.Diagnostics.Process.Start(startInfo);
Here I've added escaped quotes around filename, and it works.
You can use the ProcessStartInfo class to separate your arguments, FileName, WorkingDirectory and arguments without worry for spaces
string fullPath = #"C:\FOLDER\folder with spaces\OTHER_FOLDER\executable.exe"
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = Path.GetFileName(fullPath);
psi.WorkingDirectory = Path.GetDirectoryName(fullPath);
psi.Arguments = "p1=hardCodedv1 p2=" + MakeParameter();
Process.Start(psi);
where MakeParameter is a function that returns the string to be used for the p2 parameter
Try this
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "\"C:\\FOLDER\\folder with spaces\\OTHER_FOLDER\\executable.exe\"";
startInfo.Arguments = "p1=hardCodedv1 p2=v2";
Process.Start(startInfo);
After looking at the other solutions provided I ran into the issue where all my various arguments were bundled into one argument.
i.e. "-setting0=arg0 --subsetting0=arg1"
So I would propose the following:
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "\"" + Prefs.CaptureLocation.FullName + "\"";
psi.Arguments = String.Format("-setting0={0} --subsetting0={1}", "\"" + arg0 + "\"", "\"" + arg1+ "\"");
Process.Start(psi);
With the quotes around each argument, instead of around the entire set of arguments. And as pointed out by Red_Shadow this can all be done with the single line
Process.Start("\"" + filename + "\"", arguments here)
Very subtle caveat:
If I use ArgumentList, it only works when using it strictly trimmed (without leading or trailing spaces) and each string in it's own array place.
var psi = new ProcessStartInfo("cmd") {
ArgumentList = {
"--somepath",
"/root/subpath",
"--someid",
"12345",
}
};
If I try for example
"--somepath /root/subpath",
it doesn't work and I get errors from the cmd application.
Even
"--somepath ",
breaks the parser of the receiving program.
If the process you want to start is cmd /C
and the argument contains multiple spaces like C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe /N /T C:\users\someuser\AppData\Local\Temp\temp file with spaces.tmp Printer Name with Spaces maybe this answer will help you:
https://stackoverflow.com/a/6378038/20704455
In short: double quote
string arguments ="/C \"\"C:\\Program Files (x86)\\Adobe\\Acrobat Reader DC\\Reader\\AcroRd32.exe\" /N /T \"C:\\users\\someuser\\AppData\\Local\\Temp\\temp file with spaces.tmp\" \"Printer Name with Spaces\"\"";
ProcessStartInfo procStartInfo = new ProcessStartInfo("C:\\Windows\\sysnative\\cmd.exe",arguments);
Previously somebody has asked how to run a command line command in C# from visual studio and the beneath was the answer.
I tried the same intended to call a tool called cccc which can run on command line. But when I run the beneath code I do not get any results and nothing shows wrong.
Stating generally how can we run the same commands from C# as it was in command line and get the same results. Say I call a program (it could be any program that is able to run on command line, for instance, cccc, ccm, and so on) on command line and get some results. How to call the command line and give the arguments so it will call in its turn the cccc or whatever and do the same thing as it was without C#.
string strCmdText;
strCmdText = "/C d: cd D:\\Exercises\\npp52\\PowerEditor\\src && dir /s /b | cccc - --outdir=d:\\myfolder";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
Add 'pause' to the end of your command:
string strCmdText;
strCmdText = "/C d: cd D:\\Exercises\\npp52\\PowerEditor\\src && dir /s /b | cccc - --outdir=d:\\myfolder & pause";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
or redirect console standard output to a stream.
Here need more magic with OutputDataReceived handler
void Main()
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName="cmd.exe";
proc.StartInfo.Arguments = "/c ping 127.0.0.1";
proc.StartInfo.UseShellExecute = false;
proc.OutputDataReceived += new DataReceivedEventHandler(SortOutputHandler);
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
proc.BeginOutputReadLine();
proc.WaitForExit();
proc.Close();
}
private void SortOutputHandler(object sendingProcess,
DataReceivedEventArgs outLine)
{
if (!String.IsNullOrEmpty(outLine.Data))
{
// Do what You need with out
Console.WriteLine(outLine.Data);
}
}
Instead of trying to put everything inside a string you could take advantage of the ProcessStartInfo class to better define your arguments
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "CMD.EXE";
psi.WorkingDirectory = "D:\\Exercises\\npp52\\PowerEditor\\src ";
psi.Arguments = "/C dir /s /b | cccc - --outdir=d:\\myfolder"";
psi.WindowStyle = ProcessWindowStyle.Normal;
Process.Start(psi);
Also with the command window open you could see if there are syntax errors in your command
Another problem is that you are not using RedirectStandardOutput, so output is discarded. Take a look at this answer.
Long story short...
This doesnt work:
Process p = new Process();
p.StartInfo.FileName = #"External\PsExec.exe";
string file = String.Concat(Path.Combine(Environment.CurrentDirectory,"temp"),#"\iisreset",DateTime.Now.ToString("ddMMyyyy-hhmmssss"),".txt");
p.StartInfo.Arguments = String.Format("-s -u {0}\\{1} -p {2} \\\\{3} iisreset > \"{4}\"", Domain,UserName, Password, machineIP, file);
p.StartInfo.CreateNoWindow = true;
p.Start();
p.WaitForExit();
I'm getting a RPC Unavailable message.
But when I access the command line in the program folder, then i run this: (with the correct parameters), exactly like I specified in the filename/arguments...
External\PsExec.exe -s -u [user] -p [password] \\[ip] iisreset > "[path]"
It works!
Do I have to specify anything else in the C# Process ? What could be possibly happening?
Thanks in advance!
EDIT: It works if I put cmd as the FileName and /c PsExec.exe before the arguments. The problem is this way it always show the window.
Instead of using p.startinfo.arguments use p.standardinput.writeline(command)
string PSPath = #"C:\PSTools\PsExec.exe";
fullcommand = PSPath + " -u " + userName + " -p " + password + " \\\\" + remoteMachine + " -h cmd.exe /c " + command + "";
Console.Clear();
//Console.WriteLine(fullcommand);
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.FileName = "cmd.exe";
//process.StartInfo.Arguments = fullcommand;
process.Start();
process.StandardInput.WriteLine(fullcommand);
process.StandardInput.Flush();
process.StandardInput.Close();
Console.WriteLine("*****Command*****");
Console.WriteLine(fullcommand);
Console.WriteLine("*****Output*****");
Console.WriteLine(process.StandardOutput.ReadToEnd());
Console.WriteLine("*****Error*****");
Console.WriteLine(process.StandardError.ReadToEnd());
Console.WriteLine("*****Exit*****");
process.WaitForExit();
Console.WriteLine("Again ?");
You cannot redirect standard output using the arguments the way you are doing. That's not how things actually work.
At the command line, your arguments end when the command interpreter sees the >, and it begins the process of redirecting standard output to the filename.
To accomplish this in C# you need to use the RedirectStandardOutput property of the StartInfo class, then read from the Process.StandardOutput stream and write to a file.
The MSDN documentation for RedirectStandardOutput has a short example you can use to get started.
iisreset [machinename] -
you don't need psexec