I am trying to start a process on Mac and Windows (using Unity) to run FFMPEG to convert a video to a .ogv video. My code is as follows:
string command = "ffmpeg -i '" + filepath + "' -codec:v libtheora -qscale:v 10 -codec:a libvorbis -qscale:a 10 -y '"+workingDir+"/ogv_Video/"+System.IO.Path.GetFileNameWithoutExtension(filepath)+".ogv'";
UnityEngine.Debug.Log("Command: "+command);
try{
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo (workingDir+"/..", command);
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
startInfo.FileName =workingDir+"/ffmpeg";
//Process.Start (startInfo);
Process p = Process.Start(startInfo);
p.EnableRaisingEvents = true;
string strOutput = p.StandardOutput.ReadToEnd();
UnityEngine.Debug.Log ("Running..."+strOutput);
p.WaitForExit();
UnityEngine.Debug.Log ("Got here. "+strOutput);
int exitCode = p.ExitCode;
UnityEngine.Debug.Log ("Process exit code = "+exitCode);
}
catch(Exception e) {
UnityEngine.Debug.Log ("An error occurred");
UnityEngine.Debug.Log ("Error: "+e);
}
The command executes and does not through any exception. However, it terminates instantly and prints Exit Code 1 which is "Catchall for general errors" -this seems not too helpful!
What am I doing wrong with my code, please?
You'll notice that my code prints out the command in full. If I copy that command and paste it into the terminal, it runs absolutely fine.
It turns out I was setting up the arguments wrongly. Referring to this Stack Overflow question, I was able to produce the expected result with the following code:
try{
Process process = new Process();
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.FileName = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) +#"ffmpeg";
process.StartInfo.Arguments = command;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();
JSONDataObject rtnMsg = new JSONDataObject("StartConvertOK", "-1", new List<string>());
return JsonUtility.ToJson(rtnMsg);
}
It does seem as though the answer was not that different from what I was doing, but it does work!
Related
I'm trying to use cmd CLI to excute a newman collection run. However when the process is running it's getting stuck and never finishes processing.
Any suggestions on how to deal with that?
string cmdCommand="newman run demo.postman_collection.json --env-var HTTP_PROXY --insecure";
int TotalTimeout= 150000;
CliProcess = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new
System.Diagnostics.ProcessStartInfo();
if (_inputDir != null)
{
startInfo.WorkingDirectory = _inputDir;
}
//startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.CreateNoWindow = false;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C "+cmdCommand;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardInput = true;
bool processExited;
startInfo.RedirectStandardOutput = false;
CliProcess.StartInfo = startInfo;
CliProcess.Start();
CliProcess.StandardInput.WriteLine("exit");
//CliProcess.BeginOutputReadLine();
//CliProcess.BeginErrorReadLine();
//CliProcess.Close();
processExited = CliProcess.WaitForExit(TotalTimeout);
// //&& outputWaitHandle.WaitOne(TotalTimeout) && errorWaitHandle.WaitOne(TotalTimeout);
//CliProcess.CancelOutputRead();
//CliProcess.CancelErrorRead();
//ExitCode = GetProcessExitCode();
//CliProcess.Kill();
//}
//Wait additional minute for the process to exit
if (!processExited)
{
KillNewman();
TraceLogger.Instance.LogMessage(TraceLevel.Warning, MsgSrc, "[SendCmdCommand(string cmdCommand)] Newman process was killed due to timeout");
}
This is the most I can get out of it:
It gets stuck here^ and never continues.
the problem was due to the fact that the proxy was misconfigured so the request was sent trying to get to an unresponsive proxy server...
So in conclusion, there was nothing wrong with the code itself.
I have an exe which has some parameters- path of another application and some files to be opened from that application. There would be an output as part of that application which would be displayed in the console of my exe.
But i am unable to get the output from the console.
I have the code:
ProcessStartInfo psi = new ProcessStartInfo("\"" + dllpath + "\\newapplication.exe" + "\"");
Process p = new Process();
psi.UseShellExecute = false;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
p.Start();
The process starts successfully, and then i have to open a file in the process which happens through another class. So after the file opened, some extraction happens and the result is displayed on the console.
When i give p.WaitForExit(); nothing happens other than starting the application! How do i acheive to retreive the output on StandardOutput as per my code? Need Help!
This is the correct way to do it:
string outputProcess = "";
string errorProcess = "";
using (Process process = new Process())
{
process.StartInfo.FileName = path;
process.StartInfo.Arguments = arguments;
process.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.Start();
outputProcess = process.StandardOutput.ReadToEnd();
errorProcess = process.StandardError.ReadToEnd();
process.WaitForExit();
}
Remember to use the using statement when you have an IDisposable object
Thanks to #user2526830 for the code. Based on that code I added few lines to my program since I want to read the output of the SSH command. Below is my code which gives an error at line while
StandardOut has not been redirected or the process hasn't started yet.
What I want to achieve is that I want to read the output of ls into a string.
ProcessStartInfo startinfo = new ProcessStartInfo();
startinfo.FileName = #"f:\plink.exe";
startinfo.Arguments = "-ssh abc#x.x.x.x -pw abc123";
Process process = new Process();
process.StartInfo = startinfo;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.Start();
process.StandardInput.WriteLine("ls -ltr /opt/*.tmp");
process.StandardInput.WriteLine("exit");
process.StartInfo.RedirectStandardOutput = true;
while (!process.StandardOutput.EndOfStream)
{
string line = process.StandardOutput.ReadLine();
}
process.WaitForExit();
Console.ReadKey();
Try setting standard output redirection before starting the process.
process.StartInfo.RedirectStandardOutput = true;
process.Start();
It might be that the process already terminated when you try to read the output (dues to your "exit" command). Try the below slightly modified version where I moved your while loop after the "ls" command but before the "exit" command.
It should read the output of your "ls" command fine, but unfortunately will most probably hang at some point as you will never get EndOfStream on the StandardOutput. When there is nothing more to read, ReadLine will block until it can get read another line.
So unless you know how to detect the last line of the output generated by your command and break out of the loop after you read it, you may need to use a separate thread either for reading or for writing.
ProcessStartInfo startinfo = new ProcessStartInfo();
startinfo.FileName = #"f:\plink.exe";
startinfo.Arguments = "-ssh abc#x.x.x.x -pw abc123";
Process process = new Process();
process.StartInfo = startinfo;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
process.StandardInput.WriteLine("ls -ltr /opt/*.tmp");
while (!process.StandardOutput.EndOfStream)
{
string line = process.StandardOutput.ReadLine();
}
process.StandardInput.WriteLine("exit");
process.WaitForExit();
Console.ReadKey();
Since i finished my School-Project and there is nothing left for now, I started to implement a Easteregg in my little Console Application. It should install telnet (pkgmgr /iu:"TelnetClient") and call the StarWars animation: "telnet" + "o" + "towel.blinkenlights.nl"
To do that, my Application opens up a CMD-Prompt, which installs Telnet:
public static void EastereggInstall()
{
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("pkgmgr /iu:'TelnetClient'");
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
Console.WriteLine(cmd.StandardOutput.ReadToEnd());
Environment.Exit(0);
}
After the Task is finished with Environment.Exit(0); it calls another CMD-prompt to connect to the telnet Server which starts the Animation:
public static void EastereggPlay()
{
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("telnet" + "o" + "towel.blinkenlights.nl");
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
Console.WriteLine(cmd.StandardOutput.ReadToEnd());
}
However, the first Commandprompt closes itself with no Error-message whatsoever.
I've also tried to use Console.ReadKey() to get the Error, but still no useful info there. My first thought was that cmd.StandardInput.WriteLine("telnet" + "o" + "towel.blinkenlights.nl"); can't be executed by using it in a single line, so i tried
cmd.StandardInput.WriteLine("telnet");
cmd.StandardInput.WriteLine("o");
cmd.StandardInput.WriteLine("towel.blinkenlights.nl");
Still no success. So do you guys know what i should do to get this piece of Code to work? Thanks!
use
ProcessStartInfo startInfo = new ProcessStartInfo("cmd");
startInfo.WindowStyle = ProcessWindowStyle.Normal;
startInfo.Arguments = "/c telnet o towel.blinkenlights.nl";
Process.Start(startInfo);
make sure that command works because the cmd process will just exit if not.
to make sure everything works, try something like
startInfo.Arguments = "/c ping google.com -t";
also, while testing you should consider setting CreateNoWindow to false
Environment.Exit(0) close the whole environment.
You should close only process, so the code can reach the telnet connection.
I have an app.exe application that asks to enter input path string, once i enter, it asks output path string... now when i enter, app.exe perform some operation
i need to pass these paths from my Window Form Application
i saw a lot of questions like this but could not implement what i require because i never worked with processes and Stream Reader or Writer
any help please... examples will be thanked.. thank you..
string input = #"C:\Documents and Settings\pankaj\Desktop\My File\greetingsfreinds.ppt";
string output = #"C:\Documents and Settings\pankaj\Desktop\test";
Process process = new Process();
process.StartInfo.FileName = #"C:\Program Files\Wondershare\MyApp\app.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = false;
process.StartInfo.RedirectStandardInput = true;
process.Start();
process.WaitForExit(3000);
process.Close();
ok i tried that
but its giving some exception
StandardOut has not been redirected or the process hasn't started yet...
my code was
string input = #"C:\Documents and Settings\pankaj\Desktop\My File\greetingsfreinds.ppt";
string output = #"C:\Documents and Settings\pankaj\Desktop\test";
Process process = new Process();
process.StartInfo.FileName = #"C:\Program Files\Wondershare\MyApp\app.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.Arguments = input + ";" + output;
process.Start();
string Strout = process.StandardOutput.ReadToEnd();
process.WaitForExit();
process.Close();
You can use ProcessStartInfo.Arguments for this.
Process process = new Process()
process.StartInfo.FileName = #"C:\Program Files\Wondershare\MyApp\app.exe";
process.StartInfo.UseShellExecute = false;
....
process.Arguments = input + " " + output;