Passing arguments to running process in C# - c#

I've some troubles with running processes and passing args to them.
I know how to run process with some args
ProcessStartInfo psi = new ProcessStartInfo("cmd.exe", "/c something");
Process p = Process.Start(psi)
The problem is that after script is executed process is terminated. That's why there is "/c"
But I'm running multiple scripts and I would like to run them in one process ("cmd.exe") not to start new process every time.
Is there some solutions for it ?
I hope somebody understand what I'm talking about ;)

I recommend you utilize a batch file to script the execution of your executables and call your batch file instead. Or, you can do this -
Process p = new Process();
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "cmd.exe";
info.RedirectStandardInput = true;
info.UseShellExecute = false;
p.StartInfo = info;
p.Start();
using (StreamWriter sw = new StreamWriter(p.StandardInput))
{
if (sw.BaseStream.CanWrite)
{
sw.WriteLine("mysql -u root -p");
sw.WriteLine("mypassword");
sw.WriteLine("use mydb;");
}
}

It sounds like you ought to investigate redirecting the standard input - be sure to also set psi.UseShellExecute to false. You'll probably also want to redirect standard output, so you can have some way of knowing what your child process is doing.
Read more about redirection here.

Related

Trigger Apache Nutch Crawl Programmatically

I'm trying to create a ASP.NET web api to trigger a crawl event to happen. I can't seem to get cygwin to process any of the commands I give it. The only thing I can really do is get it to open a terminal. Once the terminal is open I'd have to redirect the pwd to another location and then trigger my command I want.
Process p = new Process();
ProcessStartInfo info = new ProcessStartInfo();
info.CreateNoWindow = false;
info.RedirectStandardInput = true;
info.UseShellExecute = false;
info.FileName = "C:\\cygwin64\\bin\\mintty.exe";
p.StartInfo = info;
p.Start();
StreamWriter sw = p.StandardInput;
if (sw.BaseStream.CanWrite)
{
sw.WriteLine(#"cd C:\Users\UName\Desktop\apache-nutch-2.3-mongodb\runtime\local\");
sw.WriteLine("bin/autoCrawl");
}
sw.Close();
p.WaitForExit();
I've tried many approaches, this is the last one I've tried but it just does nothing. Is there a way to launch this crawl from my .NET application? I've looked into the NutchApi about creating a new job with a type of crawl but I'm not sure if that applies here or not.
I ended up figuring out how to use the NutchApi to answer my question.

Passing arguments one by one one in console exe by c# code

I want to run an exe file by my c# code. The exe file is a console application written in c#.
The console application performs some actions which includes writing content in database and writing some files to directory.
The console application (exe file) expects some inputs from user.
Like it first asks , 'Do you want to reset database ?' y for yes and n for no.
again if user makes a choice then application again asks , 'do you want to reset files ?'
y for yes and n for no.
If user makes some choice the console application starts to get executed.
Now I want to run this exe console application by my c# code. I am trying like this
string strExePath = "exe path";
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = strExePath;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
using (Process exeProcess = Process.Start(startInfo))
{
exeProcess.WaitForExit();
}
I want to know how can I provide user inputs to the console application by my c# code?
Please help me out in this. Thanks in advance.
You can redirect input and output streams from your exe file.
See redirectstandardoutput
and redirectstandardinput for examples.
For reading:
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
For writing:
...
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.Start();
StreamWriter myStreamWriter = myProcess.StandardInput;
myStreamWriter.WriteLine("y");
...
myStreamWriter.Close();
ProcessStartInfo has a constructor that you can pass arguments to:
public ProcessStartInfo(string fileName, string arguments);
Alternatively, you can set it on it's property:
ProcessStartInfo p = new ProcessStartInfo();
p.Arguments = "some argument";
Here is a sample of how to pass arguments to the *.exe file:
Process p = new Process();
// Redirect the error stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = #"\filepath.exe";
p.StartInfo.Arguments = "{insert arguments here}";
p.Start();
error += (p.StandardError.ReadToEnd());
p.WaitForExit();

Executing command-prompt command in C#

:)
I have a software which can be executed via command line, and now I want it to be executed directly from my C# app. Sadly, there is no error but I still can't do it. :(
The path of .exe file of the software is C:\program files\mysoftware.exe
The command I would like to input is
cd c:\program files\mysoftwareFolder
enter
mysoftware.exe d:\myfolder\file1.xxx d:\myfolder\file2.xxx -mycommand
enter
exit
The commands above work so well in the actual command prompt, but they just don't work from my C# code.
Here is the code:
Process cmdprocess = new Process();
System.Diagnostics.ProcessStartInfo startinfo = new System.Diagnostics.ProcessStartInfo();
startinfo.FileName = "cmd";
startinfo.WindowStyle = ProcessWindowStyle.Hidden;
startinfo.CreateNoWindow = true;
startinfo.RedirectStandardInput = true;
startinfo.RedirectStandardOutput = true;
startinfo.UseShellExecute = false;
cmdprocess.StartInfo = startinfo;
cmdprocess.Start();
System.IO.StreamReader sr = cmdprocess.StandardOutput;
System.IO.StreamWriter sw = cmdprocess.StandardInput;
sw.WriteLine(#"echo on");
sw.WriteLine(#"c:");
sw.WriteLine(#"cd" +#"program files\mysoftwarefolder");
sw.WriteLine(#"mysoftware.exe" +#"d:\myfolder\file1.xxx" +#"d:\myfolder\file2.xxx" +#"-mycommand");
sw.WriteLine(#"exit");
sw.Close();
sr.Close();
I guess the incorrect parts might be "startinfo.FileName = "cmd";" or the way I typed the command in the code, but I have no idea how to correct them. :(
Please tell me what I did wrong. I appreciate every answer from you! :)))
UPDATE Thank you for your helps! I tried writing the command in batch file, but it only works in debugging mode. (I forgot to tell you guys that I am developing a web service.) When I run my external project which will use this C# service, it won't work. I don't know whether I should add something to my code or not.
help meeeeee pleaseeeee (T___T)
Write these commands in a batch file and execute the batch file.
In batch file:
cd c:\program files\mysoftwareFolder
mysoftware.exe
d:\myfolder\file1.xxx
d:\myfolder\file2.xxx -mycommand
exit
Code:
Process cmdprocess = new Process();
ProcessStartInfo startinfo = new ProcessStartInfo();
startinfo.FileName = "path to batchfile.bat";
startinfo.WindowStyle = ProcessWindowStyle.Hidden;
startinfo.CreateNoWindow = true;
startinfo.RedirectStandardInput = true;
startinfo.RedirectStandardOutput = true;
startinfo.UseShellExecute = false;
cmdprocess.StartInfo = startinfo;
cmdprocess.Start();
Instead of:
startinfo.FileName = "cmd";
Directly use
startinfo.FileName = #"c:\program files\mysoftwarefolder\mysoftware.exe";
Then pass the arguments to the start info as
startinfo.Arguments = #"d:\myfolder\file1.xxx " +#"d:\myfolder\file2.xxx " +#"-mycommand";
So the whole code looks like:
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = #"c:\program files\mysoftwarefolder\mysoftware.exe";
p.StartInfo.Arguments = #"d:\myfolder\file1.xxx " +#"d:\myfolder\file2.xxx " +#"-mycommand";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
If you need to see output from your program you can simply use the output string.
2 things: I think you have spacing problems and you're not reading the result of these commands. cmd is probably telling you ..."is not recognized as an internal or external command"
If you look at what you're throwing at cmd, it will be:
echo on
c:
cdprogram files\mysoftware folder
mysoftware.exed:\myfolder\file1.xxx
That won't work when you try it in cmd. CMD is almost certainly kicking back error messages at you, but you're never reading from sr so you'll never know it.
I'd add in some spaces and include all the paths in quotes internally like so:
sw.WriteLine(#"echo on");
sw.WriteLine(#"c:");
sw.WriteLine("cd \"program files\\mysoftwarefolder\"");
sw.WriteLine("mysoftware.exe \"d:\\myfolder\\file1.xxx\" d:\\myfolder\\file2.xxx\" -mycommand");
sw.WriteLine(#"exit");

How to launch an external process in C#, using a cmd window

I am having trouble executing an external console application using Process.Start
Process p = new Process();
p.StartInfo.WorkingDirectory = "dump";
p.StartInfo.FileName = "test.exe";
p.StartInfo.Arguments = s;
p.Start();
When the argument that p generates executes, the external application crashes, although if I copy the exact same argument in a command line window it runs fine.
So my question instead how would I create a new instance of a command window and then add the command test.exe + s to run?
So effectively I am launching cmd and then adding my arguments on to it
If you want to run test.exe prm1 prm2 via cmd, use cmd.exe /c test.exe prm1 prm2. Though I don't really understand what this has to do with the crashes. Sounds like your problem is with test.exe - find out what's causing it to crash, and that will help you fix your C# code so that you don't need the cmd.
One of the places I would examine is the working directory. When you set it to "dump", are you sure the current directory is what you expect? Try using a full path first. It's possible that test.exe happens to be in the system path so it gets executed, but its working directory is not what it expects, and this causes it to crash.
try this:
ProcessStartInfo processToRunInfo = new ProcessStartInfo();
processToRunInfo.Arguments = "Arguments");
processToRunInfo.CreateNoWindow = true;
processToRunInfo.WorkingDirectory = "C:\\yourDir\\";
processToRunInfo.FileName = "test.exe";
//processToRunInfo.CreateNoWindow = true;
//processToRunInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process process = new Process();
process.StartInfo = processToRunInfo;
process.Start();
Process p = new Process();
p.StartInfo.WorkingDirectory = "/full/path/to/dump";
p.StartInfo.FileName = "/full/path/to/test.exe";
p.StartInfo.Arguments = s; // will call 'text.exe s'
p.Start();
Take a look at MSDN.
You need to Create an instance of the StartInfo class and user Start() such as
ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe");
startInfo.WindowStyle = ProcessWindowStyle.Minimized;
Process.Start(startInfo);
startInfo.Arguments = "www.example.com";
Process.Start(startInfo);
Try it!
Rewriting your code would look something like this:
ProcessStartInfo startInfo = new ProcessStartInfo("test.exe");
startInfo.WindowStyle = ProcessWindowStyle.Minimized;
startInfo.WorkingDirectory = "dump";
startInfo.Arguments = "s";
Process.Start(startInfo);

C#.Net: Why is my Process.Start() hanging?

I'm trying to run a batch file, as another user, from my web app. For some reason, the batch file hangs! I can see "cmd.exe" running in the task manager, but it just sits there forever, unable to be killed, and the batch file is not running. Here's my code:
SecureString password = new SecureString();
foreach (char c in "mypassword".ToCharArray())
password.AppendChar(c);
ProcessStartInfo psi = new ProcessStartInfo();
psi.WorkingDirectory = #"c:\build";
psi.FileName = Environment.SystemDirectory + #"\cmd.exe";
psi.Arguments = "/q /c build.cmd";
psi.UseShellExecute = false;
psi.UserName = "builder";
psi.Password = password;
Process.Start(psi);
If you didn't guess, this batch file builds my application (a different application than the one that is executing this command).
The Process.Start(psi); line returns immediately, as it should, but the batch file just seems to hang, without executing. Any ideas?
EDIT: See my answer below for the contents of the batch file.
The output.txt never gets created.
I added these lines:
psi.RedirectStandardOutput = true;
Process p = Process.Start(psi);
String outp = p.StandardOutput.ReadLine();
and stepped through them in debug mode. The code hangs on the ReadLine(). I'm stumped!
I believe I've found the answer. It seems that Microsoft, in all their infinite wisdom, has blocked batch files from being executed by IIS in Windows Server 2003. Brenden Tompkins has a work-around here:
http://codebetter.com/blogs/brendan.tompkins/archive/2004/05/13/13484.aspx
That won't work for me, because my batch file uses IF and GOTO, but it would definitely work for simple batch files.
Why not just do all the work in C# instead of using batch files?
I was bored so i wrote this real quick, it's just an outline of how I would do it since I don't know what the command line switches do or the file paths.
using System;
using System.IO;
using System.Text;
using System.Security;
using System.Diagnostics;
namespace asdf
{
class StackoverflowQuestion
{
private const string MSBUILD = #"path\to\msbuild.exe";
private const string BMAIL = #"path\to\bmail.exe";
private const string WORKING_DIR = #"path\to\working_directory";
private string stdout;
private Process p;
public void DoWork()
{
// build project
StartProcess(MSBUILD, "myproject.csproj /t:Build", true);
}
public void StartProcess(string file, string args, bool redirectStdout)
{
SecureString password = new SecureString();
foreach (char c in "mypassword".ToCharArray())
password.AppendChar(c);
ProcessStartInfo psi = new ProcessStartInfo();
p = new Process();
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.WorkingDirectory = WORKING_DIR;
psi.FileName = file;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = redirectStdout;
psi.UserName = "builder";
psi.Password = password;
p.StartInfo = psi;
p.EnableRaisingEvents = true;
p.Exited += new EventHandler(p_Exited);
p.Start();
if (redirectStdout)
{
stdout = p.StandardOutput.ReadToEnd();
}
}
void p_Exited(object sender, EventArgs e)
{
if (p.ExitCode != 0)
{
// failed
StringBuilder args = new StringBuilder();
args.Append("-s k2smtpout.secureserver.net ");
args.Append("-f build#example.com ");
args.Append("-t josh#example.com ");
args.Append("-a \"Build failed.\" ");
args.AppendFormat("-m {0} -h", stdout);
// send email
StartProcess(BMAIL, args.ToString(), false);
}
}
}
}
Without seeing the build.cmd it's hard to tell what is going on, however, you should build the path using Path.Combine(arg1, arg2); It's the correct way to build a path.
Path.Combine( Environment.SystemDirectory, "cmd.exe" );
I don't remember now but don't you have to set UseShellExecute = true ?
Another possibility to "debug" it is to use standardoutput and then read from it:
psi.RedirectStandardOutput = True;
Process proc = Process.Start(psi);
String whatever = proc.StandardOutput.ReadLine();
In order to "see" what's going on, I'd suggest you transform the process into something more interactive (turn off Echo off) and put some "prints" to see if anything is actually happening. What is in the output.txt file after you run this?
Does the bmail actually executes?
Put some prints after/before to see what's going on.
Also add "#" to the arguments, just in case:
psi.Arguments = #"/q /c build.cmd";
It has to be something very simple :)
My guess would be that the build.cmd is waiting for some sort of user-interaction/reply. If you log the output of the command with the "> logfile.txt" operator at the end, it might help you find the problem.
Here's the contents of build.cmd:
#echo off
set path=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;%path%
msbuild myproject.csproj /t:Build > output.txt
IF NOT ERRORLEVEL 1 goto :end
:error
bmail -s k2smtpout.secureserver.net -f build#example.com -t josh#example.com -a "Build failed." -m output.txt -h
:end
del output.txt
As you can see, I'm careful not to output anything. It all goes to a file that gets emailed to me if the build happens to fail. I've actually been running this file as a scheduled task nightly for quite a while now. I'm trying to build a web app that allows me to run it on demand.
Thanks for everyone's help so far! The Path.Combine tip was particularly useful.
I think cmd.exe hangs if the parameters are incorrect.
If the batch executes correctly then I would just shell execute it like this instead.
ProcessStartInfo psi = new ProcessStartInfo();
Process p = new Process();
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.WorkingDirectory = #"c:\build";
psi.FileName = #"C:\build\build.cmd";
psi.UseShellExecute = true;
psi.UserName = "builder";
psi.Password = password;
p.StartInfo = psi;
p.Start();
Also it could be that cmd.exe just can't find build.cmd so why not give the full path to the file?
What are the endlines of you batch? If the code hangs on ReadLine, then the problem might be that it's unable to read the batch fileā€¦

Categories

Resources