What is the difference between the below processes? - c#

This process is running "independently" from my app. I can use my form meanwhile the script is running, not waiting for exit.
string strCmdText = "some command line script";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
This one though stops the process in my form till command line window is being closed:
Process p = new Process();
p.StartInfo.Verb = "runas";
p.StartInfo.FileName = cmd.exe;
p.Start();
To me both seems to be the same process.start(). So what is the difference?

They are very similar but not equivalent.
Here is how Process.Start method implemented;
public static Process Start(string fileName, string arguments)
{
return Start(new ProcessStartInfo(fileName, arguments));
}
new ProcessStartInfo(fileName, arguments) constructor sets second parameter to arguments string which is ProcessStartInfo.Arguments property not Verb property. And also;
public static Process Start(ProcessStartInfo startInfo)
{
Process process = new Process();
if (startInfo == null) throw new ArgumentNullException("startInfo");
process.StartInfo = startInfo;
if (process.Start()) {
return process;
}
return null;
}
As you can see from it's documentation;
The overload associates the resource with a new Process component. If
the process is already running, no additional process is started.
Instead, the existing process resource is reused and no new Process
component is created. In such a case, instead of returning a new
Process component, Start returns null to the calling procedure.

Related

Kill Process in ffmpeg in c#

I'm using Process class to execute commands in ffmpeg like this:
string command = "/C ffmpeg -re -i test.mp4 -f mpegts udp://127.0.0.1:" + port.Text;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.Arguments = command;
process.Start();
this code streams video to network, but I want to stop streaming when I click on button
I used process.kill() but the process still streaming even if I closed application
How can I stop process in background or send ctrl+c to it ?
The leading "/C" indicates that you start it via cmd.exe?
In that case process corresponds to cmd which in turn starts ffmpeg. Thus killing cmd doesn't kill ffmpeg.
string command = "-re -i test.mp4 -f mpegts udp://127.0.0.1:" + port.Text;
process.StartInfo.FileName ="ffmpeg";
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.Arguments = command;
process.Start();
process.Kill(); should work then.
So I was going through the same trouble of starting and stopping ffmpeg process in my selenium Nunit test. After bit of struggle I was able to create a simple solution. Sending as "q" a input to the process window of ffmpeg gracefully stops the process and the video recording is not corrupt as well.
here is my c# code to start the ffmpeg and stop it after execution.
Create a bat file to start your ffmpeg (you will be calling this batfile from your c# code)
In you selenium test , create a recording class and 2 methods to start and stop the recording(in my case I was starting the bat file before all test as in calling the executeScreenRecordingBatFile method in onetimesetup attribute to start the recording and calling the StopScreenRecording method in onetimeteardown ) Sample code below.
using System.Diagnostics;
using System.IO;
namespace FunctionalTests
{
public class Recording
{
public static Process process;
public static void executeScreenRecordingBatFile()
{
try
{
process = new Process();
process.StartInfo.FileName = #"C:\Program Files (x86)\StartScreenRecording.bat";
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardInput = true;// this required to send input to the current process window.
bool started = process.Start();
if (started==true)
{
Console.WriteLine("Bat file started");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace.ToString());
throw;
}
}
public static void StopScreenRecording()
{
StreamWriter myStreamWriter = process.StandardInput; // this required to send StandardInput stream, nothing fancy
myStreamWriter.WriteLine("q"); //this will send q as an input to the ffmpeg process window making it stop , please cross check in task manager once if the ffmpeg is still running or closed.
}
}
}
I created a method to kill ffmpeg process.
private void KillAllFFMPEG()
{
Process killFfmpeg = new Process();
ProcessStartInfo taskkillStartInfo = new ProcessStartInfo
{
FileName = "taskkill",
Arguments = "/F /IM ffmpeg.exe",
UseShellExecute = false,
CreateNoWindow = true
};
killFfmpeg.StartInfo = taskkillStartInfo;
killFfmpeg.Start();
}
Just call it wherever you want.
UPDATE 1
In order to kill just one instance of the FFMPEG process, we need to get it's PID first. When you define your ffmpeg process for streaming, define it in the global scope and use following command to get the PID after it is initialized.
int myProcessId = FfmpegProcess.Id;
Then call the following
private void KillFFMPEGByPID(int PID)
{
Process killFfmpeg = new Process();
ProcessStartInfo taskkillStartInfo = new ProcessStartInfo
{
FileName = "taskkill",
Arguments = "/PID " + Convert.ToString(PID) + " /T",
UseShellExecute = false,
CreateNoWindow = true
};
killFfmpeg.StartInfo = taskkillStartInfo;
killFfmpeg.Start();
}
This will kill only the process with the given PID. /T flag at the end of the argument determines that whole process tree will be killed.
Cheers

How to restart a windows service on failure?

I came across this question, which looked like it would resolve what I'm trying to do, and I'm trying to use similar code where a Process() object is created and the "sc" command is called from code.
static void SetRecoveryOptions(string serviceName)
{
int exitCode;
using (var process = new Process())
{
var startInfo = process.StartInfo;
startInfo.FileName = "sc";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
// tell Windows that the service should restart if it fails
startInfo.Arguments = string.Format("failure \"{0}\" reset= 0 actions= restart/60000", serviceName);
process.Start();
process.WaitForExit();
exitCode = process.ExitCode;
}
if (exitCode != 0)
throw new InvalidOperationException();
}
I've tried calling that code from a few locations (such as the committed event handler for the service installer, OnStart of the service itself, etc) but every time I get an exception as soon as the Process() object is created. The exception is: "operation is not allowed due to the current state of the object".
Any ideas what I'm missing here?

Calling Mp4Box.exe from .NET C#

Hello i am making a code for doing some editing on mp4 video using mp4box.exe
i want to execute this command line:
"D:\Work\Me\CloudContentUpload\trunk\ContentUploading Current\bin\Debug\Mp4Box\Mp4Box.exe" -isma -inter 500 "C:\Users\Abdullah\Desktop\videoo\amr khaled - Asmaa_elmogeb\Asmaa_elmogeb(1).mp4"
This command executed successfully when i run it manually on command line
but i try to execute it with the following C# code:
public string ExecuteCommandSync(object command)
{
try
{
// create the ProcessStartInfo using "cmd" as the program to be run,
// and "/c " as the parameters.
// Incidentally, /c tells cmd that we want it to execute the command that follows,
// and then exit.
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
// The following commands are needed to redirect the standard output.
// This means that it will be redirected to the Process.StandardOutput StreamReader.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
// 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();
// Display the command output.
return result;
}
catch (Exception objException)
{
return objException.Message;
}
}
the result returned is empty string !!
You shouldn't need to call cmd for this.
You should call your program directly and pass in the arguments to the Arguments property of ProcessStartInfo.

Command line program/app + C# class method

When working with a command line program, via a c# class method.
How do you determine if the commandline program was successfully executed and the operation it has performed is ok or has failed?
Also how do you get the screen commandline output into the c# class method?
You can use the Process class to execute a command line command.
The following code captures the standard output to output, and assigns the processes exit code to exitCode.
using (Process p = new Process())
{
p.StartInfo.FileName = exeName;
p.StartInfo.Arguments = args;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
int exitCode = p.ExitCode;
}
Something like:
Process mycommand = new Process();
mycommand.StartInfo.FileName = "myexe.exe";
mycommand.StartInfo.Arguments = "param1";
mycommand.StartInfo.UseShellExecute = false;
mycommand.StartInfo.RedirectStandardOutput = true;
mycommand.Start();
Console.WriteLine(mycommand.StandardOutput.ReadToEnd());
mycommand.WaitForExit();
You usually determine an exe's state wether the exit code is 0, but that is arguably down to the writer of the exe
I assume you're using the Process class to call the command line app.
You can find the exit code of the process using Process.ExitCode. You can redirect its standard output by setting ProcessStartInfo.RedirectStandardOutput before starting it, and then either using Process.StandardOutput or the Process.OutputDataReceived event.
Take a look at this questionenter link description here.
The additional information you might need is process.ExitCode to see if it was sucessful. Of course, the Main method of the console app must return an exit code when it is unsuccessful, which many do not.
For this, you use the Process.Start method. You can control how the process runs with the passed in ProcessStartInfo:
var myProcess = Process.Start(new ProcessStartInfo {
FileName = "process.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
});
if (!myProcess.WaitForExit(5000)) { // give it 5 seconds to exit
myProcess.Kill();
}
if (myProcess.ExitCode != 0) {
// error!
}
var output = myProcess.StandardOutput.ReadToEnd(); // access output

How to pass the arguments to a batch file?

I have requirement to run a set of *.sql files using batch file like this.
private void btn_Execute_Click(object sender, EventArgs e)
{
try {
//Creating A batch file to execute the scripts using SQLPLUS....
FileInfo fi5 = new FileInfo("c:/EMPSCRIPTS/execute.bat");
StreamWriter sw2 = fi5.CreateText();
sw2.WriteLine("#Echo Off \r \nsqlplus scotte/tiger#emp #\"c:/EMPSCRIPTS/RUNALL.sql\" \r \nEXIT ");
sw2.Close();
System.Diagnostics.Process proc; // Declare New Process
proc = System.Diagnostics.Process.Start(ConfigurationManager.AppSettings["BatFilePath"].ToString()); // run test.bat from command line.
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = "/c" + ConfigurationManager.AppSettings["BatFilePath"].ToString();
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardInput = true;
proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
proc.Close();
}
catch (Exception ex) {
MessageBox.Show("Insertion Completed");
}
}
But I want to stop some files being executed unnecessarily. I found the option for passing the parameters. I want to give the parameters to the files staticly. Based on the users input that parameter has to execute. Could any one help me?
Thanks in Advance.
You're changing the values of StartInfo after the process has been started, which has no effect on the process. See the "Remarks" section here for more information.
Create a new instance of ProcessStartInfo, set it up with what you need, then pass it into the overload of Start that takes an instance of this type.
In addition, once you change your code around, you can probably skip writing the command line to the batch file. Your executable filename is sqlplus and your arguments are scotte/tiger#emp #\"c:/EMPSCRIPTS/RUNALL.sql\"
You're misusing Process.Start.
You need to create a new ProcessStartInfo object, set all of its properties, then pass it to Process.Start.
Modifying the StartInfo of an already-running process, as your code is doing, has no effect.

Categories

Resources