Running multiple commands from C# application - c#

I want to run several commands via C# application like
Previously I had a batch file and I ran it using C# but now few of the commands can take inputs. But how to do that ?
I tried
Process cmdprocess = new Process();
ProcessStartInfo startinfo = new ProcessStartInfo();
Environment.SetEnvironmentVariable("filename", FileName);
startinfo.FileName = #"C:\Users\cnandy\Desktop\St\2nd Sep\New_CN\New folder\Encrypt web.config_RSAWebFarm\Decrypt Connection String.bat";
startinfo.WindowStyle = ProcessWindowStyle.Hidden;
startinfo.CreateNoWindow = true;
startinfo.RedirectStandardInput = true;
startinfo.RedirectStandardOutput = true;
startinfo.UseShellExecute = false;
cmdprocess.StartInfo = startinfo;
cmdprocess.Start();
And in the batch file
cd C:\Windows\Microsoft.NET\Framework64\v4.0.30319
aspnet_regiis -pi "CustomKeys2" "C:\Users\cnandy\Desktop\Encryption_keys\CustomEncryptionKeys.xml"
aspnet_regiis -pa "CustomKeys2" "NT AUTHORITY\NETWORK SERVICE"
aspnet_regiis -pdf "connectionStrings" %filename%
But effectively they did not run get executed at all. How to achieve the same where for the last command I can accept an input instead of hard coding
"C:\Users\cnandy\Desktop\Test\Websites\AccountDeduplicationWeb"
?

Try this:
Process p = new Process()
{
StartInfo = new ProcessStartInfo("cmd.exe")
{
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
}
};
p.Start();
using (StreamWriter sw = p.StandardInput)
{
sw.WriteLine("First command here");
sw.WriteLine("Second command here");
}
p.StandardInput.WriteLine("exit");
Alternatively, try this more direct way (which also implements the last thing you requested):
string strEntry = ""; // Let the user assign to this string, for example like "C:\Users\cnandy\Desktop\Test\Websites\AccountDeduplicationWeb"
Process p = new Process()
{
StartInfo = new ProcessStartInfo("cmd.exe")
{
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
}
};
p.Start();
p.StandardInput.WriteLine("cd C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319");
p.StandardInput.WriteLine("aspnet_regiis -pi \"CustomKeys2\" \"C:\\Users\\cnandy\\Desktop\\Encryption_keys\\CustomEncryptionKeys.xml\"");
p.StandardInput.WriteLine("aspnet_regiis -pa \"CustomKeys2\" \"NT AUTHORITY\\NETWORK SERVICE\"");
p.StandardInput.WriteLine("aspnet_regiis -pdf \"connectionStrings\" " + strEntry);
p.StandardInput.WriteLine("exit"); //or even p.Close();
If using the second way, it is recommended to let the user enter the path in a textbox, then grab the string from the textbox's Text property, where all the necessary extra back-slashes will be automatically appended.
It should be mentioned that no cmd will show up running your batch file, or the commands.

You can still make a batch file as you used to. Only change it needs is accepting variables.
Something like
CallYourBatch.bat "MyFileName"
Then in you batch file, you can accept a parameter
SET fileName=%~1
aspnet_regiis -pdf "connectionStrings" %fileName%
Similarly the same functionality can be used while forming your command text, if you must do it as part of C# code.
Also might i suggest using a CALL command to call your batch files? More information on the same is at http://ss64.com/nt/call.html

Start the batch file using Process object. You can use Environment variables to pass the values between processes. in this case, from C# to bat file you can pass values using environment variable.
c#
Environment.SetEnvironmentVariable("searchString","*.txt")
in bat file you can access the value as like below
dir %searchString%
To start the bat file from c#
System.Diagnostics.Process.Start("path\commands.bat");
Sample code to start notepad from C# with Batch file and Variables
System.Environment.SetEnvironmentVariable("fileName", "test.txt");
System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "/commands.bat");
Console.ReadLine();
Bat file
#echo "staring note pad"
notepad %fileName%

Related

Executing batch file located on remote machine

I'm trying to execute a batch file that is located on a remote machine with the following line of code:
System.Diagnostics.Process.Start(\\10.0.24.103\somePath\batchFile.bat);
And it blocks on this line of code. When I try to run it manually (by writing that address in Windows Explorer), it works, but I have to accept a security warning message first. I'm assuming this is why it's blocking when it's done through code...is there any way to force it to execute through code?
I solved my problem by adding more detail to the ProcessStartInfo object:
var process = new Process();
var startInfo = new ProcessStartInfo
{
CreateNoWindow = true,
FileName = "cmd.exe",
Arguments = "/c \"\"" + batchFile + "\"\"",
WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true
};
process.StartInfo = startInfo;
process.Start();
process.WaitForExit(30000);
I needed to specify to use cmd.exe, as well as surrounding the batchFile path in double quotes in case there are spaces in the path.
Try prefacing it with cmd /c(that's a space after /c).
Is this IP address a Windows machine on your domain etc.

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();

Start command windows and run commands inside

I need to start the command window with some arguments and run more commands inside.
For example, launch a test.cmd and run mkdir.
I can launch the test.cmd with processstartinfo , but i am not sure how to run further commands. Can I pass further arguments to the test.cmd process?
How do I go about this?
Unable to add comments to answer... SO writing here.
Andrea, This is what I was looking for. However the above code doesnt work for me.
I am launching a test.cmd which is new command environment (like razzle build environment) and I need to run further commands.
psi.FileName = #"c:\test.cmd";
psi.Arguments = #"arg0 arg1 arg2";
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
psi.UseShellExecute = false;
Process p = new Process();
p.StartInfo = psi;
p.Start();
p.StandardInput.WriteLine(#"dir>c:\results.txt");
p.StandardInput.WriteLine(#"dir>c:\results2.txt");
You can send further commands to cmd.exe using the process
standard input. You have to redirect it, in this way:
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
var process = new Process {StartInfo = startInfo};
process.Start();
process.StandardInput.WriteLine(#"dir>c:\results.txt");
process.StandardInput.WriteLine(#"dir>c:\results2.txt");
process.StandardInput.WriteLine("exit");
process.WaitForExit();
Remember to write "exit" as your last command, otherwise the cmd process doesn't terminate correctly...
The /c parameter to cmd.
ProcessStartInfo start = new ProcessStartInfo("cmd.exe", "/c pause");
Process.Start(start);
(pause is just an example of what you can run)
But for creating a directory you can do that and most other file operations from c# directly
System.IO.Directory.CreateDirectory(#"c:\foo\bar");
Start a cmd from c# is useful only if you have some big bat-file that you don't want to replicate in c#.
What are you trying to achieve? Do you actually need to open a command window, or do you need to simply make a directory, for example?
mkdir is a windows executable - you can start this program in the same way you start cmd - there's no need to start a command window process first.
You could also create a batch file containing all the commands you want to run, then simply start it using the Process and ProcessStartInfo classes you're already using.
How come this doesn't work?
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = false
};
var process = new Process { StartInfo = startInfo };
process.Start();
process.StandardInput.WriteLine(#" dir");
process.WaitForExit();

How do I use ProcessStartInfo to run a batch file?

But it doesn't work -meaning the java code is not executed.
Although the batch file runs fine when clicked in Windows explorer or when run in command line ..
Since this works fine when the batch file is a single DOS command, I think this is somehow related to the fact that the Java code needs ~20 minutes to run.
I'm using the following code
var si = new ProcessStartInfo();
si.CreateNoWindow = true;
si.FileName = batchFileName;
si.UseShellExecute = false;
Process.Start(si);
What am I doing wrong?
Set UseShellExecute to true, so it loads cmd.exe to run the batch file.
Check this - a batch file wrapper of ProcessStartInfo:
C:\>ProcessStartJS.bat "cmd.exe" -arguments "/c pause" -style Minimized -priority High -newWindow yes -useshellexecute yes
Started: cmd.exe /c pause
PID:6540
As Lucas Jones mentioned in the comments, if you don't want to use ShellExecute, do it like this:
string fullBatPath = #"C:\path with space\file.bat";
var process = new Process()
{
StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"cmd /C \"{fullBatPath}\"",
UseShellExecute = false,
CreateNoWindow = true,
}
};
process.Start();

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