forked from fdorg/flashdevelop
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProcessRunner.cs
More file actions
146 lines (127 loc) · 5.03 KB
/
ProcessRunner.cs
File metadata and controls
146 lines (127 loc) · 5.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using PluginCore.Managers;
namespace PluginCore.Utilities
{
public class ProcessRunner
{
Process process;
Boolean isRunning;
StreamReader outputReader;
StreamReader errorReader;
Int32 tasksFinished;
public event LineOutputHandler Output;
public event LineOutputHandler Error;
public event ProcessEndedHandler ProcessEnded;
public String WorkingDirectory;
public Process HostedProcess { get { return process; } }
public Boolean IsRunning { get { return isRunning; } }
public Boolean RedirectInput;
NextTask nextTask = null;
public void Run(String fileName, String arguments)
{
Run(fileName, arguments, false);
}
public void Run(String fileName, String arguments, Boolean shellCommand)
{
if (isRunning)
{
// kill process and queue Run command
nextTask = () => {
Run(fileName, arguments, shellCommand);
};
this.KillProcess();
return;
}
if (!shellCommand && !File.Exists(fileName))
throw new FileNotFoundException("The program '" + fileName + "' was not found.", fileName);
isRunning = true;
process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = RedirectInput;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.StandardOutputEncoding = Encoding.Default;
process.StartInfo.StandardErrorEncoding = Encoding.Default;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = fileName;
process.StartInfo.Arguments = arguments;
process.StartInfo.WorkingDirectory = WorkingDirectory ?? PluginBase.MainForm.WorkingDirectory;
process.Start();
outputReader = process.StandardOutput;
errorReader = process.StandardError;
// we need to wait for all 3 threadpool operations
// to finish (processexit, readoutput, readerror)
tasksFinished = 0;
ThreadStart waitForExitDel = new ThreadStart(process.WaitForExit);
waitForExitDel.BeginInvoke(new AsyncCallback(TaskFinished), null);
ThreadStart readOutputDel = new ThreadStart(ReadOutput);
ThreadStart readErrorDel = new ThreadStart(ReadError);
readOutputDel.BeginInvoke(new AsyncCallback(TaskFinished), null);
readErrorDel.BeginInvoke(new AsyncCallback(TaskFinished), null);
}
public void KillProcess()
{
if (process == null) return;
try
{
if (isRunning) TraceManager.AddAsync("Kill active process...", -3);
isRunning = false;
// recursive kill (parent and children)
Process KillerP = new Process();
KillerP.StartInfo.FileName = "taskkill.exe";
KillerP.StartInfo.Arguments = "/PID " + process.Id + " /T /F";
KillerP.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
KillerP.Start();
KillerP.WaitForExit();
}
catch (Exception ex)
{
ErrorManager.ShowError(ex);
}
}
private void ReadOutput()
{
while (true)
{
string line = outputReader.ReadLine();
if (line == null) break;
if (Output != null) Output(this, line);
}
}
private void ReadError()
{
while (true)
{
string line = errorReader.ReadLine();
if (line == null) break;
if (Error != null) Error(this, line);
}
}
private void TaskFinished(IAsyncResult result)
{
lock (this)
{
if (++tasksFinished >= 3)
{
isRunning = false;
if (nextTask != null)
{
nextTask();
nextTask = null;
// do not call ProcessEnd if another process was queued after the kill
}
else if (process != null && ProcessEnded != null)
ProcessEnded(this, process.ExitCode);
}
}
}
}
public delegate void LineOutputHandler(Object sender, String line);
public delegate void ProcessEndedHandler(Object sender, Int32 exitCode);
public delegate void ProcessOutputHandler(Object sender, String line);
delegate void NextTask();
}