forked from christianrondeau/SikuliSharp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSikuliRuntime.cs
91 lines (71 loc) · 3.35 KB
/
SikuliRuntime.cs
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
using System;
using System.Diagnostics;
namespace SikuliSharp {
public interface ISikuliRuntime : IDisposable {
void Start ();
void Stop (bool ignoreErrors = false);
string Run (string command, string resultPrefix, double timeoutInSeconds);
}
public class SikuliRuntime : ISikuliRuntime {
private readonly IAsyncDuplexStreamsHandlerFactory _asyncDuplexStreamsHandlerFactory;
private Process _process;
private static IAsyncTwoWayStreamsHandler _asyncTwoWayStreamsHandler;
private static ISikuliScriptProcessFactory _sikuliScriptProcessFactory;
private const string InteractiveConsoleReadyMarker = "... use ctrl-d to end the session";
private const string ErrorMarker = "[error]";
private const string ExitCommand = "exit()";
private const int SikuliReadyTimeoutSeconds = 120;
public SikuliRuntime (IAsyncDuplexStreamsHandlerFactory asyncDuplexStreamsHandlerFactory, ISikuliScriptProcessFactory sikuliScriptProcessFactory) {
if (asyncDuplexStreamsHandlerFactory == null) throw new ArgumentNullException ("asyncDuplexStreamsHandlerFactory");
if (sikuliScriptProcessFactory == null) throw new ArgumentNullException ("sikuliScriptProcessFactory");
_asyncDuplexStreamsHandlerFactory = asyncDuplexStreamsHandlerFactory;
_sikuliScriptProcessFactory = sikuliScriptProcessFactory;
}
public void Start () {
if (_process != null) throw new InvalidOperationException ("This Sikuli session has already been started");
_process = _sikuliScriptProcessFactory.Start ("-i");
_asyncTwoWayStreamsHandler = _asyncDuplexStreamsHandlerFactory.Create (_process.StandardOutput, _process.StandardError, _process.StandardInput);
_asyncTwoWayStreamsHandler.ReadUntil (SikuliReadyTimeoutSeconds, InteractiveConsoleReadyMarker);
}
public void Stop (bool ignoreErrors = false) {
if (_process == null) return;
_asyncTwoWayStreamsHandler.WriteLine (ExitCommand);
if (!_process.HasExited) {
if (!_process.WaitForExit (500))
_process.Kill ();
}
string errors = null;
if (!ignoreErrors)
errors = _process.StandardError.ReadToEnd ();
_asyncTwoWayStreamsHandler.WaitForExit ();
_asyncTwoWayStreamsHandler.Dispose ();
_asyncTwoWayStreamsHandler = null;
_process.Dispose ();
_process = null;
if (!ignoreErrors && !String.IsNullOrEmpty (errors))
throw new SikuliException ("Sikuli Errors: " + errors);
}
public string Run (string command, string resultPrefix, double timeoutInSeconds) {
if (_process == null || _process.HasExited)
throw new InvalidOperationException ("The Sikuli process is not running");
#if (DEBUG)
Debug.WriteLine (command);
#endif
_asyncTwoWayStreamsHandler.WriteLine (command);
_asyncTwoWayStreamsHandler.WriteLine ("");
_asyncTwoWayStreamsHandler.WriteLine ("");
var result = _asyncTwoWayStreamsHandler.ReadUntil (timeoutInSeconds, ErrorMarker, resultPrefix);
if (result.IndexOf (ErrorMarker, StringComparison.Ordinal) > -1) {
result = result + Environment.NewLine + string.Join (Environment.NewLine, _asyncTwoWayStreamsHandler.ReadUpToNow (0.1d));
if (result.Contains ("FindFailed"))
throw new SikuliFindFailedException (result);
if (!result.Contains ("jvmhook"))
throw new SikuliException (result);
}
return result;
}
public void Dispose () {
Stop (true);
}
}
}