I have a batch file containing the following commands:
cd C:\myfolder
NuGet Update -self
NuGet pack mypackage.nuspec
myfolder contains mypackage.nuspec and NuGet.exe. I try to run this command with C# using the following function:
private static int ExecuteCommand(string path)
{
ProcessStartInfo ProcessInfo;
Process Process;
ProcessInfo = new ProcessStartInfo(path);
ProcessInfo.CreateNoWindow = true;
ProcessInfo.UseShellExecute = false;
ProcessInfo.WorkingDirectory = new System.IO.FileInfo(path).DirectoryName;
ProcessInfo.EnvironmentVariables["EnableNuGetPackageRestore"] = "true";
// *** Redirect the output ***
ProcessInfo.RedirectStandardError = true;
ProcessInfo.RedirectStandardOutput = true;
Process = Process.Start(ProcessInfo);
Process.WaitForExit();
// *** Read the streams ***
string output = Process.StandardOutput.ReadToEnd();
string error = Process.StandardError.ReadToEnd();
int ExitCode = Process.ExitCode;
Process.Close();
return ExitCode;
}
However, my commands are not executed. What is causing this behavior and what is the solution? Those strings will probably be used in the future, I'll update my question then (just to prevent chriticism :)).
This is the final version of the function:
private static ShellCommandReturn ExecuteCommand(string path)
{
ProcessStartInfo processInfo;
Process process;
processInfo = new ProcessStartInfo(path);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.WorkingDirectory = new System.IO.FileInfo(path).DirectoryName;
processInfo.EnvironmentVariables["EnableNuGetPackageRestore"] = "true";
// *** Redirect the output ***
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
process = Process.Start(processInfo);
process.WaitForExit();
// *** Read the streams ***
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
int exitCode = process.ExitCode;
process.Close();
return new ShellCommandReturn { Error = error, ExitCode = exitCode, Output = output };
}
ShellCommandReturn is a simple custom class with a few data members where error, output and exit code of a shell command are stored.
Thanks.
EDIT: After a certain amount of collaboration :)
The problem is that this is executing in the context of a web application, which doesn't have the same environment variables set.
Apparently setting:
startInfo.EnvironmentVariables["EnableNuGetPackageRestore"] = "true"
(using the naming of my final code below) fixes the problem.
Old answer (still worth reading)
Look at this code:
ProcessInfo = new ProcessStartInfo(path);
ProcessInfo.CreateNoWindow = false;
ProcessInfo.UseShellExecute = true;
ProcessInfo.WorkingDirectory = new System.IO.FileInfo(path).DirectoryName;
Process = Process.Start(path);
You're creating a ProcessStartInfo, but then completely ignoring it. You should be passing it into Process.Start. You should also rename your variables. Conventionally local variables start with lower case in C#. Additionally, it's a good idea to initialize variables at the point of first use, where possible. Oh, and import namespaces so you don't fully qualified names such as System.IO.FileInfo in your code. Finally, object initializers are useful for classes like ProcessStartInfo:
var startInfo = new ProcessStartInfo(path) {
CreateNoWindow = false,
UseShellExecute = true,
WorkingDirectory = new FileInfo(path).DirectoryName;
};
var process = Process.Start(startInfo);
Related
I am working on a C# .net core project.I created a process to run "xdotool windowactivate $windowpid".I should store the windowID which process run on it.The solution could be any property of xdotool which i couldn't find,or Is there any way to take windowId of a process when it is created?
Another Try is that:
I created my pages with this method. I tried to take mainwindowtitle of process;because of single process,i couldn't take the titles.
static List<string> chromeTitles = new List<string>();
public static Process StartChrome(string filePath)
{
string dataDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Chrome-UserData");
filePath += " --user-data-dir=" + dataDirectory;
var Chrome = new Process
{
StartInfo =
{
FileName = "C:/Program/chrome.exe",
Arguments = filePath,
UseShellExecute = false,
CreateNoWindow=true,
WindowStyle = ProcessWindowStyle.Maximized,
}
};
Chrome.Start();
string title = Chrome.MainWindowTitle;
chromeTitles.Add(title);
}
Then I call it :
StartChrome("https://tr.wikipedia.org/wiki/Anasayfa");
Thread.Sleep(2000);
StartChrome("https://tureng.com/");
You can use the Process class for accessing more capabilities.
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "xdotool.exe";
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.Arguments = $"windowactivate $windowpid";
process.StartInfo = startInfo;
process.Start();
To get the PID of the process that got run by the code, you can use Process.ID property:
process.Id;
if you want to read the output, you can add this code:
string output = process.StandardOutput.ReadToEnd();
To get Output, startInfo.RedirectStandardOutput should be True.
I'm trying to make some kind of app, in C# Windows Forms Application (not console one, with tab pages, configuration, and console as a list box).
My problem is, that when I am writing some kind of input (to the text box), nothing happens (I'm new to coding).
My code:
Process process = new Process
{
StartInfo =
{
FileName = textBox2.Text,
//Arguments = textBox3.Text,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
CreateNoWindow = false,
}
};
server = process;
process.Start();
...
/* LATER */
...
serverInput = process.StandardInput;
...
serverInput.Write(textBoxInput.Text);
UPDATE - SOLVED: code:
serverInput.WriteLine(...);
Method 1:
This will be enough to run a batch files present in a directory:
string[] arrBatFiles = Directory.GetFiles(textBox2.Text, "*.bat"); //search at directory path
//loop through all batch files
foreach(string sFile in arrBatFiles)
{
Process.Start(sFile);
}
Method 2:
If you want to use ProcessStartInfo members, use following method:
public void ExecuteCommand(string sBatchFile, string command)
{
int ExitCode;
ProcessStartInfo ProcessInfo;
Process process;
string sBatchFilePath = textBox2.Text; //batch file Path
ProcessInfo = new ProcessStartInfo(sBatchFile, command);
ProcessInfo.CreateNoWindow = false;
ProcessInfo.UseShellExecute = false;
ProcessInfo.WorkingDirectory = Path.GetDirectoryName(sBatchFile);
// *** Redirect the output ***
ProcessInfo.RedirectStandardError = true;
ProcessInfo.RedirectStandardOutput = true;
process = Process.Start(ProcessInfo);
process.WaitForExit();
// *** Read the streams ***
string sInput = process.StardardInput.ReadToEnd();
string sOutput = process.StandardOutput.ReadToEnd();
string sError = process.StandardError.ReadToEnd();
ExitCode = process.ExitCode;
}
UPDATE:
How to call when you have directory of batch files.
string[] arrBatFiles = Directory.GetFiles(textBox2.Text, "*.bat"); //search at directory path
//loop through all batch files
foreach(string sFile in arrBatFiles)
{
ExecuteCommand(sFile, string.Empty); //string.Empty refer optional command args
}
I have run the bat file through dotnet in c# is as below
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "d://s.bat";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
it works fine while running through dotnet ide.
But my problem is when ever i run the above code after publishing through IIS it returns me error as
StandardOut-has-not-been-redirected-or-the-process-hasn-t-started-yet.
can you give me some guide lines to solve this problem?
Do this way, to overcome the error:-
StringBuilder content = new StringBuilder();
while ( ! p.HasExited ) {
content.Append(p.StandardOutput.ReadToEnd());
}
string output = content.ToString();
You have to use the RedirectStandardOutput = true.
Link from MSDN
Quote from link:
ProcessStartInfo.RedirectStandardOutput Property
Gets or sets a value that indicates whether the output of an application is written to the Process.StandardOutput stream.
A snippet from my issue to the same problem, when i was making sure our server was starting.
if (IsProcessRunning(ServerProcessName)) { return; }
var p = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = path,
RedirectStandardOutput = true,
UseShellExecute = false
}
};
p.Start();
var a = "";
while (!a.Contains("ServicesStarted"))
{
a = p.StandardOutput.ReadLine();
}
I want to using C# process to get result from Command Prompt. The command is "java HelloWorld 1" (I have been build it to HelloWorld.class file using "javac HelloWorld.java")
The java code:
public class HelloWorld {
public HelloWorld() {}
public static void main(String[] args) { System.out.println("STARTED");
try {
int param = Integer.parseInt(args[0].toString());
if (param == 1) {
System.out.println("BASE 64!");
} else if (param == 2) {
System.out.println("MD5!");
} else {
System.out.println("INPUT NOT MATCH!");
}
} catch (Exception ee) {
System.out.println("NO INPUT - ERROR");
}
} }
and The C# code:
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "C:\\Program Files\\Java\\jdk1.6.0_25\\bin\\java.exe";
p.StartInfo.Arguments = "HelloWorld 1";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
string strOutput = p.StandardOutput.ReadToEnd();
p.WaitForExit();
But the strOutput is "".
Can you give me the solution?
Thank you!
The most likely thing is that java cannot find your HelloWorld.class file.
In that case, it will write to the standard error something like
Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld
Caused by: java.lang.ClassNotFoundException: HelloWorld
and then a stack trace.
And it will not write anything to the standard output
I suggest you do two things:
1) read from standard error as well and see what that says
2) add a classpath argument prior to the class file
p.StartInfo.Arguments = " -cp C:\\code\\myapp HelloWorld 1";
(Obviously substituting in the correct path to the folder that contains HelloWorld.class)
Another alternative is to set your process start info to the location of HelloWorld:
ProcessStartInfo pInfo = new ProcessStartInfo(#"C:\Program Files\Java\jdk1.6.0_25\bin\java.exe");
pInfo.Arguments = = "HelloWorld";
pInfo.WorkingDirectory = #"C:\JavaFiles";
pInfo.UseShellExecute = false;
pInfo.RedirectStandardOutput = true;
Process javaProc = Process.Start(pInfo);
string output = javaProc.StandarOutput.ReadToEnd();
EDIT: I just realized your p was a Process object. WorkingDirectory is a property of ProcessStartInfo
This is assuming that C:\JavaFiles\HelloWorld.class and C:\JavaFiles\HelloWorld.java exists. You should also follow Greg's advice and read StandardError, as it will help you troubleshoot future problems
I have following code
using (StreamWriter outfile = new StreamWriter(#"f:\trial.cpp"))
{
outfile.Write(txtCode.InnerText);
}
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo(#"cl.exe", #" 'trial.cpp'");
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.UserName = "asdasd";
SecureString secureString = new SecureString();
foreach (char c in "abcded")
{
secureString.AppendChar(c);
}
procStartInfo.Password = secureString;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
procStartInfo.WorkingDirectory = #"f:\";
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result = proc.StandardOutput.ReadToEnd();
How to pass file name as parameter? Above code doesn't run and I have tried all full path, different path options.
can anyone help?
The argument is set incorrectly. You have:
var procStartInfo = new ProcessStartInfo(#"cl.exe", #" 'trial.cpp'");
Where there are spaces and single quotes in the name. Try:
var procStartInfo = new ProcessStartInfo(#"cl.exe", #"trial.cpp");
EDIT:
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "CL.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = "trial.cpp";
try
{
using (Process exeProcess = Process.Start(startInfo))
{
exeProcess.WaitForExit();
}
}
catch
{
// error handling
}
The point here is that CL is a command line executable, not a windows GUI application.
http://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx
http://msdn.microsoft.com/en-us/library/kezkeayy.aspx
http://msdn.microsoft.com/en-us/library/9s7c9wdw.aspx
If the cl.exe is not in the system PATH (which by default it is not) then the start process will not find the executable and it will fail to run.
So I suspect you are seeing the fact that the cl.exe is not in the system PATH.