I'm stuck trying to send commands to a cmd prompt that is waiting for my input.
The command in question is JavaLoader, which if I try to use on a BlackBerry device with a password it prompts me for a password. I would like to enter a password but using C# code.
Assuming that I've successfully created the cmd.exe using a Process like so:
process = new Process();
// Invokes the cmd process specifying the command to be executed.
string cmdProcess = string.Format(System.Globalization.CultureInfo.InvariantCulture, #"{0}\cmd.exe", new object[] { Environment.SystemDirectory });
// Pass executing file to cmd (Windows command interpreter) as a arguments
//Removed /C tells cmd that we want it to execute the command that follows, and then exit.
string cmdArguments = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", new object[] { command });
// Pass any command line parameters for execution
if (arguments != null && arguments.Length > 0)
{
cmdArguments += string.Format(System.Globalization.CultureInfo.InvariantCulture, " {0}", new object[] { arguments, System.Globalization.CultureInfo.InvariantCulture });
}
process.StartInfo.FileName = cmdProcess;
process.StartInfo.Arguments = cmdArguments;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false; // Must be false for redirection
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
bool s = process.Start();
How do I go about responding the cmd's prompt for a passwords?
I've tried getting the Input stream and using .WriteLine("randompassword") like so:
while (process.Responding)
{
sw.WriteLine(response);
}
Another thing I've noticed is the prompt for a password is not being picked up as Output or Error and the application will in fact hang here because it's waiting for my input.
Related
I tried to get the output of passed argument in the cmd.exe via c# code. But when the code string outw = cmd.StandardOutput.ReadToEnd().ToString(); executing takes more and more time. Here my command prompt arguments work perfectly.
Here is my code
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();
cmd.StandardInput.WriteLine("git init && git remote add gitlab https://gitlab.company.com/test2.git && git push gitlab --delete branchname");
cmd.StandardInput.WriteLine("git remote remove gitlab");
string outw = cmd.StandardOutput.ReadToEnd().ToString();//Here my code strucks
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
cmd.WaitForExit();
Where I made the mistake? I waited for more than 30 min but I did not get the output in the string outw. How could I get the output test as a string in string outw?
In C# WPF: I want to execute a CMD command, how exactly can I execute a cmd command programmatically?
Here's a simple example :
Process.Start("cmd","/C copy c:\\file.txt lpt1");
As mentioned by the other answers you can use:
Process.Start("notepad somefile.txt");
However, there is another way.
You can instance a Process object and call the Start instance method:
Process process = new Process();
process.StartInfo.FileName = "notepad.exe";
process.StartInfo.WorkingDirectory = "c:\temp";
process.StartInfo.Arguments = "somefile.txt";
process.Start();
Doing it this way allows you to configure more options before starting the process. The Process object also allows you to retrieve information about the process whilst it is executing and it will give you a notification (via the Exited event) when the process has finished.
Addition: Don't forget to set 'process.EnableRaisingEvents' to 'true' if you want to hook the 'Exited' event.
if you want to start application with cmd use this code:
string YourApplicationPath = "C:\\Program Files\\App\\MyApp.exe"
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.WindowStyle = ProcessWindowStyle.Hidden;
processInfo.FileName = "cmd.exe";
processInfo.WorkingDirectory = Path.GetDirectoryName(YourApplicationPath);
processInfo.Arguments = "/c START " + Path.GetFileName(YourApplicationPath);
Process.Start(processInfo);
Using Process.Start:
using System.Diagnostics;
class Program
{
static void Main()
{
Process.Start("example.txt");
}
}
How about you creat a batch file with the command you want, and call it with Process.Start
dir.bat content:
dir
then call:
Process.Start("dir.bat");
Will call the bat file and execute the dir
You can use this to work cmd in C#:
ProcessStartInfo proStart = new ProcessStartInfo();
Process pro = new Process();
proStart.FileName = "cmd.exe";
proStart.WorkingDirectory = #"D:\...";
string arg = "/c your_argument";
proStart.Arguments = arg;
proStart.WindowStyle = ProcessWindowStyle.Hidden;
pro.StartInfo = pro;
pro.Start();
Don't forget to write /c before your argument !!
Argh :D not the fastest
Process.Start("notepad C:\test.txt");
Are you asking how to bring up a command windows? If so, you can use the Process object ...
Process.Start("cmd");
You can do like below:
var command = "Put your command here";
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.WorkingDirectory = #"C:\Program Files\IIS\Microsoft Web Deploy V3";
procStartInfo.CreateNoWindow = true; //whether you want to display the command window
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
label1.Text = result.ToString();
In addition to the answers above, you could use a small extension method:
public static class Extensions
{
public static void Run(this string fileName,
string workingDir=null, params string[] arguments)
{
using (var p = new Process())
{
var args = p.StartInfo;
args.FileName = fileName;
if (workingDir!=null) args.WorkingDirectory = workingDir;
if (arguments != null && arguments.Any())
args.Arguments = string.Join(" ", arguments).Trim();
else if (fileName.ToLowerInvariant() == "explorer")
args.Arguments = args.WorkingDirectory;
p.Start();
}
}
}
and use it like so:
// open explorer window with given path
"Explorer".Run(path);
// open a shell (remanins open)
"cmd".Run(path, "/K");
I have a console application that executes some commands and outputs some logs.
I need the output that display the command and its result, like this one:
>Loading the database...
>mysql -uUser -pPassword myDbName < mydumpFile
ERROR 1045 (28000): Access denied for user 'User'#'localhost' (using password: Y
ES)
>End loading the databse...
I did the folowing:
void ImportData()
{
Program.Log("INFO", "Start importing data... <<<");
Process myProcess = new Process();
string mySqlArgs = string.Format(" -u{0} -p{1} {2} < \"{3}\"",
bddUser, bddPassword, databaseName, dumpPath);
ProcessStartInfo myProcessStartInfo =
new ProcessStartInfo("mysql", mySqlArgs);
myProcessStartInfo.UseShellExecute = false;
myProcessStartInfo.RedirectStandardOutput = true;
myProcess.StartInfo = myProcessStartInfo;
myProcess.Start();
StreamReader reader = myProcess.StandardOutput;
string theOutput = reader.ReadToEnd();
if (theOutput.Length > 0)
Program.Log("SQL", theOutput);
Program.Log("INFO", "END importing data >>>");
}
but this code
1) does not display the command itself (just the result)
2) the request perhaps should be bad formatted, because the result is like a format error in the mysql command
UPDATE: the new code is a litte bit better
Program.Log("INFO", "Start importing Materials... <<<".Fill(code));
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();
/* execute "mysql -uUser -pPassword base < dump" */
string mySqlCommand = "mysql -u{0} -p{1} {2} < \"{3}\"";
cmd.StandardInput.WriteLine(mySqlCommand, bddUser, bddPassword, databaseName, dumpPath);
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
StreamReader reader = cmd.StandardOutput;
string theOutput = reader.ReadToEnd();
if (theOutput.Length > 0)
Program.Log("SQL", Environment.NewLine + theOutput);
Program.Log("INFO", "END importing Materials >>>".Fill(code));
, but anyway, it displays additional information from the cmd.exe first execution (before mysql command) and also the command line after the mysql command result...
Execute the script as
mysql -vvv -uUser ...
this Option will Display the queries during execution of the script.
As for your other Problem: Why do you call a cmd.exe? Just call mysql.exe directly from your program and skip the shell...
I have a button I click that executes a command. The command may prompt for some standard input and I need to respond to that input, the problem is the way the program runs may be different from day to day so I need to interpret the standard output and redirect standard input accordingly.
I have this simple piece of code that reads the standard output line by line and when it sees a prompt for password, it'll send standard input, however the program just hangs since it never sees the prompt for the password, but when I run the batch file the password prompt is there.
Here is the batch file I am calling to execute this test:
#echo off
echo This is a test of a prompt
echo At the prompt, Enter a response
set /P p1=Enter the Password:
echo you entered "%p1%"
Here is the output of that batch file when run from the command line:
C:\Projects\SPP\MOSSTester\SPPTester\bin\Debug>test4.bat
This is a test of a prompt
At the prompt, Enter a response
Enter the Password: Test1
you entered "Test1"
Here is the C# snippet I am using to call the batch file that is hanging:
var proc = new Process();
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = "/c test4.bat";
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardInput = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
//read the standard output and look for prompt for password
StreamReader sr = proc.StandardOutput;
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
Debug.WriteLine(line);
if (line.Contains("Password"))
{
Debug.WriteLine("Password Prompt Found, Entering Password");
proc.StandardInput.WriteLine("thepassword");
}
}
sr.Close();
proc.WaitForExit();
Here is the debug standard output I see, notice that I never see the prompt for the password, why is this? it just hangs?
This is a test of a prompt
At the prompt, Enter a response
Is there a way I can watch the standard output for prompting and react to it accordingly?
Your main problem is that you are working through the stream reader using sr.ReadLine() this is an issue because the prompt for a password halts until the user enters a new line (hits enter after typing the password).
So you need to read the stream 1 character at a time. This example should help you get started.
while (!sr.EndOfStream)
{
var inputChar = (char)sr.Read();
input.Append(inputChar);
if (StringBuilderEndsWith(input, Environment.NewLine))
{
var line = input.ToString();
input = new StringBuilder();
Debug.WriteLine(line);
}
else if (StringBuilderEndsWith(input, "Password:"))
{
Debug.WriteLine("Password Prompt Found, Entering Password");
proc.StandardInput.WriteLine("thepassword");
var line = input.ToString();
input = new StringBuilder();
Debug.WriteLine(line);
}
}
private static bool StringBuilderEndsWith(StringBuilder haystack, string needle)
{
var needleLength = needle.Length - 1;
var haystackLength = haystack.Length - 1;
for (int i = 0; i < needleLength; i++)
{
if (haystack[haystackLength - i] != needle[needleLength - i])
{
return false;
}
}
return true;
}
With the process class you can run the batch file directly. The standard I/O might not be getting through since it has to go through cmd first
proc.StartInfo.FileName = "test4.bat";
proc.StartInfo.Arguments = "";
All I am trying to do is send a command that opens a model with the program.exe
Supposed to be super simple!
Ex:
"C:\Program Files (x86)\River Logic\Enterprise Optimizer 7.4 Developer\EO74.exe" "C:\PauloXLS\Constraint Sets_1.cor"
The line above works well if pasted on the command prompt window.
However, when trying to pass the same exact string on my code it gets stuck on C:\Program
string EXE = "\"" + #tbx_base_exe.Text.Trim() + "\"";
string Model = "\"" + #mdl_path.Trim()+ "\"";
string ExeModel = EXE + " " + Model;
MessageBox.Show(ExeModel);
ExecuteCommand(ExeModel);
ExeModel is showing te following line on Visual Studio:
"\"C:\\Program Files (x86)\\River Logic\\Enterprise Optimizer 7.4 Developer\\EO74.exe\" \"C:\\PauloXLS\\Constraint Sets_1.cor\""
To me looks like it is the string I need to send in to the following method:
public int ExecuteCommand(string Command)
{
int ExitCode;
ProcessStartInfo ProcessInfo;
Process Process;
ProcessInfo = new ProcessStartInfo("cmd.exe", "/K " + Command);
ProcessInfo.CreateNoWindow = true;
ProcessInfo.UseShellExecute = true;
Process = Process.Start(ProcessInfo);
Process.WaitForExit();
ExitCode = Process.ExitCode;
Process.Close();
return ExitCode;
}
Things I've tried:
Pass only one command at a time (works as expected), but not an option since the model file will open with another version of the software.
Tried to Trim
Tried with # with \"
Can anyone see any obvious mistake? Thanks.
It's pretty straightforward. You just create a command line object then write to it, then to execute it you read back from it using SR.ReadToEnd():
private string GETCMD()
{
string tempGETCMD = null;
Process CMDprocess = new Process();
System.Diagnostics.ProcessStartInfo StartInfo = new System.Diagnostics.ProcessStartInfo();
StartInfo.FileName = "cmd"; //starts cmd window
StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
StartInfo.CreateNoWindow = true;
StartInfo.RedirectStandardInput = true;
StartInfo.RedirectStandardOutput = true;
StartInfo.UseShellExecute = false; //required to redirect
CMDprocess.StartInfo = StartInfo;
CMDprocess.Start();
System.IO.StreamReader SR = CMDprocess.StandardOutput;
System.IO.StreamWriter SW = CMDprocess.StandardInput;
SW.WriteLine("#echo on");
SW.WriteLine("cd\\"); //the command you wish to run.....
SW.WriteLine("cd C:\\Program Files");
//insert your other commands here
SW.WriteLine("exit"); //exits command prompt window
tempGETCMD = SR.ReadToEnd(); //returns results of the command window
SW.Close();
SR.Close();
return tempGETCMD;
}
Why are you opening a command prompt (cmd.exe)? Just pass the name of the executable.