三国卡牌客户端基础资源仓库
yyl
3 小时以前 cec146fc3fe287928e075c79ece20a20a9b16b20
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
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
 
using System;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
 
namespace Microsoft.Unity.VisualStudio.Editor
{
    internal class ProcessRunnerResult
    {
        public bool Success { get; set; }
        public string Output { get; set; }
        public string Error { get; set; }
    }
 
    internal static class ProcessRunner
    {
        public const int DefaultTimeoutInMilliseconds = 300000;
 
        public static ProcessStartInfo ProcessStartInfoFor(string filename, string arguments, bool redirect = true, bool shell = false)
        {
            return new ProcessStartInfo
            {
                UseShellExecute = shell,
                CreateNoWindow = true, 
                RedirectStandardOutput = redirect,
                RedirectStandardError = redirect,
                FileName = filename,
                Arguments = arguments
            };
        }
 
        public static void Start(string filename, string arguments)
        {
            Start(ProcessStartInfoFor(filename, arguments, false));
        }
 
        public static void Start(ProcessStartInfo processStartInfo)
        {
            var process = new Process { StartInfo = processStartInfo };
 
            using (process)
            {
                process.Start();
            }
        }
 
        public static ProcessRunnerResult StartAndWaitForExit(string filename, string arguments, int timeoutms = DefaultTimeoutInMilliseconds, Action<string> onOutputReceived = null)
        {
            return StartAndWaitForExit(ProcessStartInfoFor(filename, arguments), timeoutms, onOutputReceived);
        }
 
        public static ProcessRunnerResult StartAndWaitForExit(ProcessStartInfo processStartInfo, int timeoutms = DefaultTimeoutInMilliseconds, Action<string> onOutputReceived = null)
        {
            var process = new Process { StartInfo = processStartInfo };
 
            using (process)
            {
                var sbOutput = new StringBuilder();
                var sbError = new StringBuilder();
 
                var outputSource = new TaskCompletionSource<bool>();
                var errorSource = new TaskCompletionSource<bool>();
                
                process.OutputDataReceived += (_, e) =>
                {
                    Append(sbOutput, e.Data, outputSource);
                    if (onOutputReceived != null && e.Data != null)
                        onOutputReceived(e.Data);
                };
                process.ErrorDataReceived += (_, e) => Append(sbError, e.Data, errorSource);
 
                process.Start();
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();
                
                var run = Task.Run(() => process.WaitForExit(timeoutms));
                var processTask = Task.WhenAll(run, outputSource.Task, errorSource.Task);
 
                if (Task.WhenAny(Task.Delay(timeoutms), processTask).Result == processTask && run.Result)
                    return new ProcessRunnerResult {Success = true, Error = sbError.ToString(), Output = sbOutput.ToString()};
 
                try
                {
                    process.Kill();
                }
                catch
                {
                    /* ignore */
                }
                
                return new ProcessRunnerResult {Success = false, Error = sbError.ToString(), Output = sbOutput.ToString()};
            }
        }
 
        private static void Append(StringBuilder sb, string data, TaskCompletionSource<bool> taskSource)
        {
            if (data == null)
            {
                taskSource.SetResult(true);
                return;
            }
 
            sb?.Append(data);
        }
    }
}