My application opens a website then runs a VBS file to do some data input. Once it's completed the data input, I want to quit the application.
In my current iteration, the VBS file executes and my C# code keeps going (quitting the web app before the data entry is completed).
Process.Start(appPath + #"external\website.url");
getAllProcesses(false);
ProcessStartInfo startInfo = new ProcessStartInfo(appPath + #"\external\UNLOCK.vbs", employeeID);
Process scriptProc = new Process();
scriptProc.StartInfo.FileName = #"cscript";
scriptProc.StartInfo.WorkingDirectory = appPath + #"external\";
scriptProc.StartInfo.Arguments = "UNLOCK.vbs " + employeeID;
scriptProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; //prevent console window from popping up
scriptProc.StartInfo.RedirectStandardError = true;
scriptProc.StartInfo.RedirectStandardInput = true;
scriptProc.StartInfo.RedirectStandardOutput = true;
scriptProc.StartInfo.ErrorDialog = false;
scriptProc.StartInfo.UseShellExecute = false;
scriptProc.Start();
scriptProc.WaitForExit(); // <-- Optional if you want program running until your script exit
Read(scriptProc.StandardOutput);
Read(scriptProc.StandardError);
while(true)
{
String completed = Console.ReadLine();
scriptProc.StandardInput.WriteLine(completed);
if(completed.CompareTo("Completed") == 0)
{
break;
}
}
if (scriptProc.HasExited)
{
getAllProcesses(true);
Application.Exit();
}
scriptProc.Close();
I want to only execute
getAllProcesses(true);
Application.Exit();
ONLY After I get output from my VBS file that says "Completed".
My VBS file has a line that says
WScript.Echo "Completed"
at the end.
Process scriptProc = new Process();
ProcessStartInfo info = new ProcessStartInfo();
info.WorkingDirectory = appPath + #"external\";
info.FileName = "Cscript.exe";
info.Arguments = "UNLOCK.vbs" + employeeID;
info.RedirectStandardError = true;
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
info.WindowStyle = ProcessWindowStyle.Hidden;
scriptProc.StartInfo = info;
scriptProc.Start();
scriptProc.WaitForExit();
bool exit = false;
while (!scriptProc.StandardOutput.EndOfStream)
{
if (scriptProc.StandardOutput.ReadLine() == "Completed")
{
exit = true;
break;
}
}
if (exit == true)
{
getAllProcesses(true);
Application.Exit();
}
Related
I want to run visual studios command programmatically.I have tried the above code but no help.All I am getting is a command prompt with my project`s directory open.
I have used Execute("VS140COMNTOOLS") as input.
private void Execute(string vsEnvVar) {
var vsInstallPath = Environment.GetEnvironmentVariable(vsEnvVar);
if (Directory.Exists(vsInstallPath)) {
var filePath = vsInstallPath + "vsvars32.bat";
if (File.Exists(filePath)) {
//start vs command process
Process proc = new Process();
var command = Environment.GetEnvironmentVariable("ComSpec");
command = #"" + command + #"";
//var batfile = #"E:\Test\vstest.bat";
var args = string.Format("/S/K \" \"{0}\" \"", filePath);
proc.StartInfo.FileName = command;
proc.StartInfo.Arguments = args;
//proc.StartInfo.RedirectStandardInput = true;
//proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.UseShellExecute = false;
proc.Start();
} else {
Console.WriteLine("File Does not exists " + filePath);
}
}
}
Try this:
private Process Execute(string vsEnvVar)
{
Process process = new Process();
ProcessStartInfo psi = new ProcessStartInfo("cmd.exe");//assume location is in path. Otherwise use ComSpec env variable
psi.CreateNoWindow = true;
psi.UseShellExecute = false;
psi.RedirectStandardError = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo = psi;
// attach output events
process.ErrorDataReceived += new DataReceivedEventHandler(process_ErrorDataReceived);
process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
process.StartInfo = psi;
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.StandardInput.WriteLine(string.Format("call \"%{0}%vsvars32.bat\""), vsEnvVar);
process.StandardInput.Flush();
return process;
}
Now you can execute any commands by writing to process.StandardInput
process.StandardInput.WriteLine(#"msbuild c:\MySolution.sln /t:Clean");
I am trying to run cmd winsat -drive c programmatically
The code below is only returning "Windows System Assessment Tool" the first line of the output but is not letting the winsat run and return the rest of the output
I am looking for the entire output to be returned shown here
The code I am using is this
public string RunAndOutput(object command)
{
var procStartInfo =
new ProcessStartInfo("winsat", "/c " + "-drive c");
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
var proc = new Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
proc.WaitForExit(); // Wait for everything to finish
return result;
}
You will need to wait for the process to exit using WaitForExit(), like this:
public string RunAndOutput(object command)
{
var procStartInfo =
new ProcessStartInfo("cmd", "/c " + command);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
var proc = new Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
proc.WaitForExit(); // Wait for everything to finish
return result;
}
Running a Git diff gets stuck, till killed when running as a System.Diagnostics.Process.
Code:
class Program
{
static void Main(string[] args)
{
ProcessStartInfo pInfo = new ProcessStartInfo();
pInfo.FileName = "git.exe";
pInfo.Arguments = "diff --name-only --exit-code V2.4-Beta-01 HEAD";
pInfo.WorkingDirectory = #"C:\Git";
pInfo.UseShellExecute = false;
pInfo.CreateNoWindow = true;
pInfo.RedirectStandardError = true;
pInfo.RedirectStandardOutput = true;
Process p = new Process();
p.StartInfo = pInfo;
p.Start();
p.WaitForExit(10000);
if (!p.HasExited)
{
p.Kill();
Console.WriteLine("Killed!!!");
}
Console.WriteLine(p.StandardOutput.ReadToEnd());
Console.WriteLine(p.StandardError.ReadToEnd());
Console.ReadLine();
}
}
How to avoid this and make the program exists normally without expiring its timeout?
The problem is that someone has to consume the stdout buffer or it will get filled and the process gets stucked (see explanation here). The diff I was trying retrieved 983 lines, which was causing a buffer overflow.
The following is a solution to my problem:
class Program
{
static void Main(string[] args)
{
ProcessStartInfo pInfo = new ProcessStartInfo();
pInfo.FileName = "git.exe";
pInfo.Arguments = "diff --name-only --exit-code V2.4-Beta-01 HEAD";
pInfo.WorkingDirectory = #"C:\Git";
pInfo.UseShellExecute = false;
pInfo.CreateNoWindow = true;
pInfo.RedirectStandardError = true;
pInfo.RedirectStandardOutput = true;
string output = string.Empty;
Process p = new Process();
p.StartInfo = pInfo;
p.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
{
output += e.Data + Environment.NewLine;
}
});
p.Start();
p.BeginOutputReadLine();
p.WaitForExit();
p.Close();
Console.WriteLine(output);
Console.ReadLine();
}
}
i have a little question. Is it possible to get the logging stream (logging module) from a python script in C# using Process and ProcessStartInfo ?
As example:
ProcessStartInfo start = new ProcessStartInfo();
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
start.FileName = "runtime\\bin\\python\\python_mcp";
start.Arguments = "runtime\\decompile.py %*";
start.CreateNoWindow = true;
start.UseShellExecute = false;
bBuild = true;
sStatus = "Decompiling...";
Process proc = new Process();
proc.StartInfo = start;
this.Invoke((MethodInvoker)delegate { rtOut.Clear(); });
OutputMsg("========== Decompiling Binaries ==========");
this.Invoke((MethodInvoker)delegate { proc.Start(); });
while (!proc.StandardOutput.EndOfStream)
{
OutputMsg(proc.StandardOutput.ReadLine());
}
this.Invoke((MethodInvoker)delegate { proc.WaitForExit(); });
this.Invoke((MethodInvoker)delegate { proc.Close(); });
OutputMsg("========== Finished decompiling ==========");
bBuild = false;
sStatus = sIdleMessage;
but proc.StandardOutput.ReadLine() does not get any output.
The standart print() output from python is caught but not the logging one
I hope someone can help me.
I'm working on a custom IDE in C# for a scripting language, and I have a problem.
I'm trying to start the compiler process (pawncc.exe) and pass arguments to it. I've done that, and now I have a problem. When I want to display the output from the compiler application, it only displays some parts of it. It should output this (got this from the command prompt):
Pawn compiler 3.2.3664 Copyright (c) 1997-2006, ITB CompuPhase
newGM.pwn(0) : fatal error 100: cannot read from file: "includes/main_include.inc"
Compilation aborted.
1 Error.
But it doesn't. It outputs this (in the application, using the same command/arguments):
Pawn compiler 3.2.3664 Copyright (c) 1997-2006, ITB CompuPhase
1 Error.
I just don't get it! It's a really weird thing. It might be something simple but I've been looking at it, and researching for hours now! Here's my code:
public Form3(string path)
{
InitializeComponent();
this._path = path;
Process myProcess = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo("pawncc.exe");
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.Arguments = path + " -r -d2";
myProcess.StartInfo = startInfo;
myProcess.Start();
while (true)
{
string myString;
byte[] buffer = new byte[512];
var ar = myProcess.StandardOutput.BaseStream.BeginRead(buffer, 0, 512, null, null);
ar.AsyncWaitHandle.WaitOne();
var bytesRead = myProcess.StandardOutput.BaseStream.EndRead(ar);
if (bytesRead > 0)
{
myString = Encoding.ASCII.GetString(buffer, 0, bytesRead);
}
else
{
myProcess.WaitForExit();
break;
}
richTextBox1.Text = myString;
}
}
!!EDIT:
It does the same thing with this code:
public Form3(string path)
{
InitializeComponent();
this._path = path;
Process myProcess = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo("pawncc.exe");
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.Arguments = path + " -r -d2";
myProcess.StartInfo = startInfo;
myProcess.Start();
using (StreamReader reader = myProcess.StandardOutput)
{
string result = reader.ReadToEnd();
richTextBox1.Text = result;
}
}
You need to redirect the standard error stream as well:
startInfo.RedirectStandardError = true;
Edit: I just reviewed the code and discovered that you are only readonly the StandardOutput stream.
I generally monitor the process for both the standard and error output streams using the DataReceived events on the process and adding the results into a stringbuilder, then storing the StringBuilder content in the UI element:
private static System.Text.StringBuilder m_sbText;
public Form3(string path)
{
InitializeComponent();
this._path = path;
Process myProcess = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo("pawncc.exe");
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.Arguments = path + " -r -d2";
myProcess.StartInfo = startInfo;
m_sbText = new System.Text.StringBuilder(1000);
myProcess.OutputDataReceived += ProcessDataHandler;
myProcess.ErrorDataReceived += ProcessDataHandler;
myProcess.Start();
myProcess.BeginOutputReadLine();
myProcess.BeginErrorReadLine();
while (!myProcess.HasExited)
{
System.Threading.Thread.Sleep(500);
System.Windows.Forms.Application.DoEvents();
}
RichTextBox1.Text = m_sbText.ToString();
}
private static void ProcessDataHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
// Collect the net view command output.
if (!String.IsNullOrEmpty(outLine.Data))
{
// Add the text to the collected output.
m_sbText.AppendLine(outLine.Data);
}
}
There are obviously variations on this, but this should get you started.
I dont have the pawnCC application so I cant try but it appears they restrict the verbosity of debugging information to external applications - apart from the command prompt.
Can you try spawning the pawncc.exe via cmd:
"cmd.exe \c CommandParameterToLaunchPawnCCwithArguments"
I've noticed some sporadic issues when dealing with the raw output/error streams from spawned processes in the past, hence why I usually deal with captured output via eventing:
Process myProcess = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo("pawncc.exe");
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.Arguments = path + " -r -d2";
myProcess.EnableRaisingEvents = true;
myProcess.OutputDataReceived += OnOutputDataReceived;
myProcess.ErrorDataReceived += OnErrorDataReceived;
myProcess.StartInfo = startInfo;
myProcess.Start();
myProcess.BeginOutputReadLine();
myProcess.BeginErrorReadLine();