This repository was archived by the owner on Oct 9, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 74
Expand file tree
/
Copy pathProcessSpawnable.cs
More file actions
146 lines (127 loc) · 4.88 KB
/
Copy pathProcessSpawnable.cs
File metadata and controls
146 lines (127 loc) · 4.88 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.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ExpectNet
{
/// <summary>
/// Represents spawnable shell command
/// </summary>
public class ProcessSpawnable : ISpawnable
{
private IProcess _process;
private Task<string> _errorRead = null;
private Task<string> _stdRead = null;
internal IProcess Process { get { return _process; } }
/// <summary>
/// Initializes new ProcessSpawnable instance to handle shell command process
/// </summary>
/// <param name="filename">filename to be run</param>
/// <param name="arguments">arguments to be passed to process</param>
public ProcessSpawnable(string filename, string arguments)
{
Process p = new Process();
p.StartInfo.FileName = filename;
p.StartInfo.Arguments = arguments;
_process = new ProcessAdapter(p);
}
/// <summary>
/// Initializes new ProcessSpawnable instance to handle shell command process
/// </summary>
/// <param name="filename">filename to be run</param>
public ProcessSpawnable(string filename)
: this(filename, "")
{ }
/// <summary>
/// Initializes new ProcessSpawnable instance to handle shell command process
/// </summary>
/// <param name="process">process to be run</param>
public ProcessSpawnable(Process process)
{
_process = new ProcessAdapter(process);
}
internal ProcessSpawnable(IProcess process)
{
_process = process;
}
/// <summary>
/// Prepares and starts process
/// </summary>
public void Init()
{
if (_process.StartInfo.FileName == null || _process.StartInfo.FileName.Length == 0)
{
throw new ArgumentException("FileName cannot be empty string", "_process.StartInfo.FileName");
}
// _process.StartInfo.UseShellExecute = false;
// _process.StartInfo.RedirectStandardInput = true;
// _process.StartInfo.RedirectStandardError = true;
// _process.StartInfo.RedirectStandardOutput = true;
_process.Start();
}
/// <summary>
/// Writes to process StandardInput stream
/// </summary>
/// <param name="command">specify what should be written to process</param>
public void Write(string command)
{
if (_errorRead == null || _errorRead.IsCanceled || _errorRead.IsCompleted || _errorRead.IsFaulted)
{
//_process.StandardError.DiscardBufferedData();
}
if (_stdRead == null || _stdRead.IsCanceled || _stdRead.IsCompleted || _stdRead.IsFaulted)
{
//_process.StandardOutput.DiscardBufferedData();
}
_process.StandardInput.Write(command);
}
/// <summary>
/// Reads in asynchronous way from both standard input and standard error streams.
/// </summary>
/// <returns>text read from streams</returns>
public async Task<string> ReadAsync()
{
List<Task<string>> tasks = new List<Task<string>>();
RecreateErrorReadTask();
RecreateStdReadTask();
tasks.Add(_errorRead);
tasks.Add(_stdRead);
var ret = await Task<string>.WhenAny<string>(tasks).ConfigureAwait(false);
return await ret.ConfigureAwait(false);
}
private void RecreateErrorReadTask()
{
if (_errorRead == null || _errorRead.IsCanceled || _errorRead.IsCompleted || _errorRead.IsFaulted)
{
char[] tmp = new char[256];
_errorRead = CreateStringAsync(tmp, _process.StandardError.ReadAsync(tmp, 0, 256));
}
}
private void RecreateStdReadTask()
{
if (_stdRead == null || _stdRead.IsCanceled || _stdRead.IsCompleted || _stdRead.IsFaulted)
{
char[] tmp = new char[256];
_stdRead = CreateStringAsync(tmp, _process.StandardOutput.ReadAsync(tmp, 0, 256));
}
}
private async Task<string> CreateStringAsync(char[] c, Task<int> n)
{
return new string(c, 0, await n.ConfigureAwait(false));
}
/// <summary>
/// Reads in synchronous way from both standard input and standard error streams.
/// </summary>
/// <returns>text read from streams</returns>
public string Read(out bool complete)
{
var t = Task.Run(async () => { return await ReadAsync().ConfigureAwait(false); });
complete = false;
return t.Result;
}
}
}