I'm using the below code to download from youtube using youtube-dl python script.
string pythonPath = #"C:\Python35\python.exe";
string ydl = #"C:\Y\ydl\youtube-dl";
string tempLocation = Server.MapPath("/ydl/");
string Output = "";
string Error = "";
int numOutputLines = 0;
int numErrorLines = 0;
using (Process process = new Process())
{
process.EnableRaisingEvents = true;
process.StartInfo.ErrorDialog = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.FileName = pythonPath;
process.StartInfo.WorkingDirectory = tempLocation;
process.StartInfo.Arguments = ydl + " --output test.mp4 --force-ipv4 -f bestvideo[ext=mp4]+bestaudio[ext=m4a] \"" + Url + "\"";
process.StartInfo.Verb = "runas";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
StringBuilder output = new StringBuilder();
StringBuilder error = new StringBuilder();
using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
{
process.OutputDataReceived += (sender, e) =>
{
if (e.Data == null)
{
outputWaitHandle.Set();
}
else
{
numOutputLines++;
this.Context.Response.Write(Environment.NewLine + "[" + numOutputLines.ToString() + "] - " + e.Data);
output.AppendLine("[" + numOutputLines.ToString() + "] - " + e.Data);
}
};
process.ErrorDataReceived += (sender, e) =>
{
if (e.Data == null)
{
errorWaitHandle.Set();
}
else
{
numErrorLines++;
this.Context.Response.Write(Environment.NewLine + "[" + numErrorLines.ToString() + "] - " + e.Data);
error.AppendLine("[" + numErrorLines.ToString() + "] - " + e.Data);
}
};
//process.Exited += (s, a) =>
//{
// process.Close();
//};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
//process.WaitForExit();
Process[] curProcess = Process.GetProcessesByName("youtube-dl");
Process youtubeProcess = curProcess.FirstOrDefault();
while (!youtubeProcess.HasExited)
{
Thread.Sleep(100);
}
Output = output.ToString();
Error = error.ToString();
process.Close();
}
}
I used the proccess in this way because I want to have the percentage of youtube-dl script for showing in my client side progress bar.
But there are some problems and it's that WaitForExit is not working. I read from other topics that this issue is related to wait in process not working for child process(I mean in my way, the wait for exit works for python not for youtube-dl script)
What should I do?
Since you are interested in a child process maybe you an try to poll on the youtube process by using the method:
Process.GetProcessesByName(string processName);
Something like this:
Process[] curProcess = Process.GetProcessesByName("your youtube process name");
Process youtubeProcess = curProcess.FirstOrDefault(); // Get here the right process instance
while (!youtubeProcess.HasExited)
{
Thread.Sleep(100);
}
Related
I would like to use Powershell to Start an application with some options of Start-Process as the code and then close the application after the process is done. The process is to measure some signals.
At first, this process is done by the C# code but I think this function can be converted to Powershell. However I dont' know how to do that, especially, with the Process.Exited and Process.EnableRaisingEvents.
Please help me.
Thank you in advance.
public void Execute_process(string console_path, string arg1)
{
try
{
//プロセス作成
p = new Process();
p.StartInfo.FileName = console_path + "\\" + "IQfactRun_Console.exe";
//p.StartInfo.Verb = "RunAs";
p.StartInfo.Arguments = " -run " + ini["IQFACT", "flow_folder"] + "\\" + arg1;
Debug.WriteLine("arg:" + " -run " + ini["IQFACT", "flow_folder"] + "\\" + arg1);
p.StartInfo.CreateNoWindow = false;
p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Minimized;
p.StartInfo.UseShellExecute = true;
p.StartInfo.WorkingDirectory = ini["IQFACT", "Console_file"];
p.StartInfo.RedirectStandardError = false;
p.StartInfo.RedirectStandardOutput = false;
p.StartInfo.RedirectStandardInput = false;
p.Exited += new EventHandler(Process_exited);
p.EnableRaisingEvents = true;
//プロセス実行状態に設定
run_status = true;
//外部プロセス起動
p.Start();
}
catch (Exception ex)
{
Debug.WriteLine("例外発生:" + ex);
}
}
I have this class which runs a process:
public static async Task<ProcessResult> ExecuteShellCommand(string command, string arguments="", int timeout=1000, bool insertWait=false)
{
var result = new ProcessResult();
using (var process = new Process())
{
process.StartInfo.FileName = command;
process.StartInfo.Arguments = arguments;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
var outputBuilder = new StringBuilder();
var outputCloseEvent = new TaskCompletionSource<bool>();
process.OutputDataReceived += (s, e) =>
{
// The output stream has been closed i.e. the process has terminated
if (e.Data == null)
{
outputCloseEvent.SetResult(true);
}
else
{
outputBuilder.AppendLine(e.Data);
}
};
var errorBuilder = new StringBuilder();
var errorCloseEvent = new TaskCompletionSource<bool>();
process.ErrorDataReceived += (s, e) =>
{
// The error stream has been closed i.e. the process has terminated
if (e.Data == null)
{
errorCloseEvent.SetResult(true);
}
else
{
errorBuilder.AppendLine(e.Data);
}
};
bool isStarted;
try
{
process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
isStarted = process.Start();
StreamReader reader = process.StandardOutput;
string output = reader.ReadToEnd();
result.Output = output;
}
catch (Exception error)
{
// Usually it occurs when an executable file is not found or is not executable
result.Completed = true;
result.ExitCode = -1;
result.Output = error.Message;
isStarted = false;
}
if (isStarted)
{
// Reads the output stream first and then waits because deadlocks are possible
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (insertWait)
{
await Task.Delay(150000);
}
// Creates task to wait for process exit using timeout
var waitForExit = WaitForExitAsync(process, timeout);
// Create task to wait for process exit and closing all output streams
var processTask = Task.WhenAll(waitForExit, outputCloseEvent.Task, errorCloseEvent.Task);
// Waits process completion and then checks it was not completed by timeout
if (await Task.WhenAny(Task.Delay(timeout), processTask) == processTask && waitForExit.Result)
{
result.Completed = true;
result.ExitCode = process.ExitCode;
// Adds process output if it was completed with error
if (process.ExitCode != 0)
{
result.Output = $"{outputBuilder}{errorBuilder}";
}
}
else
{
try
{
// Kill hung process
process.Kill();
}
catch
{
}
}
}
}
return result;
}
This line calls the ExecuteShellCommand method:
var result = TestHelper.ExecuteShellCommand(MessageInjectorOptions.MessageInjectorFilename, MessageInjectorOptions.MessageInjectorParameters + " " + binaryFile + " " + topic + " " + partition, 300000, true);
My logging shows that this is the command that gets run:
C:\Program Files\Java\jre1.8.0_281\bin\java.exe -jar C:\Users\Administrator\Downloads\test_tool\Jar\Injector\Injector-1.0.jar FILE TOPIC 2
This should push messages contained in FILE to a Kafka topic but the messages don't appear on the topic so I assume the jar doesn't run. If I copy and paste the command to a dos terminal and run it I can see the messages on the topic.
Is there anything wrong with my code that might cause Process to not run correctly?
I am currently struggling with bringing existing data in batch file to C# window form
The whole objective is getting a result lively from batch file to C# rich text box but I am keep getting failure of doing it.
The procedure works like click button->run batch file secretly->C# gets data lively->display in rich text box
I was successful to run a batch file but it runs in another new CMD causing hanging problem during debugging.
I would like to know whether anyone can wrote me a code to overcome such problem. Hope for the best answer
ProcessStartInfo cmd = new ProcessStartInfo();
Process process = new Process();
cmd.FileName = #"cmd";
cmd.UseShellExecute = false;
cmd.RedirectStandardError = true;
cmd.RedirectStandardInput = true;
cmd.RedirectStandardOutput = true;
cmd.CreateNoWindow = true;
process.EnableRaisingEvents = false;
process.StartInfo = cmd;
process.Start();
process.StandardInput.Write(#"cd C:\Users\%username%\Desktop\Claymore's Dual Ethereum+Decred_Siacoin_Lbry_Pascal AMD+NVIDIA GPU Miner v11.0" + Environment.NewLine);
process.StandardInput.Write(#"EthDcrMiner64.exe -allpools 1 -epool asia1.ethereum.miningpoolhub.com:20535 -ewal AJStudio.AJStudio001 -epsw x -esm 2" + Environment.NewLine);
process.StandardInput.Close();
string result = process.StandardOutput.ReadToEnd();
StringBuilder sb = new StringBuilder();
sb.Append("[result info]" + DateTime.Now + "\r\n");
sb.Append(result);
sb.Append("\r\n");
richTextBox1.Text = sb.ToString();
process.WaitForExit();
process.Close();
To get real-time feedback from Process, use OutputDataReceived and ErrorDataReceived events. Something like this:
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.OutputDataReceived += Process_OutputDataReceived;
process.ErrorDataReceived += Process_ErrorDataReceived;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
private void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data == null) return;
log("ERROR: " + e.Data);
}
private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data == null) return;
log(e.Data);
}
I want to import a csv file to mongodb by using mongoimport in C#. So I implement this method
public bool importCSV(string filepath, string db, string collectionName){
string result="";
try
{
ProcessStartInfo procStart = new ProcessStartInfo("cmd", "C:/MongoDB/Server/3.0/bin/mongoimport -d " + db + " -c " + collectionName + " --type csv --file " + filepath );
procStart.RedirectStandardOutput = true;
procStart.CreateNoWindow = false;
Process proc = new Process();
proc.StartInfo = procStart;
proc.Start();
result += proc.StandardOutput.ReadToEnd();
}
catch(Exception e){
Console.WriteLine(e.ToString());
}
if (!result.Equals("")){
return true;
}
return false;
}
When I run command itself, I can import file to MongoDB. But by using C#, method returns false.
Can anyone help me to solve this problem?
SOLUTION!!!
public bool importCsv(string filepath, string collectionName){
string result ="";
try
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = #"C:/MongoDB/Server/3.0/bin/mongoimport.exe";
startInfo.Arguments = #" -d test -c " + collectionName + " --type csv --file " + filepath + " --headerline";
Process proc = new Process();
proc.StartInfo = startInfo;
proc.Start();
result += "ddd";
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
if (!result.Equals(""))
{
return true;
}
return false;
}
try something like this:
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
{
result+=e.Data;
}
});
process.Start();
// Asynchronously read the standard output of the spawned process.
// This raises OutputDataReceived events for each line of output.
process.BeginOutputReadLine();
process.WaitForExit();
process.Close();
I'm trying to capture process output in "realtime" (while it's running). The code I use is rather simple (see below). For some strange reason the OutputDataReceived event is never called. Why?
private void button2_Click(object sender, EventArgs e)
{
// Setup the process start info
var processStartInfo = new ProcessStartInfo("ping.exe", "-t -n 3 192.168.100.1")
{
UseShellExecute = false,
RedirectStandardOutput = true
};
// Setup the process
mProcess = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true };
// Register event
mProcess.OutputDataReceived += OnOutputDataReceived;
// Start process
mProcess.Start();
mProcess.WaitForExit();
}
void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
{
//Never gets called...
}
You need to call
mProcess.BeginOutputReadLine();
BeginOutputReadLine - "Begins asynchronous read operations on the redirected StandardOutput stream of the application."
void ExecuteCommand(string cmdpath, string cmdargs)
{
string command = cmdpath + " " + cmdargs;
tabc_results.SelectTab(1);
DoConsole("\r\nCmd>> " + command + "\r\n");
var processInfo = new System.Diagnostics.ProcessStartInfo("cmd.exe", "/c " + command);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
var process = System.Diagnostics.Process.Start(processInfo);
process.OutputDataReceived += (
object sender, System.Diagnostics.DataReceivedEventArgs e
) => DoConsole("stdout>> " + e.Data + "\r\n");
//Console.WriteLine("output>>" + e.Data);
process.BeginOutputReadLine();
process.ErrorDataReceived += (
object sender, System.Diagnostics.DataReceivedEventArgs e
) =>DoConsole("stderr>> " + e.Data + "\r\n");
//Console.WriteLine("error>>" + e.Data);
process.BeginErrorReadLine();
process.WaitForExit();
DoConsole("retcode>> " + process.ExitCode.ToString() + "\r\n");
//Console.WriteLine("ExitCode: {0}", process.ExitCode);
process.Close();
}