I have the following command that I wish to run (which works when I manually run it in cmd):
"C:\Program Files\APP\APP.exe" -CMV "C:\Program Files\APP\Second\IT" -ID 5 6 7 4 2
This is the code that I have written in C#:
string firstPath = #"""C:\Program Files\APP\APP.exe""";
string secondPath = #"""C:\Program Files\APP\Second\IT""";
string command = firstPath + " -CMV " + secondPath + " -ID 5 6 7 4 2");
I also tried the following piece of code:
int exitCode;
ProcessStartInfo processInfo;
Process process;
processInfo = new ProcessStartInfo("cmd.exe", command);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
// *** Redirect the output ***
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
//processInfo.Arguments
process = Process.Start(processInfo);
process.WaitForExit();
// *** Read the streams ***
// Warning: This approach can lead to deadlocks, see Edit #2
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
exitCode = process.ExitCode;
Console.WriteLine("output>>" + (String.IsNullOrEmpty(output) ? "(none)" : output));
Console.WriteLine("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : error));
Console.WriteLine("ExitCode: " + exitCode.ToString(), "ExecuteCommand");
process.Close();
This still doesn't seem to work! Any help is much appreciated.
*********FINAL EDIT*********
This is the string that gets sent in as the command:
""C:\\Program Files\\DEEM\\DEEM.exe" -ENV "C:\\Program Files\\DEEM\\Environments\\IT" -ID 01004698001001 00285209090217 00285209090250 00285209090382 99041250643762"
Which results in the following error:
"'C:\Program' is not recognized as an internal or external
command,\r\noperable program or batch file.\r\n"
All I need to make it work is to take out the first and last quote which are wrapped due to the command being a string. I am not sure how to take the quotes out.
Your first example works if you wait for the process to exit:
static void Main(string[] args)
{
string firstPath = #"""C:\Program Files\APP\APP.exe""";
string secondPath = #"""C:\Program Files\APP\Second\IT""";
string command = firstPath + " -CMV " + secondPath + " -ID 5 6 7 4 2";
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
//startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = firstPath; //"cmd.exe";
startInfo.Arguments = command;
process.StartInfo = startInfo;
process.Start();
// **** don't forget to wait for the process to exit ***
process.WaitForExit();
var code = process.ExitCode;
var time = process.ExitTime;
}
In your second example you did use WaitForExit(), but there is some other stuff broken I did not investigate on.
Related
I have a WPF application that executes a Powershell script and then displays a message in a textbox in the application. The Powershell script is executed like this:
string scriptPath = folderPath + "/EXECUTE.ps1";
string powershellPath = #"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
string outputLog = folderPath + "output.log";
bool is64 = IntPtr.Size == 8;
var ENV = "Get-ItemProperty HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\* "
+ (is64 ? ",HKLM:\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*" : "")
+ " | Select-Object DisplayName";
ProcessStartInfo startInstall = new ProcessStartInfo(powershellPath, ENV);
startInstall.UseShellExecute = false;
startInstall.Arguments = scriptPath;
startInstall.EnvironmentVariables.Add("RedirectStandardOutput", "true");
startInstall.EnvironmentVariables.Add("RedirectStandardError", "true");
startInstall.EnvironmentVariables.Add("UseShellExecute", "false");
startInstall.EnvironmentVariables.Add("CreateNoWindow", "true");
Process Install = Process.Start(startInstall);
Install.Close();
Console.WriteLine("Script executed successfully");
Console.WriteLine("Output available at: " + outputLog);
The last two lines in Console.WriteLine are printed out in a textbox. I was wondering, is there a way that I can show the output of the Powershell terminal window inside of this textbox named txtboxExecutionResult? I am not executing any Powershell command from my application, just starting and executing the EXECUTE.ps1 file from the application. I'd really appreciate any help to point me in some direction.
I had a similar issue once with reading output from another application and I solved it by reading the standard output of the process.
Process process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = false;
process.StartInfo.CreateNoWindow = false;
process.StartInfo.FileName = "example.exe";
process.StartInfo.Arguments = args;
process.Start();
output = await process.StandardOutput.ReadToEndAsync();
I am developing and distributing it with Blazor server-side and I'm trying to run exe,bat files on the deployed server.
When run with the following code, it runs very well in local, but when deployed to the server, it does not run.
The deployed server environment is being distributed with IIS.
Please let me know if you have any other settings for running files on the server.
Or if the code is wrong. I hope for help.
=============== Function Definition ===============
public void ExecuteCommand(string command)
{
int exitCode;
ProcessStartInfo processInfo;
Process process = new Process();
processInfo = new ProcessStartInfo("cmd.exe", "/C " + command);
processInfo.WorkingDirectory = Path.Combine(_environment.WebRootPath, "test");
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.Verb = "runas";
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
process = Process.Start(processInfo);
process.WaitForExit();
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
exitCode = process.ExitCode;
Console.WriteLine("output>>" + (String.IsNullOrEmpty(output) ? "(none)" : output));
Console.WriteLine("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : error));
Console.WriteLine("ExitCode: " + exitCode.ToString(), "ExecuteCommand");
process.Close();
}
=============== Execute Function ===============
ExecuteCommand(string.Format("batchTest.bat {0}", userDirPath));
I am trying to run a batch file using C#
The batch file for the test purposes contains
msg * Test
It works if I run it manually.
Then I use the following code to run this .bat file
filePath = full path to batch file
var startInfo = new ProcessStartInfo
{
Arguments = "/C \"" + filePath + "\"",
FileName = "cmd.exe",
UseShellExecute = true
};
Process p = Process.Start(startInfo);
and it does not work ->
cannot find msg
What I am doing wrong?
P.S. the batch file should not be changed.
Try this way:
batchfile:
set "msg=%SystemRoot%\System32\msg.exe"
if not exist "%msg%" set "msg=%SystemRoot%\Sysnative\msg.exe"
"%msg%" * Hello
code:
string sFile = <full path to batch file>;
Process.Start("cmd.exe", "/c " + sFile);
Probably need some authorization, you may try the following code:
static void ExecuteCommand(string command)
{
int exitCode;
ProcessStartInfo processInfo;
Process process;
processInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
processInfo.CreateNoWindow = true;
processInfo.Domain = "domain"; // Your own domain
processInfo.UserName = "userName"; // Your own user name
System.Security.SecureString s = new System.Security.SecureString();
s.AppendChar('p'); // Your own password
s.AppendChar('a');
s.AppendChar('s');
s.AppendChar('s');
s.AppendChar('w');
s.AppendChar('o');
s.AppendChar('r');
s.AppendChar('d');
processInfo.Password = s;
processInfo.UseShellExecute = false;
// *** Redirect the output ***
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
process = Process.Start(processInfo);
process.WaitForExit();
// *** Read the streams ***
// Warning: This approach can lead to deadlocks, see Edit #2
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
exitCode = process.ExitCode;
Console.WriteLine("output>>" + (String.IsNullOrEmpty(output) ? "(none)" :
output));
Console.WriteLine("error>>" + (String.IsNullOrEmpty(error) ? "(none)" :
error));
Console.WriteLine("ExitCode: " + exitCode.ToString(), "ExecuteCommand");
process.Close();
}
static void Main()
{
ExecuteCommand(#"C:\displayMsg.bat");
}
You may check your domain in Control Panel >> User Account >> Manage User Accounts
Source of reference: source
The problem is the location of the file (msg.exe) in the different OS versions (32bit/64bit)
I suppose it helps How can I execute msg.exe by C# in windows?
Edited:
It works fine -
class Program
{
static void Main(string[] args)
{
int ExitCode;
try
{
var returnedMsgPath = string.Empty;
if (LocateMsgExe(out returnedMsgPath))
{
var startInfo = new ProcessStartInfo()
{
FileName = returnedMsgPath,
Arguments = #"* /v Hello",
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardOutput = true
};
var p = Process.Start(startInfo);
p.WaitForExit();
// *** Read the streams ***
string output = p.StandardOutput.ReadToEnd();
string error = p.StandardError.ReadToEnd();
ExitCode = p.ExitCode;
MessageBox.Show("output >>" + (String.IsNullOrEmpty(output) ? "(none)" : output));
MessageBox.Show("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : error));
MessageBox.Show("ExitCode: " + ExitCode.ToString(), "ExecuteCommand");
p.Close();
}
else
{
MessageBox.Show("Not found");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public static bool LocateMsgExe(out string returnedMsgPath)
{
returnedMsgPath = null;
string[] msgPaths = new string[] { Environment.ExpandEnvironmentVariables(#"%windir%\system32\msg.exe"),
Environment.ExpandEnvironmentVariables(#"%windir%\sysnative\msg.exe") };
foreach (string msgPath in msgPaths)
{
if (File.Exists(msgPath))
{
returnedMsgPath = msgPath;
return true;
}
}
return false;
}
}
I'm trying to run a batch file with arguments and also redirect the output.
When I don't redirect the output and use UseShellExecute = true, the batch file runs with the arguments as expected.
When I use UseShellExecute = false (to do the redirect), then I see that the command-line opens for a split a second and then closes.
I've read the output, using string output = proc.StandardOutput.ReadToEnd();
and I see that it contains the batch file content...
Can someone help me understand why it happens?
Thank you for your help :)
Here's the relevant code:
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.CreateNoWindow = false;
proc.EnableRaisingEvents = false;
// the command
proc.StartInfo.FileName = command;
// the parameters of the command
proc.StartInfo.Arguments = args;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
try
{
// in case there is missing '"'
if (isContainQuote && index < 0)
{
str = "missing '\"' in the command " + commandStr;
}
else
{
proc.Start();
string output = proc.StandardOutput.ReadToEnd();
if (bWaitForExit)
{
proc.WaitForExit(m_SHELL_CMD_TIMEOUT);
str = "Succeed to run the command: " + commandStr + ", Output: " + proc.StandardOutput.ReadToEnd();
}
else
{
str = "Succeed to run the command: " + commandStr;
}
}
}
catch (Exception e)
{
str = e.Message + ". Failed to run the command: " + commandStr;
// return the error from the operation system
}
Seeing your batch file could help. By default batch files echo their commands to standard out.
Try adding an #ECHO OFF command to the beginning of the batch file to be sure that the batch file commands aren't echoed to the standard output.
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.