├── .gitignore
├── LICENSE
├── OpenRoC
├── AboutDialog.Designer.cs
├── AboutDialog.cs
├── AboutDialog.resx
├── App.config
├── Docs
│ ├── main.png
│ ├── process.png
│ └── settings.png
├── Extensions.cs
├── FodyWeavers.xml
├── Logger.cs
├── LogsDialog.Designer.cs
├── LogsDialog.cs
├── LogsDialog.resx
├── MainDialog.Designer.cs
├── MainDialog.cs
├── MainDialog.resx
├── Metrics
│ ├── Collector.cs
│ ├── CpuCollector.cs
│ ├── GpuCollector.cs
│ ├── Manager.cs
│ └── RamCollector.cs
├── OpenRoC.csproj
├── OpenRoC.sln
├── ProcessDialog.Designer.cs
├── ProcessDialog.cs
├── ProcessDialog.resx
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── Resources
│ └── OpenRoc.xml
├── SensuInterface.cs
├── Settings.cs
├── SettingsDialog.Designer.cs
├── SettingsDialog.cs
├── SettingsDialog.resx
├── packages.config
├── phoenix.ico
└── testProcessWindowed
│ ├── App.config
│ ├── MainForm.Designer.cs
│ ├── MainForm.cs
│ ├── MainForm.resx
│ ├── Program.cs
│ ├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
│ └── testProcessWindowed.csproj
├── README.md
├── libOpenRoC
├── ExecutorService.cs
├── Extensions.cs
├── NativeMethods.cs
├── ProcessHelper.cs
├── ProcessManager.cs
├── ProcessObserver.cs
├── ProcessOptions.cs
├── ProcessRunner.cs
├── Properties
│ └── AssemblyInfo.cs
└── libOpenRoC.csproj
└── testOpenRoC
├── .gitignore
├── ExecutorServiceUnitTests.cs
├── ProcessManagerUnitTests.cs
├── ProcessOptionsUnitTests.cs
├── ProcessRunnerUnitTests.cs
├── Properties
└── AssemblyInfo.cs
└── testOpenRoC.csproj
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 | *.VC.VC.opendb
85 |
86 | # Visual Studio profiler
87 | *.psess
88 | *.vsp
89 | *.vspx
90 | *.sap
91 |
92 | # TFS 2012 Local Workspace
93 | $tf/
94 |
95 | # Guidance Automation Toolkit
96 | *.gpState
97 |
98 | # ReSharper is a .NET coding add-in
99 | _ReSharper*/
100 | *.[Rr]e[Ss]harper
101 | *.DotSettings.user
102 |
103 | # JustCode is a .NET coding add-in
104 | .JustCode
105 |
106 | # TeamCity is a build add-in
107 | _TeamCity*
108 |
109 | # DotCover is a Code Coverage Tool
110 | *.dotCover
111 |
112 | # NCrunch
113 | _NCrunch_*
114 | .*crunch*.local.xml
115 | nCrunchTemp_*
116 |
117 | # MightyMoose
118 | *.mm.*
119 | AutoTest.Net/
120 |
121 | # Web workbench (sass)
122 | .sass-cache/
123 |
124 | # Installshield output folder
125 | [Ee]xpress/
126 |
127 | # DocProject is a documentation generator add-in
128 | DocProject/buildhelp/
129 | DocProject/Help/*.HxT
130 | DocProject/Help/*.HxC
131 | DocProject/Help/*.hhc
132 | DocProject/Help/*.hhk
133 | DocProject/Help/*.hhp
134 | DocProject/Help/Html2
135 | DocProject/Help/html
136 |
137 | # Click-Once directory
138 | publish/
139 |
140 | # Publish Web Output
141 | *.[Pp]ublish.xml
142 | *.azurePubxml
143 | # TODO: Comment the next line if you want to checkin your web deploy settings
144 | # but database connection strings (with potential passwords) will be unencrypted
145 | *.pubxml
146 | *.publishproj
147 |
148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
149 | # checkin your Azure Web App publish settings, but sensitive information contained
150 | # in these scripts will be unencrypted
151 | PublishScripts/
152 |
153 | # NuGet Packages
154 | *.nupkg
155 | # The packages folder can be ignored because of Package Restore
156 | **/packages/*
157 | # except build/, which is used as an MSBuild target.
158 | !**/packages/build/
159 | # Uncomment if necessary however generally it will be regenerated when needed
160 | #!**/packages/repositories.config
161 | # NuGet v3's project.json files produces more ignoreable files
162 | *.nuget.props
163 | *.nuget.targets
164 |
165 | # Microsoft Azure Build Output
166 | csx/
167 | *.build.csdef
168 |
169 | # Microsoft Azure Emulator
170 | ecf/
171 | rcf/
172 |
173 | # Windows Store app package directories and files
174 | AppPackages/
175 | BundleArtifacts/
176 | Package.StoreAssociation.xml
177 | _pkginfo.txt
178 |
179 | # Visual Studio cache files
180 | # files ending in .cache can be ignored
181 | *.[Cc]ache
182 | # but keep track of directories ending in .cache
183 | !*.[Cc]ache/
184 |
185 | # Others
186 | ClientBin/
187 | ~$*
188 | *~
189 | *.dbmdl
190 | *.dbproj.schemaview
191 | *.pfx
192 | *.publishsettings
193 | node_modules/
194 | orleans.codegen.cs
195 |
196 | # Since there are multiple workflows, uncomment next line to ignore bower_components
197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
198 | #bower_components/
199 |
200 | # RIA/Silverlight projects
201 | Generated_Code/
202 |
203 | # Backup & report files from converting an old project file
204 | # to a newer Visual Studio version. Backup files are not needed,
205 | # because we have git ;-)
206 | _UpgradeReport_Files/
207 | Backup*/
208 | UpgradeLog*.XML
209 | UpgradeLog*.htm
210 |
211 | # SQL Server files
212 | *.mdf
213 | *.ldf
214 |
215 | # Business Intelligence projects
216 | *.rdl.data
217 | *.bim.layout
218 | *.bim_*.settings
219 |
220 | # Microsoft Fakes
221 | FakesAssemblies/
222 |
223 | # GhostDoc plugin setting file
224 | *.GhostDoc.xml
225 |
226 | # Node.js Tools for Visual Studio
227 | .ntvs_analysis.dat
228 |
229 | # Visual Studio 6 build log
230 | *.plg
231 |
232 | # Visual Studio 6 workspace options file
233 | *.opt
234 |
235 | # Visual Studio LightSwitch build output
236 | **/*.HTMLClient/GeneratedArtifacts
237 | **/*.DesktopClient/GeneratedArtifacts
238 | **/*.DesktopClient/ModelManifest.xml
239 | **/*.Server/GeneratedArtifacts
240 | **/*.Server/ModelManifest.xml
241 | _Pvt_Extensions
242 |
243 | # Paket dependency manager
244 | .paket/paket.exe
245 | paket-files/
246 |
247 | # FAKE - F# Make
248 | .fake/
249 |
250 | # JetBrains Rider
251 | .idea/
252 | *.sln.iml
253 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Helios Interactive
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/OpenRoC/AboutDialog.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace oroc
2 | {
3 | partial class AboutDialog
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutDialog));
32 | this.AboutRichTextBox = new System.Windows.Forms.RichTextBox();
33 | this.title = new System.Windows.Forms.Label();
34 | this.caption = new System.Windows.Forms.Label();
35 | this.SuspendLayout();
36 | //
37 | // AboutRichTextBox
38 | //
39 | this.AboutRichTextBox.BackColor = System.Drawing.SystemColors.Control;
40 | this.AboutRichTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
41 | this.AboutRichTextBox.Location = new System.Drawing.Point(12, 115);
42 | this.AboutRichTextBox.Name = "AboutRichTextBox";
43 | this.AboutRichTextBox.ReadOnly = true;
44 | this.AboutRichTextBox.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.None;
45 | this.AboutRichTextBox.Size = new System.Drawing.Size(528, 170);
46 | this.AboutRichTextBox.TabIndex = 0;
47 | this.AboutRichTextBox.TabStop = false;
48 | this.AboutRichTextBox.Text = resources.GetString("AboutRichTextBox.Text");
49 | this.AboutRichTextBox.LinkClicked += new System.Windows.Forms.LinkClickedEventHandler(this.OnAboutRichTextBoxLinkClicked);
50 | //
51 | // title
52 | //
53 | this.title.Dock = System.Windows.Forms.DockStyle.Top;
54 | this.title.Font = new System.Drawing.Font("Microsoft Sans Serif", 27.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
55 | this.title.Location = new System.Drawing.Point(0, 0);
56 | this.title.Name = "title";
57 | this.title.Size = new System.Drawing.Size(552, 64);
58 | this.title.TabIndex = 1;
59 | this.title.Text = "OpenRoC";
60 | this.title.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
61 | //
62 | // caption
63 | //
64 | this.caption.Dock = System.Windows.Forms.DockStyle.Top;
65 | this.caption.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
66 | this.caption.Location = new System.Drawing.Point(0, 64);
67 | this.caption.Name = "caption";
68 | this.caption.Size = new System.Drawing.Size(552, 39);
69 | this.caption.TabIndex = 2;
70 | this.caption.Text = "Open-source Restart on Crash";
71 | this.caption.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
72 | //
73 | // AboutDialog
74 | //
75 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
76 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
77 | this.ClientSize = new System.Drawing.Size(552, 297);
78 | this.Controls.Add(this.caption);
79 | this.Controls.Add(this.title);
80 | this.Controls.Add(this.AboutRichTextBox);
81 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
82 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
83 | this.MaximizeBox = false;
84 | this.Name = "AboutDialog";
85 | this.Text = "About";
86 | this.ResumeLayout(false);
87 |
88 | }
89 |
90 | #endregion
91 |
92 | private System.Windows.Forms.RichTextBox AboutRichTextBox;
93 | private System.Windows.Forms.Label title;
94 | private System.Windows.Forms.Label caption;
95 | }
96 | }
--------------------------------------------------------------------------------
/OpenRoC/AboutDialog.cs:
--------------------------------------------------------------------------------
1 | namespace oroc
2 | {
3 | using System.Diagnostics;
4 | using System.Windows.Forms;
5 |
6 | public partial class AboutDialog : Form
7 | {
8 |
9 | public AboutDialog()
10 | {
11 | InitializeComponent();
12 | }
13 |
14 | private void OnAboutRichTextBoxLinkClicked(object sender, LinkClickedEventArgs e)
15 | {
16 | using (Process.Start(e.LinkText)) { /* no-op */ }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/OpenRoC/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/OpenRoC/Docs/main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosInteractive/OpenRoC/9b69c54c28e230f795b48e92c2bff4ab29d80ad7/OpenRoC/Docs/main.png
--------------------------------------------------------------------------------
/OpenRoC/Docs/process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosInteractive/OpenRoC/9b69c54c28e230f795b48e92c2bff4ab29d80ad7/OpenRoC/Docs/process.png
--------------------------------------------------------------------------------
/OpenRoC/Docs/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosInteractive/OpenRoC/9b69c54c28e230f795b48e92c2bff4ab29d80ad7/OpenRoC/Docs/settings.png
--------------------------------------------------------------------------------
/OpenRoC/Extensions.cs:
--------------------------------------------------------------------------------
1 | namespace oroc
2 | {
3 | using Newtonsoft.Json;
4 | using Newtonsoft.Json.Converters;
5 |
6 | using System;
7 | using System.IO;
8 | using System.Xml;
9 | using System.Drawing;
10 | using System.Xml.Linq;
11 | using System.Reflection;
12 | using System.Windows.Forms;
13 | using System.Xml.Serialization;
14 |
15 | internal static class Extensions
16 | {
17 | public static bool SetDoubleBuffered(this Control control, bool enable)
18 | {
19 | PropertyInfo doubleBufferPropertyInfo = control.GetType().GetProperty(
20 | "DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
21 |
22 | if (doubleBufferPropertyInfo != null)
23 | {
24 | bool current = (bool)doubleBufferPropertyInfo.GetValue(control);
25 |
26 | if (current != enable)
27 | {
28 | doubleBufferPropertyInfo.SetValue(control, enable, null);
29 | return true;
30 | }
31 | }
32 |
33 | return false;
34 | }
35 |
36 | public static string ToXmlNodeString(this T self)
37 | {
38 | XmlSerializerNamespaces serializer_namespace = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
39 | XmlWriterSettings serializer_settings = new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true };
40 | XmlSerializer serializer = new XmlSerializer(typeof(T));
41 |
42 | StringWriter string_writer = new StringWriter();
43 | using (XmlWriter xml_writer = XmlWriter.Create(string_writer, serializer_settings))
44 | {
45 | serializer.Serialize(xml_writer, self, serializer_namespace);
46 | return string_writer.ToString();
47 | }
48 | }
49 |
50 | public static T FromXmlNodeString(string node, string root)
51 | {
52 | XmlReaderSettings serializer_settings = new XmlReaderSettings { ValidationType = ValidationType.None };
53 | XmlSerializer serializer = new XmlSerializer(typeof(T), new XmlRootAttribute(root));
54 |
55 | using (XmlReader xml_reader = XmlReader.Create(new StringReader(node), serializer_settings))
56 | {
57 | return (T)serializer.Deserialize(xml_reader);
58 | }
59 | }
60 |
61 | public static XmlElement AsXmlElement(this XElement el)
62 | {
63 | var doc = new XmlDocument();
64 | doc.Load(el.CreateReader());
65 | return doc.DocumentElement;
66 | }
67 |
68 | public static void AppendText(this RichTextBox box, string text, Color color)
69 | {
70 | box.SelectionStart = box.TextLength;
71 | box.SelectionLength = 0;
72 |
73 | box.SelectionColor = color;
74 | box.AppendText(text);
75 | box.SelectionColor = box.ForeColor;
76 | }
77 |
78 | public static string ToJson(this object input)
79 | {
80 | var settings = new JsonSerializerSettings();
81 |
82 | settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
83 | settings.Converters.Add(new StringEnumConverter());
84 |
85 | return JsonConvert.SerializeObject(input, Newtonsoft.Json.Formatting.None, settings);
86 | }
87 |
88 | public static void SetupDataBind(this TextBox control, object instance, string prop)
89 | {
90 | control.SetupDataBind(nameof(control.Text), instance, prop);
91 | }
92 |
93 | public static void SetupDataBind(this CheckBox control, object instance, string prop)
94 | {
95 | control.SetupDataBind(nameof(control.Checked), instance, prop);
96 | }
97 |
98 | public static void SetupDataBind(this Control control, string dest, object instance, string src)
99 | {
100 | control.DataBindings.Add(new Binding(dest, instance, src));
101 | }
102 |
103 | public static void ExecuteOnMainThread(this Form form, Action task)
104 | {
105 | form.Invoke((MethodInvoker)delegate
106 | {
107 | try { task?.Invoke(); }
108 | catch (Exception ex) { Log.e("Main thread execution failed: {0}", ex.Message); }
109 | });
110 | }
111 |
112 | public static void ShiftLeft(this double[] array, double last_value = default(double))
113 | {
114 | int last_index = array.Length - 1;
115 | Array.Copy(array, 1, array, 0, last_index);
116 | array[last_index] = last_value;
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/OpenRoC/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/OpenRoC/Logger.cs:
--------------------------------------------------------------------------------
1 | namespace oroc
2 | {
3 | using log4net;
4 | using log4net.Core;
5 | using log4net.Config;
6 | using log4net.Appender;
7 |
8 | using System;
9 | using System.IO;
10 | using System.Drawing;
11 | using System.Xml.Linq;
12 | using System.Windows.Forms;
13 |
14 | class Log
15 | {
16 | public static void d(string msg) { Logger.Instance.Debug(msg); }
17 | public static void d(string fmt, params object[] args) { Logger.Instance.DebugFormat(fmt, args); }
18 | public static void w(string msg) { Logger.Instance.Warn(msg); }
19 | public static void w(string fmt, params object[] args) { Logger.Instance.WarnFormat(fmt, args); }
20 | public static void e(string msg) { Logger.Instance.Error(msg); }
21 | public static void e(string fmt, params object[] args) { Logger.Instance.ErrorFormat(fmt, args); }
22 | public static void i(string msg) { Logger.Instance.Info(msg); }
23 | public static void i(string fmt, params object[] args) { Logger.Instance.InfoFormat(fmt, args); }
24 | }
25 |
26 | internal class Logger
27 | {
28 | public static readonly ILog Instance = LogManager.GetLogger(typeof(Logger));
29 |
30 | public static void Configure(Form owner, RichTextBox logBox)
31 | {
32 | FileInfo config_file = new FileInfo(
33 | Path.Combine(Program.Directory, Properties.Resources.SettingsFileName));
34 |
35 | if (!config_file.Exists)
36 | File.WriteAllText(config_file.FullName, Properties.Resources.SettingsBaseXml);
37 |
38 | XElement phoenix_root = null;
39 |
40 | try { phoenix_root = XElement.Load(config_file.FullName); }
41 | catch (Exception ex)
42 | {
43 | Log.e("Root element cannot be loaded: {0}", ex.Message);
44 | phoenix_root = XElement.Parse(Properties.Resources.SettingsBaseXml);
45 | }
46 |
47 | if (phoenix_root == null || phoenix_root.Name != Properties.Resources.SettingsRootNode)
48 | {
49 | Log.w("Phoenix node not found. It will be created.");
50 | phoenix_root = new XElement(Properties.Resources.SettingsRootNode);
51 | }
52 |
53 | XElement log4net_root = phoenix_root.Element(Properties.Resources.SettingsLog4NetNode);
54 |
55 | if (log4net_root == null)
56 | {
57 | Log.e("Options node not found. It will be created.");
58 | log4net_root = new XElement(Properties.Resources.SettingsLog4NetNode);
59 | phoenix_root.Add(log4net_root);
60 | }
61 |
62 | XmlConfigurator.Configure(log4net_root.AsXmlElement());
63 | BasicConfigurator.Configure(new TextBoxAppender(logBox, owner));
64 |
65 | Log.d("Logger configured.");
66 | }
67 |
68 | internal class TextBoxAppender : AppenderSkeleton
69 | {
70 | private RichTextBox textBox;
71 |
72 | public TextBoxAppender(RichTextBox box, Form box_owner)
73 | {
74 | textBox = box;
75 | Threshold = Level.All;
76 | box_owner.FormClosing += (s, e) => textBox = null;
77 | }
78 |
79 | protected override void Append(LoggingEvent loggingEvent)
80 | {
81 | if (textBox == null || textBox.Disposing || textBox.IsDisposed)
82 | return;
83 |
84 | textBox.BeginInvoke((MethodInvoker)delegate
85 | {
86 | textBox.AppendText(loggingEvent.RenderedMessage + Environment.NewLine, GetLevelColor(loggingEvent.Level));
87 |
88 | if (!textBox.Visible)
89 | {
90 | textBox.SelectionStart = textBox.TextLength;
91 | textBox.ScrollToCaret();
92 | }
93 | });
94 | }
95 |
96 | static Color GetLevelColor(Level level)
97 | {
98 | if (level == Level.Error || level == Level.Critical || level == Level.Fatal)
99 | return Color.Red;
100 | else if (level == Level.Debug || level == Level.Notice)
101 | return Color.DimGray;
102 | else if (level == Level.Warn)
103 | return Color.Blue;
104 | else
105 | return Color.Black;
106 | }
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/OpenRoC/LogsDialog.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace oroc
2 | {
3 | partial class LogsDialog
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LogsDialog));
32 | this.LogTextBox = new System.Windows.Forms.RichTextBox();
33 | this.SuspendLayout();
34 | //
35 | // LogTextBox
36 | //
37 | this.LogTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
38 | this.LogTextBox.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
39 | this.LogTextBox.Location = new System.Drawing.Point(0, 0);
40 | this.LogTextBox.Name = "LogTextBox";
41 | this.LogTextBox.ReadOnly = true;
42 | this.LogTextBox.Size = new System.Drawing.Size(499, 261);
43 | this.LogTextBox.TabIndex = 0;
44 | this.LogTextBox.Text = "";
45 | this.LogTextBox.LinkClicked += new System.Windows.Forms.LinkClickedEventHandler(this.OnLogsDialogRichTextBoxLinkClicked);
46 | //
47 | // LogsDialog
48 | //
49 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
50 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
51 | this.ClientSize = new System.Drawing.Size(499, 261);
52 | this.Controls.Add(this.LogTextBox);
53 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
54 | this.Name = "LogsDialog";
55 | this.Text = "Logs";
56 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.OnLogsDialogFormClosing);
57 | this.ResumeLayout(false);
58 |
59 | }
60 |
61 | #endregion
62 |
63 | private System.Windows.Forms.RichTextBox LogTextBox;
64 | }
65 | }
--------------------------------------------------------------------------------
/OpenRoC/LogsDialog.cs:
--------------------------------------------------------------------------------
1 | namespace oroc
2 | {
3 | using System;
4 | using System.Diagnostics;
5 | using System.Windows.Forms;
6 |
7 | public partial class LogsDialog : Form
8 | {
9 | public LogsDialog()
10 | {
11 | InitializeComponent();
12 |
13 | if (LogTextBox.Handle != IntPtr.Zero)
14 | Logger.Configure(this, LogTextBox);
15 | }
16 |
17 | private void OnLogsDialogFormClosing(object sender, FormClosingEventArgs e)
18 | {
19 | if (e.CloseReason == CloseReason.UserClosing)
20 | {
21 | e.Cancel = true;
22 | Hide();
23 | }
24 | }
25 |
26 | private void OnLogsDialogRichTextBoxLinkClicked(object sender, LinkClickedEventArgs e)
27 | {
28 | using (Process.Start(e.LinkText)) { /* no-op */ }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/OpenRoC/MainDialog.cs:
--------------------------------------------------------------------------------
1 | namespace oroc
2 | {
3 | using liboroc;
4 |
5 | using System;
6 | using System.IO;
7 | using System.Windows.Forms;
8 | using System.Collections.Generic;
9 | using System.Windows.Forms.DataVisualization.Charting;
10 |
11 | public partial class MainDialog : Form
12 | {
13 | private ExecutorService screenshotService;
14 | private Metrics.Manager metricsManager;
15 | private SensuInterface sensuInterface;
16 | private ProcessDialog editProcessForm;
17 | private ProcessDialog addProcessForm;
18 | private SettingsDialog settingsForm;
19 | private AboutDialog aboutForm;
20 | private LogsDialog logsForm;
21 |
22 | private Series CpuChart;
23 | private Series GpuChart;
24 | private Series RamChart;
25 |
26 | public ProcessManager ProcessManager { get; private set; }
27 | private bool inhibitAutoCheck = false;
28 |
29 | public MainDialog()
30 | {
31 | InitializeComponent();
32 | logsForm = new LogsDialog();
33 | SetupMainDialogStatusTexts();
34 | HandleCreated += OnHandleCreated;
35 | ProcessManager = new ProcessManager();
36 | metricsManager = new Metrics.Manager();
37 | screenshotService = new ExecutorService();
38 |
39 | ProcessListView.SetDoubleBuffered(true);
40 | MetricsChart.SetDoubleBuffered(true);
41 | }
42 |
43 | private void OnHandleCreated(object sender, EventArgs e)
44 | {
45 | Log.d("Main dialog handle created.");
46 |
47 | List launchOptions = Settings.Instance.Read>
48 | (Properties.Resources.SettingsProcessListNode);
49 |
50 | Log.d("Launch options parsed. Number of launch processes: {0}", launchOptions.Count);
51 |
52 | if (Settings.Instance.IsSensuInterfaceEnabled)
53 | {
54 | SensuInterfaceUpdateTimer.Enabled = true;
55 | SensuInterfaceUpdateTimer.Tick += OnSensuInterfaceUpdateTimerTick;
56 | SetSensuInterfaceUpdateTimerInterval(Settings.Instance.SensuInterfaceTTL);
57 |
58 | sensuInterface = new SensuInterface(
59 | ProcessManager,
60 | Settings.Instance.SensuInterfaceHost,
61 | Settings.Instance.SensuInterfacePort,
62 | Settings.Instance.SensuInterfaceTTL);
63 | }
64 |
65 | launchOptions.ForEach((opt) => { ProcessManager.Add(opt); });
66 | ProcessManager.ProcessesChanged += OnProcessManagerPropertyChanged;
67 |
68 | CpuChart = MetricsChart.Series[nameof(CpuChart)];
69 | GpuChart = MetricsChart.Series[nameof(GpuChart)];
70 | RamChart = MetricsChart.Series[nameof(RamChart)];
71 | }
72 |
73 | public void SetSensuInterfaceUpdateTimerInterval(uint seconds)
74 | {
75 | int interval = (int)TimeSpan
76 | .FromSeconds(seconds * 0.8)
77 | .TotalMilliseconds;
78 |
79 | if (SensuInterfaceUpdateTimer.Interval == interval)
80 | return;
81 |
82 | Log.i("Sensu checks TTL and timeout is: {0} seconds.", seconds);
83 | Log.i("Sensu checks interval is: {0} miliseconds.", interval);
84 |
85 | SensuInterfaceUpdateTimer.Interval = interval;
86 | sensuInterface?.SetTTL(seconds);
87 | }
88 |
89 | private void OnSensuInterfaceUpdateTimerTick(object sender, EventArgs e)
90 | {
91 | Log.d("Sending Sensu checks.");
92 | sensuInterface.SendChecks();
93 | }
94 |
95 | private void OnProcessManagerPropertyChanged()
96 | {
97 | Settings.Instance.Write(Properties.Resources.SettingsProcessListNode, ProcessManager.Options);
98 | Settings.Instance.Save();
99 | }
100 |
101 | private void OnProcessListViewResize(object sender, EventArgs e)
102 | {
103 | if (ProcessListView.Columns.Count > 0)
104 | ProcessListView.AutoResizeColumn(
105 | ProcessListView.Columns.Count - 1,
106 | ColumnHeaderAutoResizeStyle.HeaderSize);
107 | }
108 |
109 | public void UpdateProcessList()
110 | {
111 | foreach (ListViewItem item in ProcessListView.Items)
112 | if (!ProcessManager.Contains(item.Text))
113 | item.Remove();
114 |
115 | ProcessManager.Runners.ForEach(p =>
116 | {
117 | if (ProcessListView.Items.ContainsKey(p.ProcessOptions.Path))
118 | {
119 | ProcessListView.Items[p.ProcessOptions.Path].Checked = p.State != ProcessRunner.Status.Disabled;
120 | ProcessListView.Items[p.ProcessOptions.Path].SubItems[1].Text = p.GetStateString();
121 | }
122 | else
123 | {
124 | ListViewItem item = new ListViewItem();
125 |
126 | item.Checked = p.State != ProcessRunner.Status.Disabled;
127 | item.Text = p.ProcessOptions.Path;
128 | item.Name = p.ProcessOptions.Path;
129 | item.SubItems.Add(p.State.ToString());
130 |
131 | p.StateChanged += () => { Log.i("Process {0} changed state to: {1}", p.ProcessOptions.Path, p.State); };
132 | p.OptionsChanged += () => { Log.d("Process changed options to: {0}", p.ProcessOptions.ToJson()); };
133 | p.ProcessCrashed += () =>
134 | {
135 | Log.e("Process {0} crashed or stopped.", p.ProcessOptions.Path);
136 |
137 | if (p.ProcessOptions.ScreenShotEnabled)
138 | TakeScreenShot();
139 | };
140 |
141 | ProcessListView.Items.Add(item);
142 | }
143 | });
144 | }
145 |
146 | private void OnSettingsButtonClick(object sender, EventArgs e)
147 | {
148 | HandleDialogRequest(ref settingsForm);
149 | }
150 |
151 | private void OnAddButtonClick(object sender, EventArgs e)
152 | {
153 | HandleDialogRequest(ref addProcessForm);
154 | }
155 |
156 | private void OnAboutButtonClick(object sender, EventArgs e)
157 | {
158 | HandleDialogRequest(ref aboutForm);
159 | }
160 |
161 | private void OnLogButtonClick(object sender, EventArgs e)
162 | {
163 | HandleDialogRequest(ref logsForm);
164 | }
165 |
166 | private void HandleDialogRequest(ref T host) where T : Form, new()
167 | {
168 | if (host == null || host.IsDisposed)
169 | {
170 | host = new T();
171 | host.Owner = this;
172 |
173 | if (host.Handle == IntPtr.Zero)
174 | Log.d("Forced handle to be created.");
175 | }
176 |
177 | if (!host.Visible)
178 | {
179 | host.Show();
180 | host.Focus();
181 | }
182 | else
183 | {
184 | host.Focus();
185 | return;
186 | }
187 | }
188 |
189 | private void OnProcessListViewItemChecked(object sender, ItemCheckedEventArgs e)
190 | {
191 | if (e.Item.Checked == (ProcessManager.Get(e.Item.Text).State != ProcessRunner.Status.Disabled))
192 | return;
193 |
194 | if (e.Item.Checked)
195 | ProcessManager.Get(e.Item.Text).RestoreState();
196 | else
197 | ProcessManager.Get(e.Item.Text).State = ProcessRunner.Status.Disabled;
198 | }
199 |
200 | private void OnMainDialogUpdateTimerTick(object sender, EventArgs e)
201 | {
202 | ProcessManager.Runners.ForEach(p => p.Monitor());
203 | metricsManager.Update();
204 | UpdateProcessList();
205 |
206 | CpuChart?.Points.DataBindY(metricsManager.CpuSamples);
207 | GpuChart?.Points.DataBindY(metricsManager.GpuSamples);
208 | RamChart?.Points.DataBindY(metricsManager.RamSamples);
209 | }
210 |
211 | #region StatusBar text feature
212 |
213 | public void SetStatusBarText(Control control, string text)
214 | {
215 | control.MouseEnter += (s, e) => { StatusText.Text = text; };
216 | control.MouseLeave += (s, e) => { ResetStatusBarText(); };
217 | }
218 |
219 | public void SetStatusBarText(ToolStripItem control, string text)
220 | {
221 | control.MouseEnter += (s, e) => { StatusText.Text = text; };
222 | control.MouseLeave += (s, e) => { ResetStatusBarText(); };
223 | }
224 |
225 | public void ResetStatusBarText()
226 | {
227 | StatusText.Text = Properties.Resources.StatusTextDefaultString;
228 | }
229 |
230 | private void SetupMainDialogStatusTexts()
231 | {
232 | ResetStatusBarText();
233 | SetStatusBarText(AddButton, "Add a new process to monitor.");
234 | SetStatusBarText(DeleteButton, "Delete selected processes.");
235 | SetStatusBarText(SettingsButton, "Adjust OpenRoC settings.");
236 | SetStatusBarText(LogsButton, "Open logging history window.");
237 | SetStatusBarText(AboutButton, "Read about OpenRoC project.");
238 | SetStatusBarText(ContextMenuAddButton, "Add a new process.");
239 | SetStatusBarText(ContextMenuEditButton, "Edit the process.");
240 | SetStatusBarText(ContextMenuDeleteButton, "Delete selected processes.");
241 | SetStatusBarText(ContextMenuDisableButton, "Disable selected processes.");
242 | SetStatusBarText(ContextMenuStart, "Run selected processes if they are stopped.");
243 | SetStatusBarText(ContextMenuStop, "Stop selected processes if they are running.");
244 | SetStatusBarText(ContextMenuShow, "Attempt to bring the main Window of the selected processes to top.");
245 | SetStatusBarText(MetricsChart, "Overall performance graph of this machine over past few seconds.");
246 | }
247 |
248 | #endregion
249 |
250 | #region Start minimized support
251 |
252 | protected override void SetVisibleCore(bool value)
253 | {
254 | if (!IsHandleCreated)
255 | {
256 | CreateHandle();
257 | base.SetVisibleCore(!Settings.Instance.IsStartMinimizedEnabled);
258 | }
259 | else
260 | {
261 | base.SetVisibleCore(value);
262 | }
263 | }
264 |
265 | #endregion
266 |
267 | #region Taskbar right-click context menu event callbacks
268 |
269 | private void OnTaskbarContextMenuToggleViewButtonClick(object sender, EventArgs e)
270 | {
271 | if (e is MouseEventArgs && (e as MouseEventArgs).Button != MouseButtons.Left)
272 | return;
273 |
274 | Visible = !Visible;
275 |
276 | if (Visible)
277 | Focus();
278 | }
279 |
280 | private void OnTaskbarContextMenuExitButtonClick(object sender, EventArgs e)
281 | {
282 | Close();
283 | }
284 |
285 | #endregion
286 |
287 | #region Process right-click context menu event callbacks
288 |
289 | private void OnContextMenuEditButtonClick(object sender, EventArgs e)
290 | {
291 | if (ProcessListView.FocusedItem == null || ProcessListView.SelectedItems.Count == 0)
292 | {
293 | MessageBox.Show(
294 | "Please select a Process to edit.",
295 | "No Process selected",
296 | MessageBoxButtons.OK,
297 | MessageBoxIcon.Warning);
298 |
299 | return;
300 | }
301 |
302 | ProcessRunner process = ProcessManager.Get(ProcessListView.FocusedItem.Text);
303 |
304 | if (editProcessForm == null || editProcessForm.IsDisposed)
305 | {
306 | editProcessForm = new ProcessDialog(process.ProcessOptions);
307 | editProcessForm.Owner = this;
308 | }
309 |
310 | if (!editProcessForm.Visible)
311 | editProcessForm.Show();
312 | else
313 | editProcessForm.Focus();
314 | }
315 |
316 | private void OnContextMenuDeleteButtonClick(object sender, EventArgs e)
317 | {
318 | if (ProcessListView.SelectedItems.Count == 0)
319 | {
320 | MessageBox.Show(
321 | "Please select Processes to delete.",
322 | "No Processes selected",
323 | MessageBoxButtons.OK,
324 | MessageBoxIcon.Warning);
325 |
326 | return;
327 | }
328 |
329 | foreach (ListViewItem item in ProcessListView.SelectedItems)
330 | ProcessManager.Remove(item.Text);
331 |
332 | UpdateProcessList();
333 | }
334 |
335 | private void OnContextMenuDisableButtonClick(object sender, EventArgs e)
336 | {
337 | if (ProcessListView.SelectedItems.Count == 0)
338 | {
339 | MessageBox.Show(
340 | "Please select Processes to disable.",
341 | "No Processes selected",
342 | MessageBoxButtons.OK,
343 | MessageBoxIcon.Warning);
344 |
345 | return;
346 | }
347 |
348 | foreach (ListViewItem item in ProcessListView.SelectedItems)
349 | ProcessManager.Get(item.Text).State = ProcessRunner.Status.Disabled;
350 | }
351 |
352 | private void OnContextMenuShowClick(object sender, EventArgs e)
353 | {
354 | if (ProcessListView.SelectedItems.Count == 0)
355 | {
356 | MessageBox.Show(
357 | "Please select Processes to show.",
358 | "No Processes selected",
359 | MessageBoxButtons.OK,
360 | MessageBoxIcon.Warning);
361 |
362 | return;
363 | }
364 |
365 | foreach (ListViewItem item in ProcessListView.SelectedItems)
366 | ProcessManager.Get(item.Text).BringToFront();
367 | }
368 |
369 | private void OnContextMenuStopClick(object sender, EventArgs e)
370 | {
371 | if (ProcessListView.SelectedItems.Count == 0)
372 | {
373 | MessageBox.Show(
374 | "Please select Processes to stop.",
375 | "No Processes selected",
376 | MessageBoxButtons.OK,
377 | MessageBoxIcon.Warning);
378 |
379 | return;
380 | }
381 |
382 | foreach (ListViewItem item in ProcessListView.SelectedItems)
383 | ProcessManager.Get(item.Text).Stop();
384 | }
385 |
386 | private void OnContextMenuStartClick(object sender, EventArgs e)
387 | {
388 | if (ProcessListView.SelectedItems.Count == 0)
389 | {
390 | MessageBox.Show(
391 | "Please select Processes to start.",
392 | "No Processes selected",
393 | MessageBoxButtons.OK,
394 | MessageBoxIcon.Warning);
395 |
396 | return;
397 | }
398 |
399 | foreach (ListViewItem item in ProcessListView.SelectedItems)
400 | ProcessManager.Get(item.Text).Start();
401 | }
402 |
403 | #endregion
404 |
405 | #region Drag and drop file support
406 |
407 | private void OnProcessListViewDragDrop(object sender, DragEventArgs e)
408 | {
409 | string[] dragged_files = e.Data.GetData(DataFormats.FileDrop, false) as string[];
410 |
411 | if (dragged_files == null)
412 | return;
413 |
414 | foreach (string dragged_file in dragged_files)
415 | {
416 | if (!ProcessManager.Contains(dragged_file))
417 | {
418 | ProcessOptions opts = new ProcessOptions();
419 |
420 | opts.Path = dragged_file;
421 | opts.WorkingDirectory = Path.GetDirectoryName(opts.Path);
422 |
423 | ProcessManager.Add(opts);
424 | }
425 | }
426 |
427 | UpdateProcessList();
428 | }
429 |
430 | private void OnProcessListViewDragEnter(object sender, DragEventArgs e)
431 | {
432 | e.Effect = DragDropEffects.Copy;
433 | }
434 |
435 | #endregion
436 |
437 | #region Disable auto-check feature of ListView on double-click
438 |
439 | private void OnProcessListViewMouseUp(object sender, MouseEventArgs e)
440 | {
441 | inhibitAutoCheck = false;
442 | }
443 |
444 | private void OnProcessListViewMouseDown(object sender, MouseEventArgs e)
445 | {
446 | inhibitAutoCheck = true;
447 | }
448 |
449 | private void OnProcessListViewItemCheck(object sender, ItemCheckEventArgs e)
450 | {
451 | if (inhibitAutoCheck)
452 | e.NewValue = e.CurrentValue;
453 | }
454 |
455 | #endregion
456 |
457 | #region ScreenShot support
458 |
459 | public void TakeScreenShot()
460 | {
461 | if (!Directory.Exists(Program.ScreenShotDirectory))
462 | Directory.CreateDirectory(Program.ScreenShotDirectory);
463 |
464 | Log.i("ScreenShot queued for execution.");
465 |
466 | screenshotService.Accept(() =>
467 | {
468 | Log.i("ScreenShot is being taken...");
469 |
470 | using (var picture = Pranas.ScreenshotCapture.TakeScreenshot())
471 | {
472 | string name = Path.Combine(
473 | Program.ScreenShotDirectory,
474 | string.Format("{0}.png", DateTime.Now.ToFileTime()));
475 |
476 | picture.Save(name);
477 |
478 | Log.i("ScreenShot is saved to: {0}", name);
479 | }
480 | });
481 | }
482 |
483 | #endregion
484 |
485 | private void DisposeAddedComponents()
486 | {
487 | screenshotService?.Dispose();
488 | metricsManager?.Dispose();
489 | ProcessManager?.Dispose();
490 | sensuInterface?.Dispose();
491 | editProcessForm?.Dispose();
492 | addProcessForm?.Dispose();
493 | settingsForm?.Dispose();
494 | aboutForm?.Dispose();
495 | logsForm?.Dispose();
496 |
497 | screenshotService = null;
498 | metricsManager = null;
499 | ProcessManager = null;
500 | sensuInterface = null;
501 | editProcessForm = null;
502 | addProcessForm = null;
503 | settingsForm = null;
504 | aboutForm = null;
505 | logsForm = null;
506 | }
507 | }
508 | }
509 |
--------------------------------------------------------------------------------
/OpenRoC/Metrics/Collector.cs:
--------------------------------------------------------------------------------
1 | namespace oroc.Metrics
2 | {
3 | using System;
4 | using System.Linq;
5 | using System.Collections.Generic;
6 |
7 | using OpenHardwareMonitor.Hardware;
8 |
9 | public abstract class ICollector
10 | {
11 | protected readonly IHardware Hardware;
12 | protected readonly List Sensors;
13 | public double CurrentSample { get; private set; } = 0.0d;
14 |
15 | protected ICollector(IHardware hardware)
16 | {
17 | Hardware = hardware;
18 | Sensors = new List();
19 |
20 | if (Hardware != null)
21 | {
22 | Hardware.SensorAdded += (sensor) =>
23 | {
24 | Log.i("Sensor {0} is added.", sensor.Name);
25 |
26 | if (Sensors != null)
27 | {
28 | if (sensor.SensorType == SensorType.Load)
29 | Sensors.Add(sensor);
30 | }
31 | };
32 |
33 | Hardware.SensorRemoved += (sensor) =>
34 | {
35 | Log.i("Sensor {0} is removed.", sensor.Name);
36 |
37 | if (Sensors != null)
38 | {
39 | if (sensor.SensorType == SensorType.Load)
40 | Sensors.Remove(sensor);
41 | }
42 | };
43 |
44 | foreach (ISensor sensor in Hardware.Sensors)
45 | {
46 | if (sensor.SensorType == SensorType.Load)
47 | {
48 | Sensors.Add(sensor);
49 | }
50 | }
51 | }
52 | }
53 |
54 | public void Update()
55 | {
56 | if (Hardware == null || Sensors.Count == 0)
57 | return;
58 |
59 | Hardware.Update();
60 |
61 | foreach (IHardware subhardware in Hardware.SubHardware)
62 | subhardware.Update();
63 |
64 | try
65 | {
66 | CurrentSample = Sensors
67 | .Where(sensor => sensor.Value.HasValue && sensor.Value.Value > 0)
68 | .Average(sensor => sensor.Value.Value)
69 | / 100d;
70 | }
71 | catch (InvalidOperationException) { /* no samples this tick */ }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/OpenRoC/Metrics/CpuCollector.cs:
--------------------------------------------------------------------------------
1 | namespace oroc.Metrics
2 | {
3 | using OpenHardwareMonitor.Hardware;
4 |
5 | public class CpuCollector : ICollector
6 | {
7 | public CpuCollector(Computer computer)
8 | : base(GetFirstCpu(computer))
9 | { /* no-op */ }
10 |
11 | private static IHardware GetFirstCpu(Computer computer)
12 | {
13 | IHardware defaultHardware = null;
14 |
15 | foreach (IHardware hardwareItem in computer.Hardware)
16 | {
17 | if (hardwareItem.HardwareType == HardwareType.CPU)
18 | {
19 | defaultHardware = hardwareItem;
20 | }
21 | }
22 |
23 | return defaultHardware;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/OpenRoC/Metrics/GpuCollector.cs:
--------------------------------------------------------------------------------
1 | namespace oroc.Metrics
2 | {
3 | using OpenHardwareMonitor.Hardware;
4 |
5 | public class GpuCollector : ICollector
6 | {
7 | public GpuCollector(Computer computer)
8 | : base(GetFirstGpu(computer))
9 | { /* no-op */ }
10 |
11 | private static IHardware GetFirstGpu(Computer computer)
12 | {
13 | IHardware defaultHardware = null;
14 |
15 | foreach (IHardware hardwareItem in computer.Hardware)
16 | {
17 | if (hardwareItem.HardwareType == HardwareType.GpuAti ||
18 | hardwareItem.HardwareType == HardwareType.GpuNvidia)
19 | {
20 | defaultHardware = hardwareItem;
21 | }
22 | }
23 |
24 | return defaultHardware;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/OpenRoC/Metrics/Manager.cs:
--------------------------------------------------------------------------------
1 | namespace oroc.Metrics
2 | {
3 | using liboroc;
4 |
5 | using System;
6 | using System.Linq;
7 |
8 | using OpenHardwareMonitor.Hardware;
9 |
10 | public class Manager : IDisposable
11 | {
12 | private Computer computer;
13 | private ICollector cpuCollector;
14 | private ICollector gpuCollector;
15 | private ICollector ramCollector;
16 | private ExecutorService setupService;
17 | private volatile bool setupFinished;
18 |
19 | public double[] CpuSamples { get; private set; }
20 |
21 | public double[] GpuSamples { get; private set; }
22 |
23 | public double[] RamSamples { get; private set; }
24 |
25 | public Manager()
26 | {
27 | setupService = new ExecutorService();
28 | setupFinished = false;
29 |
30 | var initial_sensor_value = 0.0d;
31 | var initial_sensor_count = 50;
32 |
33 | CpuSamples = new double[initial_sensor_count];
34 | CpuSamples = Enumerable.Repeat(initial_sensor_value, initial_sensor_count).ToArray();
35 |
36 | GpuSamples = new double[initial_sensor_count];
37 | GpuSamples = Enumerable.Repeat(initial_sensor_value, initial_sensor_count).ToArray();
38 |
39 | RamSamples = new double[initial_sensor_count];
40 | RamSamples = Enumerable.Repeat(initial_sensor_value, initial_sensor_count).ToArray();
41 |
42 | setupService.Accept(() =>
43 | {
44 | computer = new Computer
45 | {
46 | CPUEnabled = true,
47 | GPUEnabled = true,
48 | RAMEnabled = true,
49 | };
50 |
51 | computer.Open();
52 |
53 | cpuCollector = new CpuCollector(computer);
54 | gpuCollector = new GpuCollector(computer);
55 | ramCollector = new RamCollector(computer);
56 |
57 | setupFinished = true;
58 | });
59 | }
60 |
61 | public void Update()
62 | {
63 | if (!setupFinished)
64 | return;
65 |
66 | cpuCollector.Update();
67 | gpuCollector.Update();
68 | ramCollector.Update();
69 |
70 | CpuSamples.ShiftLeft(cpuCollector.CurrentSample);
71 | GpuSamples.ShiftLeft(gpuCollector.CurrentSample);
72 | RamSamples.ShiftLeft(ramCollector.CurrentSample);
73 | }
74 |
75 | #region IDisposable Support
76 | public bool IsDisposed { get; private set; } = false;
77 |
78 | protected virtual void Dispose(bool disposing)
79 | {
80 | if (!IsDisposed)
81 | {
82 | IsDisposed = true;
83 |
84 | if (disposing)
85 | {
86 | setupService?.Dispose();
87 | computer?.Close();
88 | }
89 |
90 | setupService = null;
91 | computer = null;
92 | }
93 | }
94 |
95 | public void Dispose()
96 | {
97 | Dispose(true);
98 | }
99 | #endregion
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/OpenRoC/Metrics/RamCollector.cs:
--------------------------------------------------------------------------------
1 | namespace oroc.Metrics
2 | {
3 | using OpenHardwareMonitor.Hardware;
4 |
5 | public class RamCollector : ICollector
6 | {
7 | public RamCollector(Computer computer)
8 | : base(GetFirstRam(computer))
9 | { /* no-op */ }
10 |
11 | private static IHardware GetFirstRam(Computer computer)
12 | {
13 | IHardware defaultHardware = null;
14 |
15 | foreach (IHardware hardwareItem in computer.Hardware)
16 | {
17 | if (hardwareItem.HardwareType == HardwareType.RAM)
18 | {
19 | defaultHardware = hardwareItem;
20 | }
21 | }
22 |
23 | return defaultHardware;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/OpenRoC/OpenRoC.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {374DFCEE-DEEA-4D48-958E-0C8F64E9FCF6}
8 | WinExe
9 | Properties
10 | oroc
11 | OpenRoC
12 | v4.5.2
13 | 512
14 | true
15 |
16 |
17 |
18 |
19 | AnyCPU
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 | true
28 | false
29 |
30 |
31 | AnyCPU
32 | pdbonly
33 | true
34 | bin\Release\
35 | TRACE
36 | prompt
37 | 4
38 | false
39 | true
40 |
41 |
42 | oroc.Program
43 |
44 |
45 | phoenix.ico
46 |
47 |
48 |
49 |
50 | packages\log4net.2.0.5\lib\net45-full\log4net.dll
51 | True
52 |
53 |
54 | packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
55 | True
56 |
57 |
58 | packages\OpenHardwareMonitor.0.7.1\lib\net40\OpenHardwareMonitorLib.dll
59 | True
60 |
61 |
62 | packages\Pranas.ScreenshotCapture.1.0.11\lib\net40\Pranas.ScreenshotCapture.dll
63 | True
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | Form
77 |
78 |
79 | AboutDialog.cs
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | Form
90 |
91 |
92 | ProcessDialog.cs
93 |
94 |
95 | Form
96 |
97 |
98 | LogsDialog.cs
99 |
100 |
101 | Form
102 |
103 |
104 | MainDialog.cs
105 |
106 |
107 |
108 |
109 |
110 |
111 | Form
112 |
113 |
114 | SettingsDialog.cs
115 |
116 |
117 | AboutDialog.cs
118 |
119 |
120 | ProcessDialog.cs
121 |
122 |
123 | LogsDialog.cs
124 |
125 |
126 | MainDialog.cs
127 |
128 |
129 | ResXFileCodeGenerator
130 | Resources.Designer.cs
131 | Designer
132 |
133 |
134 | True
135 | Resources.resx
136 | True
137 |
138 |
139 | SettingsDialog.cs
140 |
141 |
142 |
143 | SettingsSingleFileGenerator
144 | Settings.Designer.cs
145 |
146 |
147 | True
148 | Settings.settings
149 | True
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 | {90c91845-e5ae-42d2-8cad-e52564c344d0}
163 | libOpenRoC
164 |
165 |
166 |
167 |
168 |
169 |
170 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
171 |
172 |
173 |
174 |
181 |
--------------------------------------------------------------------------------
/OpenRoC/OpenRoC.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.24720.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRoC", "OpenRoC.csproj", "{374DFCEE-DEEA-4D48-958E-0C8F64E9FCF6}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "libOpenRoC", "..\libOpenRoC\libOpenRoC.csproj", "{90C91845-E5AE-42D2-8CAD-E52564C344D0}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testOpenRoC", "..\testOpenRoC\testOpenRoC.csproj", "{67901A36-B033-42D1-9651-02E1535FD389}"
11 | ProjectSection(ProjectDependencies) = postProject
12 | {AB679701-4781-4AE5-A484-7FDBAB6C0E48} = {AB679701-4781-4AE5-A484-7FDBAB6C0E48}
13 | EndProjectSection
14 | EndProject
15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testProcessWindowed", "testProcessWindowed\testProcessWindowed.csproj", "{AB679701-4781-4AE5-A484-7FDBAB6C0E48}"
16 | EndProject
17 | Global
18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
19 | Debug|Any CPU = Debug|Any CPU
20 | Release|Any CPU = Release|Any CPU
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {374DFCEE-DEEA-4D48-958E-0C8F64E9FCF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {374DFCEE-DEEA-4D48-958E-0C8F64E9FCF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {374DFCEE-DEEA-4D48-958E-0C8F64E9FCF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
26 | {374DFCEE-DEEA-4D48-958E-0C8F64E9FCF6}.Release|Any CPU.Build.0 = Release|Any CPU
27 | {90C91845-E5AE-42D2-8CAD-E52564C344D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
28 | {90C91845-E5AE-42D2-8CAD-E52564C344D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
29 | {90C91845-E5AE-42D2-8CAD-E52564C344D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {90C91845-E5AE-42D2-8CAD-E52564C344D0}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {67901A36-B033-42D1-9651-02E1535FD389}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
32 | {67901A36-B033-42D1-9651-02E1535FD389}.Debug|Any CPU.Build.0 = Debug|Any CPU
33 | {67901A36-B033-42D1-9651-02E1535FD389}.Release|Any CPU.ActiveCfg = Release|Any CPU
34 | {67901A36-B033-42D1-9651-02E1535FD389}.Release|Any CPU.Build.0 = Release|Any CPU
35 | {AB679701-4781-4AE5-A484-7FDBAB6C0E48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36 | {AB679701-4781-4AE5-A484-7FDBAB6C0E48}.Debug|Any CPU.Build.0 = Debug|Any CPU
37 | {AB679701-4781-4AE5-A484-7FDBAB6C0E48}.Release|Any CPU.ActiveCfg = Release|Any CPU
38 | {AB679701-4781-4AE5-A484-7FDBAB6C0E48}.Release|Any CPU.Build.0 = Release|Any CPU
39 | EndGlobalSection
40 | GlobalSection(SolutionProperties) = preSolution
41 | HideSolutionNode = FALSE
42 | EndGlobalSection
43 | EndGlobal
44 |
--------------------------------------------------------------------------------
/OpenRoC/ProcessDialog.cs:
--------------------------------------------------------------------------------
1 | namespace oroc
2 | {
3 | using liboroc;
4 |
5 | using System;
6 | using System.IO;
7 | using System.Diagnostics;
8 | using System.Windows.Forms;
9 |
10 | public partial class ProcessDialog : Form
11 | {
12 | public ProcessOptions Options;
13 | private OpenFileDialog filePicker;
14 | private FolderBrowserDialog folderPicker;
15 |
16 | public ProcessDialog()
17 | : this(new ProcessOptions())
18 | { /* no-op */ }
19 |
20 | public ProcessDialog(ProcessOptions opts)
21 | {
22 | InitializeComponent();
23 |
24 | Options = opts;
25 | filePicker = new OpenFileDialog();
26 | folderPicker = new FolderBrowserDialog();
27 |
28 | HandleCreated += OnProcessDialogHandleCreated;
29 | }
30 |
31 | private void OnProcessDialogHandleCreated(object sender, EventArgs e)
32 | {
33 | if (!(Owner is MainDialog))
34 | {
35 | Log.e("Owner of Process Window is not the right type.");
36 | return;
37 | }
38 |
39 | MainDialog main_dialog = Owner as MainDialog;
40 |
41 | main_dialog.SetStatusBarText(ProcessOptionPathControl, "Path to process executable. Only executables (*.exe) are valid.");
42 | main_dialog.SetStatusBarText(ProcessOptionWorkingDirectoryControl, "Working directory of the chosen process executable");
43 |
44 | main_dialog.SetStatusBarText(ProcessOptionCrashedIfNotRunningControl, "Assume process is crashed if it's not running (no effect when monitoring is disabled).");
45 | main_dialog.SetStatusBarText(ProcessOptionCrashedIfUnresponsiveControl, "Assume crash if main Window is unresponsive (no effect when monitoring is disabled).");
46 | main_dialog.SetStatusBarText(ProcessOptionDoubleCheckEnabledControl, "Enable crash double check.");
47 | main_dialog.SetStatusBarText(ProcessOptionDoubleCheckDurationControl, "Crash double check duration. After a crash, double check before killing the process");
48 | main_dialog.SetStatusBarText(ProcessOptionGracePeriodEnabledControl, "Enable a grace period between relaunches of the process.");
49 | main_dialog.SetStatusBarText(ProcessOptionGracePeriodDurationControl, "Grace period duration. After a crash, a restart happens when grace period ends.");
50 |
51 | main_dialog.SetStatusBarText(ProcessOptionPreLaunchScriptEnabledControl, "Enable before launch script execution.");
52 | main_dialog.SetStatusBarText(ProcessOptionPreLaunchScriptPathControl, "Execute and wait for this script before starting the process.");
53 |
54 | main_dialog.SetStatusBarText(ProcessOptionAggressiveCleanupEnabledControl, "Enable aggressive cleanup after process crashes.");
55 | main_dialog.SetStatusBarText(ProcessOptionPostCrashScriptEnabledControl, "Enable after crash script execution.");
56 | main_dialog.SetStatusBarText(ProcessOptionPostCrashScriptPathControl, "Execute and wait for this script after process crashed.");
57 |
58 | main_dialog.SetStatusBarText(ProcessOptionScreenshotEnabledControl, "Take a screen-shot of the main display when process crashes.");
59 | main_dialog.SetStatusBarText(ProcessOptionAlwaysOnTopEnabledControl, "Keep main Window on-top (aggressive, conflicts with other always-on-top Windows).");
60 | main_dialog.SetStatusBarText(ProcessOptionCommandLineEnabledControl, "Enable passing command line to the process.");
61 | main_dialog.SetStatusBarText(ProcessOptionCommandLineControl, "Command line to pass to the process executable.");
62 | main_dialog.SetStatusBarText(ProcessOptionEnvironmentVariablesEnabledControl, "Enable merging environment variables.");
63 | main_dialog.SetStatusBarText(ProcessOptionEnvironmentVariablesControl, "Environment variable list. Format: var1=val1;var2=val2;...");
64 |
65 | main_dialog.SetStatusBarText(StartupStateStoppedControl, "Stop the process when it is added to the process list for the first time.");
66 | main_dialog.SetStatusBarText(StartupStateRunningControl, "Run the process when it is added to the process list for the first time.");
67 | main_dialog.SetStatusBarText(StartupStateDisabledControl, "Do not monitor the process when it is added to the process list for the first time.");
68 |
69 | SetupDataBindings();
70 | SyncCheckedStates();
71 | }
72 |
73 | private void SetupDataBindings()
74 | {
75 | ProcessOptionPathControl.SetupDataBind(Options, nameof(Options.Path));
76 | ProcessOptionWorkingDirectoryControl.SetupDataBind(Options, nameof(Options.WorkingDirectory));
77 |
78 | ProcessOptionCrashedIfNotRunningControl.SetupDataBind(Options, nameof(Options.CrashedIfNotRunning));
79 | ProcessOptionCrashedIfUnresponsiveControl.SetupDataBind(Options, nameof(Options.CrashedIfUnresponsive));
80 | ProcessOptionDoubleCheckEnabledControl.SetupDataBind(Options, nameof(Options.DoubleCheckEnabled));
81 | ProcessOptionDoubleCheckDurationControl.SetupDataBind(Options, nameof(Options.DoubleCheckDuration));
82 | ProcessOptionGracePeriodEnabledControl.SetupDataBind(Options, nameof(Options.GracePeriodEnabled));
83 | ProcessOptionGracePeriodDurationControl.SetupDataBind(Options, nameof(Options.GracePeriodDuration));
84 |
85 | ProcessOptionPreLaunchScriptEnabledControl.SetupDataBind(Options, nameof(Options.PreLaunchScriptEnabled));
86 | ProcessOptionPreLaunchScriptPathControl.SetupDataBind(Options, nameof(Options.PreLaunchScriptPath));
87 |
88 | ProcessOptionAggressiveCleanupEnabledControl.SetupDataBind(Options, nameof(Options.AggressiveCleanupEnabled));
89 | ProcessOptionPostCrashScriptEnabledControl.SetupDataBind(Options, nameof(Options.PostCrashScriptEnabled));
90 | ProcessOptionPostCrashScriptPathControl.SetupDataBind(Options, nameof(Options.PostCrashScriptPath));
91 |
92 | ProcessOptionScreenshotEnabledControl.SetupDataBind(Options, nameof(Options.ScreenShotEnabled));
93 | ProcessOptionAlwaysOnTopEnabledControl.SetupDataBind(Options, nameof(Options.AlwaysOnTopEnabled));
94 | ProcessOptionCommandLineEnabledControl.SetupDataBind(Options, nameof(Options.CommandLineEnabled));
95 | ProcessOptionCommandLineControl.SetupDataBind(Options, nameof(Options.CommandLine));
96 | ProcessOptionEnvironmentVariablesEnabledControl.SetupDataBind(Options, nameof(Options.EnvironmentVariablesEnabled));
97 | ProcessOptionEnvironmentVariablesControl.SetupDataBind(Options, nameof(Options.EnvironmentVariables));
98 | }
99 |
100 | private void OnProcessOptionsSaveButtonClick(object sender, EventArgs e)
101 | {
102 | MainDialog main = Owner as MainDialog;
103 |
104 | if (main != null)
105 | {
106 | if (main.ProcessManager.Contains(Options.Path))
107 | main.ProcessManager.Get(Options.Path).ProcessOptions = Options;
108 | else
109 | main.ProcessManager.Add(Options);
110 |
111 | main.UpdateProcessList();
112 | }
113 |
114 | Close();
115 | }
116 |
117 | private void OnProcessOptionsCancelButtonClick(object sender, EventArgs e)
118 | {
119 | Close();
120 | }
121 |
122 | private void OnStartupStateRadioGroupCheckedChanged(object sender, EventArgs e)
123 | {
124 | if (StartupStateStoppedControl.Checked)
125 | Options.InitialStateEnumValue = ProcessRunner.Status.Stopped;
126 | else if (StartupStateRunningControl.Checked)
127 | Options.InitialStateEnumValue = ProcessRunner.Status.Running;
128 | else if (StartupStateDisabledControl.Checked)
129 | Options.InitialStateEnumValue = ProcessRunner.Status.Disabled;
130 | }
131 |
132 | private void SyncCheckedStates()
133 | {
134 | if (Options.InitialStateEnumValue == ProcessRunner.Status.Stopped)
135 | StartupStateStoppedControl.Checked = true;
136 | else if (Options.InitialStateEnumValue == ProcessRunner.Status.Running)
137 | StartupStateRunningControl.Checked = true;
138 | else if (Options.InitialStateEnumValue == ProcessRunner.Status.Disabled)
139 | StartupStateDisabledControl.Checked = true;
140 |
141 | OnStartupStateRadioGroupCheckedChanged(this, null);
142 | OnProcessOptionDoubleCheckEnabledControlCheckedChanged(this, null);
143 | OnProcessOptionGracePeriodEnabledControlCheckedChanged(this, null);
144 | OnProcessOptionPreLaunchScriptEnabledControlCheckedChanged(this, null);
145 | OnProcessOptionPostCrashScriptEnabledControlCheckedChanged(this, null);
146 | OnProcessOptionCommandLineEnabledControlCheckedChanged(this, null);
147 | OnProcessOptionEnvironmentVariablesEnabledControlCheckedChanged(this, null);
148 | }
149 |
150 | private void OnProcessOptionDoubleCheckEnabledControlCheckedChanged(object sender, EventArgs e)
151 | {
152 | CheckBox checkbox = ProcessOptionDoubleCheckEnabledControl;
153 |
154 | if (ProcessOptionDoubleCheckDurationControl.Enabled != checkbox.Checked)
155 | ProcessOptionDoubleCheckDurationControl.Enabled = checkbox.Checked;
156 | }
157 |
158 | private void OnProcessOptionGracePeriodEnabledControlCheckedChanged(object sender, EventArgs e)
159 | {
160 | CheckBox checkbox = ProcessOptionGracePeriodEnabledControl;
161 |
162 | if (ProcessOptionGracePeriodDurationControl.Enabled != checkbox.Checked)
163 | ProcessOptionGracePeriodDurationControl.Enabled = checkbox.Checked;
164 | }
165 |
166 | private void OnProcessOptionPreLaunchScriptEnabledControlCheckedChanged(object sender, EventArgs e)
167 | {
168 | CheckBox checkbox = ProcessOptionPreLaunchScriptEnabledControl;
169 |
170 | if (ProcessOptionPreLaunchScriptPathControl.Enabled != checkbox.Checked)
171 | ProcessOptionPreLaunchScriptPathControl.Enabled = checkbox.Checked;
172 |
173 | if (ProcessOptionPreLaunchScriptButton.Enabled != checkbox.Checked)
174 | ProcessOptionPreLaunchScriptButton.Enabled = checkbox.Checked;
175 | }
176 |
177 | private void OnProcessOptionPostCrashScriptEnabledControlCheckedChanged(object sender, EventArgs e)
178 | {
179 | CheckBox checkbox = ProcessOptionPostCrashScriptEnabledControl;
180 |
181 | if (ProcessOptionPostCrashScriptPathControl.Enabled != checkbox.Checked)
182 | ProcessOptionPostCrashScriptPathControl.Enabled = checkbox.Checked;
183 |
184 | if (ProcessOptionPostCrashScriptButton.Enabled != checkbox.Checked)
185 | ProcessOptionPostCrashScriptButton.Enabled = checkbox.Checked;
186 | }
187 |
188 | private void OnProcessOptionCommandLineEnabledControlCheckedChanged(object sender, EventArgs e)
189 | {
190 | CheckBox checkbox = ProcessOptionCommandLineEnabledControl;
191 |
192 | if (ProcessOptionCommandLineControl.Enabled != checkbox.Checked)
193 | ProcessOptionCommandLineControl.Enabled = checkbox.Checked;
194 | }
195 |
196 | private void OnProcessOptionEnvironmentVariablesEnabledControlCheckedChanged(object sender, EventArgs e)
197 | {
198 | CheckBox checkbox = ProcessOptionEnvironmentVariablesEnabledControl;
199 |
200 | if (ProcessOptionEnvironmentVariablesControl.Enabled != checkbox.Checked)
201 | ProcessOptionEnvironmentVariablesControl.Enabled = checkbox.Checked;
202 | }
203 |
204 | private void OnSelectWorkingDirectoryClick(object sender, EventArgs e)
205 | {
206 | folderPicker.Description = "Please select a folder to continue";
207 |
208 | if (folderPicker.ShowDialog() == DialogResult.OK)
209 | {
210 | Options.WorkingDirectory = folderPicker.SelectedPath;
211 | }
212 | }
213 |
214 | private void OnFileDialogRequested(object sender, EventArgs e)
215 | {
216 | if (ReferenceEquals(sender, SelectExecutablePath))
217 | {
218 | filePicker.Filter = "Windows Executable (*.exe)|*.exe";
219 | filePicker.Title = "Please select an executable to continue";
220 |
221 | if (filePicker.ShowDialog() == DialogResult.OK)
222 | {
223 | Options.Path = filePicker.FileName;
224 | Options.WorkingDirectory = Path.GetDirectoryName(Options.Path);
225 | }
226 | }
227 | else if (ReferenceEquals(sender, ProcessOptionPreLaunchScriptButton))
228 | {
229 | filePicker.Filter = "Shell Executable File (*.*)|*.*";
230 | filePicker.Title = "Please select a script to continue";
231 |
232 | if (filePicker.ShowDialog() == DialogResult.OK)
233 | {
234 | Options.PreLaunchScriptPath = filePicker.FileName;
235 | }
236 | }
237 | else if (ReferenceEquals(sender, ProcessOptionPostCrashScriptButton))
238 | {
239 | filePicker.Filter = "Shell Executable File (*.*)|*.*";
240 | filePicker.Title = "Please select a script to continue";
241 |
242 | if (filePicker.ShowDialog() == DialogResult.OK)
243 | {
244 | Options.PostCrashScriptPath = filePicker.FileName;
245 | }
246 | }
247 | }
248 |
249 | private void OnOpenScreenshotDirectoryButtonClick(object sender, EventArgs e)
250 | {
251 | if (!Directory.Exists(Program.ScreenShotDirectory))
252 | Directory.CreateDirectory(Program.ScreenShotDirectory);
253 |
254 | using (Process.Start(Program.ScreenShotDirectory)) { /* no-op */ }
255 | }
256 |
257 | private void DisposeAddedComponents()
258 | {
259 | folderPicker?.Dispose();
260 | filePicker?.Dispose();
261 |
262 | folderPicker = null;
263 | filePicker = null;
264 | }
265 | }
266 | }
267 |
--------------------------------------------------------------------------------
/OpenRoC/Program.cs:
--------------------------------------------------------------------------------
1 | namespace oroc
2 | {
3 | using System;
4 | using System.IO;
5 | using System.Threading;
6 | using System.Reflection;
7 | using System.Windows.Forms;
8 |
9 | static class Program
10 | {
11 | [STAThread]
12 | static int Main()
13 | {
14 | if (Settings.Instance.IsSingleInsntaceEnabled)
15 | {
16 | bool only_instance;
17 | using (Mutex applock = new Mutex(true, Properties.Resources.OpenRoCMutexName, out only_instance))
18 | {
19 | if (!only_instance)
20 | {
21 | MessageBox.Show(
22 | "Another OpenRoC instance is already open.",
23 | "Multiple instances detected!",
24 | MessageBoxButtons.OK,
25 | MessageBoxIcon.Error);
26 |
27 | return 1;
28 | }
29 | else
30 | {
31 | Launch();
32 | }
33 | }
34 | }
35 | else
36 | {
37 | Launch();
38 | }
39 |
40 | Settings.Instance.Save();
41 | return 0;
42 | }
43 |
44 | private static void Launch()
45 | {
46 | Application.EnableVisualStyles();
47 | Application.SetCompatibleTextRenderingDefault(false);
48 | Application.Run(new MainDialog());
49 | }
50 |
51 | public static string Directory
52 | {
53 | get { return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); }
54 | }
55 |
56 | public static string ScreenShotDirectory
57 | {
58 | get { return Path.Combine(Directory, ".ScreenShots"); }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/OpenRoC/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("OpenRoC")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("OpenRoC")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("374dfcee-deea-4d48-958e-0c8f64e9fcf6")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/OpenRoC/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace oroc.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("oroc.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized string similar to oroclock.
65 | ///
66 | internal static string OpenRoCMutexName {
67 | get {
68 | return ResourceManager.GetString("OpenRoCMutexName", resourceCulture);
69 | }
70 | }
71 |
72 | ///
73 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
74 | ///
75 | internal static System.Drawing.Icon phoenix {
76 | get {
77 | object obj = ResourceManager.GetObject("phoenix", resourceCulture);
78 | return ((System.Drawing.Icon)(obj));
79 | }
80 | }
81 |
82 | ///
83 | /// Looks up a localized string similar to Application.
84 | ///
85 | internal static string SettingsApplicationNode {
86 | get {
87 | return ResourceManager.GetString("SettingsApplicationNode", resourceCulture);
88 | }
89 | }
90 |
91 | ///
92 | /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
93 | ///<openroc>
94 | /// <log4net>
95 | /// <appender name="OpenRocRollingFile" type="log4net.Appender.RollingFileAppender">
96 | /// <file value="OpenRoc.log" />
97 | /// <appendToFile value="true" />
98 | /// <maximumFileSize value="10MB" />
99 | /// <maxSizeRollBackups value="20" />
100 | /// <layout type="log4net.Layout.PatternLayout">
101 | /// <conversionPattern value="[%5level] [%date{yyyy-MM-dd HH:mm:ss}] [%2thread] - %message%newline" />
102 | /// [rest of string was truncated]";.
103 | ///
104 | internal static string SettingsBaseXml {
105 | get {
106 | return ResourceManager.GetString("SettingsBaseXml", resourceCulture);
107 | }
108 | }
109 |
110 | ///
111 | /// Looks up a localized string similar to OpenRoc.xml.
112 | ///
113 | internal static string SettingsFileName {
114 | get {
115 | return ResourceManager.GetString("SettingsFileName", resourceCulture);
116 | }
117 | }
118 |
119 | ///
120 | /// Looks up a localized string similar to log4net.
121 | ///
122 | internal static string SettingsLog4NetNode {
123 | get {
124 | return ResourceManager.GetString("SettingsLog4NetNode", resourceCulture);
125 | }
126 | }
127 |
128 | ///
129 | /// Looks up a localized string similar to options.
130 | ///
131 | internal static string SettingsOptionNode {
132 | get {
133 | return ResourceManager.GetString("SettingsOptionNode", resourceCulture);
134 | }
135 | }
136 |
137 | ///
138 | /// Looks up a localized string similar to Processes.
139 | ///
140 | internal static string SettingsProcessListNode {
141 | get {
142 | return ResourceManager.GetString("SettingsProcessListNode", resourceCulture);
143 | }
144 | }
145 |
146 | ///
147 | /// Looks up a localized string similar to openroc.
148 | ///
149 | internal static string SettingsRootNode {
150 | get {
151 | return ResourceManager.GetString("SettingsRootNode", resourceCulture);
152 | }
153 | }
154 |
155 | ///
156 | /// Looks up a localized string similar to Ready (drag and drop executables or click Add. Double click to Edit).
157 | ///
158 | internal static string StatusTextDefaultString {
159 | get {
160 | return ResourceManager.GetString("StatusTextDefaultString", resourceCulture);
161 | }
162 | }
163 |
164 | ///
165 | /// Looks up a localized string similar to (
166 | /// _ ) )
167 | /// _,(_)._ ((
168 | /// ___,(_______). )
169 | /// ,'__. / \ /\_
170 | /// /,' / |""| \ / /
171 | ///| | | |__| |,' /
172 | /// \`.| /
173 | /// `. : : /
174 | /// `. :.,'
175 | /// `-.________,-'.
176 | ///
177 | internal static string Teapot {
178 | get {
179 | return ResourceManager.GetString("Teapot", resourceCulture);
180 | }
181 | }
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/OpenRoC/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | oroclock
122 |
123 |
124 |
125 | ..\phoenix.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
126 |
127 |
128 | Application
129 |
130 |
131 | ..\Resources\openroc.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
132 |
133 |
134 | OpenRoc.xml
135 |
136 |
137 | log4net
138 |
139 |
140 | options
141 |
142 |
143 | Processes
144 |
145 |
146 | openroc
147 |
148 |
149 | Ready (drag and drop executables or click Add. Double click to Edit)
150 |
151 |
152 | (
153 | _ ) )
154 | _,(_)._ ((
155 | ___,(_______). )
156 | ,'__. / \ /\_
157 | /,' / |""| \ / /
158 | | | | |__| |,' /
159 | \`.| /
160 | `. : : /
161 | `. :.,'
162 | `-.________,-'
163 | Teapot, duh.
164 |
165 |
--------------------------------------------------------------------------------
/OpenRoC/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace oroc.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/OpenRoC/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/OpenRoC/Resources/OpenRoc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/OpenRoC/SensuInterface.cs:
--------------------------------------------------------------------------------
1 | namespace oroc
2 | {
3 | using liboroc;
4 |
5 | using System;
6 | using System.IO;
7 | using System.Text;
8 | using System.Net.Sockets;
9 |
10 | public class SensuInterface : IDisposable
11 | {
12 | private readonly ProcessManager Manager;
13 | private UdpClient sensuClientSocket;
14 | private ExecutorService udpService;
15 | private uint checksTtl;
16 |
17 | public SensuInterface(ProcessManager manager, string host, uint port, uint ttl)
18 | {
19 | Manager = manager;
20 | checksTtl = ttl;
21 |
22 | try
23 | {
24 | sensuClientSocket = new UdpClient(host, (int)port);
25 |
26 | udpService = new ExecutorService();
27 | udpService.ExceptionReceived += ex => Log.e("UDP service: {0}", ex.Message);
28 |
29 | manager.RunnerAdded += (runner) =>
30 | {
31 | runner.StateChanged += () =>
32 | {
33 | if (runner.State != ProcessRunner.Status.Invalid)
34 | SendChecks();
35 | };
36 | };
37 | }
38 | catch(Exception ex)
39 | {
40 | Log.e("Failed to construct Sensu client socket: {0}", ex.Message);
41 | sensuClientSocket = null;
42 | }
43 | }
44 |
45 | public void SetTTL(uint ttl)
46 | {
47 | if (checksTtl == ttl)
48 | return;
49 |
50 | checksTtl = ttl;
51 | }
52 |
53 | public void SendChecks()
54 | {
55 | Manager.Runners.ForEach(runner =>
56 | {
57 | QueueUdpPacket(new
58 | {
59 | name = Path.GetFileName(runner.ProcessOptions.Path),
60 | output = runner.GetStateString(),
61 | status = (int)runner.State,
62 | timeout = checksTtl,
63 | ttl = checksTtl
64 | });
65 | });
66 | }
67 |
68 | private void QueueUdpPacket(object data)
69 | {
70 | udpService?.Accept(() =>
71 | {
72 | byte[] packet = Encoding.Default.GetBytes(data.ToJson());
73 | sensuClientSocket?.Send(packet, packet.Length);
74 | });
75 | }
76 |
77 | #region IDisposable Support
78 | public bool IsDisposed { get; private set; } = false;
79 |
80 | protected virtual void Dispose(bool disposing)
81 | {
82 | if (!IsDisposed)
83 | {
84 | IsDisposed = true;
85 |
86 | if (disposing)
87 | {
88 | sensuClientSocket?.Close();
89 | udpService?.Dispose();
90 | }
91 |
92 | sensuClientSocket = null;
93 | udpService = null;
94 | }
95 | }
96 |
97 | public void Dispose()
98 | {
99 | Dispose(true);
100 | }
101 | #endregion
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/OpenRoC/Settings.cs:
--------------------------------------------------------------------------------
1 | namespace oroc
2 | {
3 | using System;
4 | using System.IO;
5 | using System.Xml.Linq;
6 | using System.ComponentModel;
7 |
8 | public sealed class Settings : INotifyPropertyChanged
9 | {
10 | private static volatile object mutex = new object();
11 | private static volatile Settings instance;
12 | private Application application;
13 | private XElement openrocRoot;
14 | private XElement optionsRoot;
15 | private volatile bool dirty = false;
16 |
17 | public event PropertyChangedEventHandler PropertyChanged;
18 |
19 | public class Application
20 | {
21 | public bool singleInsntace = true;
22 | public bool startMinimized = false;
23 | public bool sensuInterfaceEnabled = false;
24 | public string sensuInterfaceHost = "127.0.0.1";
25 | public uint sensuInterfacePort = 3030;
26 | public uint sensuInterfaceTTL = 30;
27 | }
28 |
29 | public bool IsSingleInsntaceEnabled
30 | {
31 | get { return application.singleInsntace; }
32 | set
33 | {
34 | if (value == application.singleInsntace)
35 | return;
36 |
37 | application.singleInsntace = value;
38 | dirty = true;
39 |
40 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsSingleInsntaceEnabled)));
41 | }
42 | }
43 |
44 | public bool IsStartMinimizedEnabled
45 | {
46 | get { return application.startMinimized; }
47 | set
48 | {
49 | if (value == application.startMinimized)
50 | return;
51 |
52 | application.startMinimized = value;
53 | dirty = true;
54 |
55 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsStartMinimizedEnabled)));
56 | }
57 | }
58 |
59 | public bool IsSensuInterfaceEnabled
60 | {
61 | get { return application.sensuInterfaceEnabled; }
62 | set
63 | {
64 | if (value == application.sensuInterfaceEnabled)
65 | return;
66 |
67 | application.sensuInterfaceEnabled = value;
68 | dirty = true;
69 |
70 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsSensuInterfaceEnabled)));
71 | }
72 | }
73 |
74 | public string SensuInterfaceHost
75 | {
76 | get { return application.sensuInterfaceHost; }
77 | set
78 | {
79 | if (value == application.sensuInterfaceHost)
80 | return;
81 |
82 | application.sensuInterfaceHost = value;
83 | dirty = true;
84 |
85 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SensuInterfaceHost)));
86 | }
87 | }
88 |
89 | public uint SensuInterfacePort
90 | {
91 | get { return application.sensuInterfacePort; }
92 | set
93 | {
94 | if (value == application.sensuInterfacePort)
95 | return;
96 |
97 | application.sensuInterfacePort = value;
98 | dirty = true;
99 |
100 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SensuInterfacePort)));
101 | }
102 | }
103 |
104 | public uint SensuInterfaceTTL
105 | {
106 | get { return application.sensuInterfaceTTL; }
107 | set
108 | {
109 | if (value == application.sensuInterfaceTTL)
110 | return;
111 |
112 | application.sensuInterfaceTTL = value;
113 |
114 | if (application.sensuInterfaceTTL < 2)
115 | application.sensuInterfaceTTL = 2;
116 |
117 | dirty = true;
118 |
119 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SensuInterfaceTTL)));
120 | }
121 | }
122 |
123 | public static Settings Instance
124 | {
125 | get
126 | {
127 | if (instance == null)
128 | {
129 | lock (mutex)
130 | {
131 | if (instance == null)
132 | {
133 | instance = new Settings();
134 | instance.Setup();
135 | instance.Save();
136 | }
137 | }
138 | }
139 |
140 | return instance;
141 | }
142 | }
143 |
144 | private void Setup()
145 | {
146 | FileInfo config_file = new FileInfo(Path.Combine(
147 | Program.Directory, Properties.Resources.SettingsFileName));
148 |
149 | if (!config_file.Exists)
150 | {
151 | Log.w("Config file does not exist. It will be created at {0}", config_file.FullName);
152 | File.WriteAllText(config_file.FullName, Properties.Resources.SettingsBaseXml);
153 | }
154 |
155 | try
156 | {
157 | openrocRoot = XElement.Load(config_file.FullName);
158 | Log.d("Succesfully loaded config file {0}", config_file.FullName);
159 | dirty = false;
160 | }
161 | catch (Exception ex)
162 | {
163 | openrocRoot = XElement.Parse(Properties.Resources.SettingsBaseXml);
164 | Log.w("Failed to load config file. Defaults will be used: Reason: {0}", ex.Message);
165 | dirty = true;
166 | }
167 |
168 | if (openrocRoot == null || openrocRoot.Name != Properties.Resources.SettingsRootNode)
169 | {
170 | openrocRoot = new XElement(Properties.Resources.SettingsRootNode);
171 | Log.w("Config root name is different than {0}", Properties.Resources.SettingsRootNode);
172 | dirty = true;
173 | }
174 |
175 | optionsRoot = openrocRoot.Element(Properties.Resources.SettingsOptionNode);
176 |
177 | if (optionsRoot == null)
178 | {
179 | Log.w("Options root name is empty. A node will be created for it.");
180 | optionsRoot = new XElement(Properties.Resources.SettingsOptionNode);
181 | openrocRoot.Add(optionsRoot);
182 | dirty = true;
183 | }
184 |
185 | application = Read(Properties.Resources.SettingsApplicationNode);
186 | Write(Properties.Resources.SettingsApplicationNode, application);
187 |
188 | }
189 |
190 | public void Write(string node, T value) where T : new()
191 | {
192 | lock (this)
193 | {
194 | try
195 | {
196 | if (optionsRoot.Element(node) == null)
197 | optionsRoot.Add(new XElement(node));
198 |
199 | optionsRoot.Element(node).ReplaceAll(
200 | XElement.Parse(value.ToXmlNodeString()).Elements());
201 |
202 | dirty = true;
203 |
204 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(node));
205 | }
206 | catch (Exception ex)
207 | {
208 | Log.e("Failed to write XML string for node: {0}. Reason: {1}", node, ex.Message);
209 | dirty = false;
210 | }
211 | }
212 | }
213 |
214 | public T Read(string node) where T : new()
215 | {
216 | lock (this)
217 | {
218 | try
219 | {
220 | if (optionsRoot.Element(node) != null)
221 | return Extensions.FromXmlNodeString(
222 | optionsRoot.Element(node).ToString(), node);
223 | }
224 | catch (Exception ex)
225 | {
226 | Log.e("Failed to read XML string from node: {0}. Reason: {1}", node, ex.Message);
227 | }
228 |
229 | return new T();
230 | }
231 | }
232 |
233 | public void Save()
234 | {
235 | if (!dirty)
236 | return;
237 |
238 | lock (this)
239 | {
240 | Write(Properties.Resources.SettingsApplicationNode, application);
241 |
242 | openrocRoot.Save(Path.Combine(
243 | Program.Directory,
244 | Properties.Resources.SettingsFileName));
245 |
246 | dirty = false;
247 | }
248 | }
249 | }
250 | }
251 |
--------------------------------------------------------------------------------
/OpenRoC/SettingsDialog.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace oroc
2 | {
3 | partial class SettingsDialog
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SettingsDialog));
32 | this.StartOptionsGroup = new System.Windows.Forms.GroupBox();
33 | this.SingleInstanceCheckBox = new System.Windows.Forms.CheckBox();
34 | this.StartMinimizedCheckBox = new System.Windows.Forms.CheckBox();
35 | this.SensuGroup = new System.Windows.Forms.GroupBox();
36 | this.SensuPortTextBox = new System.Windows.Forms.TextBox();
37 | this.PortLabel = new System.Windows.Forms.Label();
38 | this.SensuHostTextBox = new System.Windows.Forms.TextBox();
39 | this.HostLabel = new System.Windows.Forms.Label();
40 | this.SensuInterfaceEnabledCheckBox = new System.Windows.Forms.CheckBox();
41 | this.SensuTTLTextBox = new System.Windows.Forms.TextBox();
42 | this.label1 = new System.Windows.Forms.Label();
43 | this.StartOptionsGroup.SuspendLayout();
44 | this.SensuGroup.SuspendLayout();
45 | this.SuspendLayout();
46 | //
47 | // StartOptionsGroup
48 | //
49 | this.StartOptionsGroup.Controls.Add(this.SingleInstanceCheckBox);
50 | this.StartOptionsGroup.Controls.Add(this.StartMinimizedCheckBox);
51 | this.StartOptionsGroup.Location = new System.Drawing.Point(12, 6);
52 | this.StartOptionsGroup.Name = "StartOptionsGroup";
53 | this.StartOptionsGroup.Size = new System.Drawing.Size(260, 77);
54 | this.StartOptionsGroup.TabIndex = 0;
55 | this.StartOptionsGroup.TabStop = false;
56 | this.StartOptionsGroup.Text = "Next time on start";
57 | //
58 | // SingleInstanceCheckBox
59 | //
60 | this.SingleInstanceCheckBox.AutoSize = true;
61 | this.SingleInstanceCheckBox.Location = new System.Drawing.Point(10, 46);
62 | this.SingleInstanceCheckBox.Name = "SingleInstanceCheckBox";
63 | this.SingleInstanceCheckBox.Size = new System.Drawing.Size(155, 17);
64 | this.SingleInstanceCheckBox.TabIndex = 1;
65 | this.SingleInstanceCheckBox.Text = "Force single-instance mode";
66 | this.SingleInstanceCheckBox.UseVisualStyleBackColor = true;
67 | //
68 | // StartMinimizedCheckBox
69 | //
70 | this.StartMinimizedCheckBox.AutoSize = true;
71 | this.StartMinimizedCheckBox.Location = new System.Drawing.Point(10, 23);
72 | this.StartMinimizedCheckBox.Name = "StartMinimizedCheckBox";
73 | this.StartMinimizedCheckBox.Size = new System.Drawing.Size(146, 17);
74 | this.StartMinimizedCheckBox.TabIndex = 0;
75 | this.StartMinimizedCheckBox.Text = "Start OpenRoC minimized";
76 | this.StartMinimizedCheckBox.UseVisualStyleBackColor = true;
77 | //
78 | // SensuGroup
79 | //
80 | this.SensuGroup.Controls.Add(this.label1);
81 | this.SensuGroup.Controls.Add(this.SensuTTLTextBox);
82 | this.SensuGroup.Controls.Add(this.SensuPortTextBox);
83 | this.SensuGroup.Controls.Add(this.PortLabel);
84 | this.SensuGroup.Controls.Add(this.SensuHostTextBox);
85 | this.SensuGroup.Controls.Add(this.HostLabel);
86 | this.SensuGroup.Controls.Add(this.SensuInterfaceEnabledCheckBox);
87 | this.SensuGroup.Location = new System.Drawing.Point(12, 89);
88 | this.SensuGroup.Name = "SensuGroup";
89 | this.SensuGroup.Size = new System.Drawing.Size(260, 77);
90 | this.SensuGroup.TabIndex = 2;
91 | this.SensuGroup.TabStop = false;
92 | this.SensuGroup.Text = "Sensu interface";
93 | //
94 | // SensuPortTextBox
95 | //
96 | this.SensuPortTextBox.Location = new System.Drawing.Point(205, 44);
97 | this.SensuPortTextBox.Name = "SensuPortTextBox";
98 | this.SensuPortTextBox.Size = new System.Drawing.Size(45, 20);
99 | this.SensuPortTextBox.TabIndex = 3;
100 | //
101 | // PortLabel
102 | //
103 | this.PortLabel.AutoSize = true;
104 | this.PortLabel.Location = new System.Drawing.Point(170, 47);
105 | this.PortLabel.Name = "PortLabel";
106 | this.PortLabel.Size = new System.Drawing.Size(32, 13);
107 | this.PortLabel.TabIndex = 3;
108 | this.PortLabel.Text = "Port :";
109 | //
110 | // SensuHostTextBox
111 | //
112 | this.SensuHostTextBox.Location = new System.Drawing.Point(42, 44);
113 | this.SensuHostTextBox.Name = "SensuHostTextBox";
114 | this.SensuHostTextBox.Size = new System.Drawing.Size(123, 20);
115 | this.SensuHostTextBox.TabIndex = 2;
116 | //
117 | // HostLabel
118 | //
119 | this.HostLabel.AutoSize = true;
120 | this.HostLabel.Location = new System.Drawing.Point(7, 47);
121 | this.HostLabel.Name = "HostLabel";
122 | this.HostLabel.Size = new System.Drawing.Size(35, 13);
123 | this.HostLabel.TabIndex = 1;
124 | this.HostLabel.Text = "Host :";
125 | //
126 | // SensuInterfaceEnabledCheckBox
127 | //
128 | this.SensuInterfaceEnabledCheckBox.AutoSize = true;
129 | this.SensuInterfaceEnabledCheckBox.Location = new System.Drawing.Point(10, 23);
130 | this.SensuInterfaceEnabledCheckBox.Name = "SensuInterfaceEnabledCheckBox";
131 | this.SensuInterfaceEnabledCheckBox.Size = new System.Drawing.Size(142, 17);
132 | this.SensuInterfaceEnabledCheckBox.TabIndex = 0;
133 | this.SensuInterfaceEnabledCheckBox.Text = "Enable Sensu interface :";
134 | this.SensuInterfaceEnabledCheckBox.UseVisualStyleBackColor = true;
135 | this.SensuInterfaceEnabledCheckBox.CheckedChanged += new System.EventHandler(this.OnSensuInterfaceEnabledCheckBoxCheckedChanged);
136 | //
137 | // SensuTTLTextBox
138 | //
139 | this.SensuTTLTextBox.Location = new System.Drawing.Point(205, 20);
140 | this.SensuTTLTextBox.Name = "SensuTTLTextBox";
141 | this.SensuTTLTextBox.Size = new System.Drawing.Size(45, 20);
142 | this.SensuTTLTextBox.TabIndex = 1;
143 | //
144 | // label1
145 | //
146 | this.label1.AutoSize = true;
147 | this.label1.Location = new System.Drawing.Point(170, 23);
148 | this.label1.Name = "label1";
149 | this.label1.Size = new System.Drawing.Size(33, 13);
150 | this.label1.TabIndex = 6;
151 | this.label1.Text = "TTL :";
152 | //
153 | // SettingsDialog
154 | //
155 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
156 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
157 | this.ClientSize = new System.Drawing.Size(284, 177);
158 | this.Controls.Add(this.SensuGroup);
159 | this.Controls.Add(this.StartOptionsGroup);
160 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
161 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
162 | this.MaximizeBox = false;
163 | this.Name = "SettingsDialog";
164 | this.Text = "Settings";
165 | this.StartOptionsGroup.ResumeLayout(false);
166 | this.StartOptionsGroup.PerformLayout();
167 | this.SensuGroup.ResumeLayout(false);
168 | this.SensuGroup.PerformLayout();
169 | this.ResumeLayout(false);
170 |
171 | }
172 |
173 | #endregion
174 |
175 | private System.Windows.Forms.GroupBox StartOptionsGroup;
176 | private System.Windows.Forms.CheckBox StartMinimizedCheckBox;
177 | private System.Windows.Forms.CheckBox SingleInstanceCheckBox;
178 | private System.Windows.Forms.GroupBox SensuGroup;
179 | private System.Windows.Forms.CheckBox SensuInterfaceEnabledCheckBox;
180 | private System.Windows.Forms.TextBox SensuPortTextBox;
181 | private System.Windows.Forms.Label PortLabel;
182 | private System.Windows.Forms.TextBox SensuHostTextBox;
183 | private System.Windows.Forms.Label HostLabel;
184 | private System.Windows.Forms.Label label1;
185 | private System.Windows.Forms.TextBox SensuTTLTextBox;
186 | }
187 | }
--------------------------------------------------------------------------------
/OpenRoC/SettingsDialog.cs:
--------------------------------------------------------------------------------
1 | namespace oroc
2 | {
3 | using System.Windows.Forms;
4 | using System.ComponentModel;
5 |
6 | public partial class SettingsDialog : Form
7 | {
8 | public SettingsDialog()
9 | {
10 | InitializeComponent();
11 | SetupDataBindings();
12 |
13 | HandleCreated += OnSettingsDialogHandleCreated;
14 | }
15 |
16 | private void OnSettingsDialogHandleCreated(object sender, System.EventArgs e)
17 | {
18 | MainDialog main_dialog = Owner as MainDialog;
19 |
20 | main_dialog.SetStatusBarText(SingleInstanceCheckBox, "Allow only one instance of OpenRoC to run on this computer.");
21 | main_dialog.SetStatusBarText(StartMinimizedCheckBox, "Start OpenRoC minimized, in task-bar next time it launches.");
22 | main_dialog.SetStatusBarText(SensuInterfaceEnabledCheckBox, "Enable Sensu 'client socket' support (applicable next time OpenRoC launches).");
23 | main_dialog.SetStatusBarText(SensuHostTextBox, "Sensu UDP 'client' host (applicable next time OpenRoC launches).");
24 | main_dialog.SetStatusBarText(SensuPortTextBox, "Sensu UDP 'client' port (applicable next time OpenRoC launches).");
25 | main_dialog.SetStatusBarText(SensuTTLTextBox, "Sensu checks TTL in seconds. Interval is 80% of TTL and timeout is equal to TTL.");
26 |
27 | SyncCheckedStates();
28 | }
29 |
30 | private void SetupDataBindings()
31 | {
32 | StartMinimizedCheckBox.SetupDataBind(Settings.Instance, nameof(Settings.Instance.IsStartMinimizedEnabled));
33 | SingleInstanceCheckBox.SetupDataBind(Settings.Instance, nameof(Settings.Instance.IsSingleInsntaceEnabled));
34 | SensuInterfaceEnabledCheckBox.SetupDataBind(Settings.Instance, nameof(Settings.Instance.IsSensuInterfaceEnabled));
35 | SensuHostTextBox.SetupDataBind(Settings.Instance, nameof(Settings.Instance.SensuInterfaceHost));
36 | SensuPortTextBox.SetupDataBind(Settings.Instance, nameof(Settings.Instance.SensuInterfacePort));
37 | SensuTTLTextBox.SetupDataBind(Settings.Instance, nameof(Settings.Instance.SensuInterfaceTTL));
38 |
39 | Settings.Instance.PropertyChanged += OnSettingsInstancePropertyChanged;
40 | }
41 |
42 | private void OnSettingsInstancePropertyChanged(object sender, PropertyChangedEventArgs e)
43 | {
44 | if (e.PropertyName == nameof(Settings.Instance.SensuInterfaceTTL))
45 | (Owner as MainDialog).SetSensuInterfaceUpdateTimerInterval(Settings.Instance.SensuInterfaceTTL);
46 | }
47 |
48 | private void OnSensuInterfaceEnabledCheckBoxCheckedChanged(object sender, System.EventArgs e)
49 | {
50 | if (SensuHostTextBox.Enabled != SensuInterfaceEnabledCheckBox.Checked)
51 | SensuHostTextBox.Enabled = SensuInterfaceEnabledCheckBox.Checked;
52 |
53 | if (SensuPortTextBox.Enabled != SensuInterfaceEnabledCheckBox.Checked)
54 | SensuPortTextBox.Enabled = SensuInterfaceEnabledCheckBox.Checked;
55 |
56 | if (SensuTTLTextBox.Enabled != SensuInterfaceEnabledCheckBox.Checked)
57 | SensuTTLTextBox.Enabled = SensuInterfaceEnabledCheckBox.Checked;
58 | }
59 |
60 | private void SyncCheckedStates()
61 | {
62 | OnSensuInterfaceEnabledCheckBoxCheckedChanged(this, null);
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/OpenRoC/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/OpenRoC/phoenix.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeliosInteractive/OpenRoC/9b69c54c28e230f795b48e92c2bff4ab29d80ad7/OpenRoC/phoenix.ico
--------------------------------------------------------------------------------
/OpenRoC/testProcessWindowed/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/OpenRoC/testProcessWindowed/MainForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace testProcessWindowed
2 | {
3 | partial class MainForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
32 | this.SuspendLayout();
33 | //
34 | // Form1
35 | //
36 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
37 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
38 | this.ClientSize = new System.Drawing.Size(284, 261);
39 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
40 | this.Name = "Form1";
41 | this.Text = "Test Windowed Process";
42 | this.ResumeLayout(false);
43 |
44 | }
45 |
46 | #endregion
47 | }
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/OpenRoC/testProcessWindowed/MainForm.cs:
--------------------------------------------------------------------------------
1 | namespace testProcessWindowed
2 | {
3 | using System;
4 | using System.Threading;
5 | using System.Windows.Forms;
6 |
7 | public partial class MainForm : Form
8 | {
9 | public MainForm()
10 | {
11 | InitializeComponent();
12 | Shown += OnShown;
13 | }
14 |
15 | private void OnShown(object sender, EventArgs e)
16 | {
17 | string[] args = Environment.GetCommandLineArgs();
18 |
19 | var unresponsive = false;
20 | var respwaittime = (int)TimeSpan.FromMinutes(30).TotalMilliseconds;
21 |
22 | if (args != null)
23 | {
24 | if (args.Length > 1)
25 | unresponsive = (args[1] == nameof(unresponsive));
26 |
27 | if (args.Length > 2)
28 | respwaittime = (int)TimeSpan.FromSeconds(int.Parse(args[2])).TotalMilliseconds;
29 | }
30 |
31 | if (unresponsive)
32 | Thread.Sleep(respwaittime);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/OpenRoC/testProcessWindowed/Program.cs:
--------------------------------------------------------------------------------
1 | namespace testProcessWindowed
2 | {
3 | using System;
4 | using System.Windows.Forms;
5 |
6 | static class Program
7 | {
8 | ///
9 | /// The main entry point for the application.
10 | ///
11 | [STAThread]
12 | static void Main()
13 | {
14 | Application.EnableVisualStyles();
15 | Application.SetCompatibleTextRenderingDefault(false);
16 | Application.Run(new MainForm());
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/OpenRoC/testProcessWindowed/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("testProcessWindowed")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("testProcessWindowed")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("ab679701-4781-4ae5-a484-7fdbab6c0e48")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/OpenRoC/testProcessWindowed/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace testProcessWindowed.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("testProcessWindowed.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/OpenRoC/testProcessWindowed/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/OpenRoC/testProcessWindowed/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace testProcessWindowed.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/OpenRoC/testProcessWindowed/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/OpenRoC/testProcessWindowed/testProcessWindowed.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {AB679701-4781-4AE5-A484-7FDBAB6C0E48}
8 | WinExe
9 | Properties
10 | testProcessWindowed
11 | testProcessWindowed
12 | v4.5.2
13 | 512
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | ..\..\testOpenRoC\processes\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | Form
51 |
52 |
53 | MainForm.cs
54 |
55 |
56 |
57 |
58 | MainForm.cs
59 |
60 |
61 | ResXFileCodeGenerator
62 | Resources.Designer.cs
63 | Designer
64 |
65 |
66 | True
67 | Resources.resx
68 |
69 |
70 | SettingsSingleFileGenerator
71 | Settings.Designer.cs
72 |
73 |
74 | True
75 | Settings.settings
76 | True
77 |
78 |
79 |
80 |
81 |
82 |
83 |
90 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OpenRoC
2 | Open-source Restart on Crash alternative with Sensu support.
3 |
4 | **THIS PROJECT IS NO LONGER ACTIVELY MAINTAINED AND THE REPOSITORY IS ARCHIVED. IF YOU COMPLIE AND TESTS PASS, YOU SHOULD BE GOOD TO GO. USE AT YOUR OWN RISK.**
5 |
6 | ## Main Window
7 | 
8 |
9 | ### Top menu bar
10 |
11 | #### Add
12 | Adds a new process to monitor. Clicking this button will open up a [Process Window](#process-window).
13 |
14 | #### Delete
15 | Removes selected processes in the [Process list](#process-list) section. You may multi-select different Processes or use the CTRL key to select them individually.
16 |
17 | #### Settings
18 | Opens up OpenRoC's [Settings Window](#settings-window).
19 |
20 | #### Logs
21 | Opens up OpenRoC's Logs Window. Logs are also stored and rotated (every 10MB) into a file named `OpenRoC.log` next to where you have `OpenRoC.exe` located.
22 |
23 | #### About
24 | Opens up OpenRoC's About Window. You may find third-party licenses and credits here.
25 |
26 | ### Process list
27 |
28 | #### Process column
29 | Lists all currently monitored Processes. You may use the check mark next to a Process to disable its monitoring. In order to add a Process to this list, you can either use the [Add](#add) button or you can do so by accessing the [Right-click menu](#right-click-menu). Double-clicking on a Process opens up its [Process Window](process-window) to edit.
30 |
31 | #### Status column
32 | Reports the current state of the Process as well as the time it has spent since the last time it entered this state. States are:
33 |
34 | - **Running:** Process is running correctly and being monitored for crashes.
35 | - **Stopped:** Process is stopped (not running) and being monitored.
36 | - **Disabled:** Process is stopped and is not being monitored.
37 |
38 | ### Performance graph
39 | It shows a line-graph of the cumulative % usage of three main resources on the computer OpenRoC is running on. CPU usage (red), RAM usage (blue), and GPU usage (green) are data gathered for the past few seconds.
40 |
41 | ### Bottom status bar
42 | Shows useful tips and explanations about some highlighted UI items.
43 |
44 | ### Right-click menu
45 | You can access this menu by right-clicking anywhere in the [Process column](#process-column) section. Following buttons are available in this menu:
46 |
47 | - **Add:** same as [Add](#add).
48 | - **Edit:** same as double clicking a Process in [Process column](#process-column).
49 | - **Delete:** same as [Delete](#delete)
50 | - **Disable:** same as using check boxes of a Process in [Process column](#process-column).
51 | - **Start Process(es):** sets state of a Process to *running*.
52 | - **Stop Process(es):** sets state of a Process to *stopped*.
53 | - **Show Window(s):** sets state of a Process to *disabled*.
54 |
55 | ### Taskbar menu
56 | You can access this menu by right-clicking on OpenRoC's icon in your task-bar while it's running.
57 |
58 | #### Show/Hide
59 | Toggles UI visibility of OpenRoC.
60 |
61 | #### Exit
62 | Quits OpenRoC.
63 |
64 | ## Process Window
65 | 
66 |
67 | ### Process path
68 |
69 | - **Executable Path:** path to the Process `.exe`. Only `.exe` is allowed (e.g `.bat` files are not allowed).
70 | - **Working Directory:** working directory of the Process. This is usually the same directory where the Process `.exe` is located.
71 |
72 | ### Crash settings
73 |
74 | - **Crashed if not running:** Assume a Process is crashed if it's not running. If you set the initial state to *running* and OpenRoC sees Process is *stopped*, it will go into the *running* state.
75 | - **Crashed if unresponsive:** Some Processes may have unresponsive windows, in that case assume it is crashed and restart it.
76 | - **Unresponsiveness time period:** The number of seconds passed until OpenRoC assumes an unresponsive process is crashed.
77 | - **Grace period:** The number of seconds to wait before attempting a relaunch of a crashed Process.
78 |
79 | ### Pre-start event
80 | You can specify a script to be executed before OpenRoC attempts to start the Process again. OpenRoC will wait for the script to execute before starting the Process.
81 |
82 | ### Post-stop event
83 | You can specify a script to be executed after OpenRoC stops the Process. OpenRoC will wait for the script to execute before starting the Process. You can also opt-in for an aggressive method of stopping processes (*recommended*).
84 |
85 | ### MISC. settings
86 | Most options in this part are self-explanatory. Most-notably you can set the initial state of the Process after you hit *Save* and return to the [Main Window](#main-window).
87 |
88 | ## Settings Window
89 | 
90 |
91 | ### Start settings
92 |
93 | #### Start minimized
94 | Enables OpenRoC to start minimized in task-bar next time it launches.
95 |
96 | #### Single instance mode
97 | Forces only one instance of OpenRoC being able to launch on this machine.
98 |
99 | ### Sensu settings
100 | Enables [Sensu client socket](https://sensuapp.org/docs/0.25/reference/clients.html#client-socket-input) support via UDP.
101 |
--------------------------------------------------------------------------------
/libOpenRoC/ExecutorService.cs:
--------------------------------------------------------------------------------
1 | namespace liboroc
2 | {
3 | using System;
4 | using System.Threading.Tasks;
5 | using System.Collections.Generic;
6 |
7 | public class ExecutorService : IDisposable
8 | {
9 | private readonly List pending;
10 | public Action ExceptionReceived;
11 |
12 | public ExecutorService()
13 | {
14 | pending = new List();
15 | }
16 |
17 | public void Accept(Action action)
18 | {
19 | if (IsDisposed)
20 | return;
21 |
22 | lock (this)
23 | {
24 | pending.Add(Task.Run(() =>
25 | {
26 | try { action(); }
27 | catch (Exception ex)
28 | { ExceptionReceived?.Invoke(ex); }
29 | }));
30 | }
31 | }
32 |
33 | public void Wait()
34 | {
35 | if (IsDisposed)
36 | return;
37 |
38 | lock (this)
39 | {
40 | Task.WaitAll(pending.ToArray());
41 | pending.ForEach(task => task.Dispose());
42 | pending.Clear();
43 | }
44 | }
45 |
46 | #region IDisposable Support
47 | public bool IsDisposed { get; private set; } = false;
48 |
49 | protected virtual void Dispose(bool disposing)
50 | {
51 | if (!IsDisposed)
52 | {
53 | if (disposing)
54 | {
55 | Wait();
56 | }
57 |
58 | IsDisposed = true;
59 | }
60 | }
61 |
62 | public void Dispose()
63 | {
64 | Dispose(true);
65 | }
66 | #endregion
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/libOpenRoC/Extensions.cs:
--------------------------------------------------------------------------------
1 | namespace liboroc
2 | {
3 | using System;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Threading;
7 | using System.Collections.Generic;
8 |
9 | public static class Extensions
10 | {
11 | public static bool IsDirectory(this string self)
12 | {
13 | try { return File.GetAttributes(self).HasFlag(FileAttributes.Directory); }
14 | catch (Exception) { return false; }
15 | }
16 |
17 | public static bool IsFile(this string self)
18 | {
19 | try { return !File.GetAttributes(self).HasFlag(FileAttributes.Directory); }
20 | catch (Exception) { return false; }
21 | }
22 |
23 | public static bool IsExecutable(this string self)
24 | {
25 | return self.IsFile() && self.EndsWith(".exe");
26 | }
27 |
28 | public static string ToColonDelimitedString(this Dictionary self)
29 | {
30 | if (self.Count == 0)
31 | return null;
32 |
33 | return string.Join(";", self
34 | .Select(x => string.Format("{0}={1}", x.Key, x.Value))
35 | .ToArray());
36 | }
37 |
38 | public static bool FromColonDelimitedString(this Dictionary self, string colon_delimited)
39 | {
40 | if (self.Count > 0)
41 | self.Clear();
42 |
43 | if (string.IsNullOrWhiteSpace(colon_delimited))
44 | return false;
45 |
46 | colon_delimited
47 | .Split(';')
48 | .Where(x => x.Contains('='))
49 | .Select(x => x.Split('='))
50 | .ToList()
51 | .ForEach(pair => self.Add(pair.First(), pair.Last()));
52 |
53 | return true;
54 | }
55 |
56 | public static string GetStateString(this ProcessRunner self)
57 | {
58 | return string.Format("{0} for {1:hh\\:mm\\:ss}", self.State, self.Stopwatch.Elapsed);
59 | }
60 |
61 | public static void WaitUntilUnresponsive(this ProcessRunner self)
62 | {
63 | while (self.Process.Responding)
64 | {
65 | self.Process.Refresh();
66 | Thread.Sleep(TimeSpan.FromMilliseconds(1));
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/libOpenRoC/NativeMethods.cs:
--------------------------------------------------------------------------------
1 | namespace liboroc
2 | {
3 | using System;
4 | using System.Runtime.InteropServices;
5 |
6 | internal static class NativeMethods
7 | {
8 | [Flags]
9 | public enum SetWindowPosFlags : uint
10 | {
11 | SWP_NOMOVE = 0x0002,
12 | SWP_NOSIZE = 0x0001,
13 | SWP_SHOWWINDOW = 0x0040
14 | }
15 |
16 | [DllImport("user32.dll", SetLastError = true)]
17 | [return: MarshalAs(UnmanagedType.Bool)]
18 | public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
19 |
20 | [DllImport("user32.dll", SetLastError = true)]
21 | [return: MarshalAs(UnmanagedType.Bool)]
22 | public static extern bool SetForegroundWindow(IntPtr hWnd);
23 |
24 | [DllImport("user32.dll", SetLastError = false)]
25 | public static extern IntPtr GetDesktopWindow();
26 |
27 | [DllImport("user32.dll", SetLastError = true)]
28 | public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
29 |
30 | [DllImport("user32.dll")]
31 | public static extern IntPtr GetForegroundWindow();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/libOpenRoC/ProcessHelper.cs:
--------------------------------------------------------------------------------
1 | namespace liboroc
2 | {
3 | using System;
4 | using System.Diagnostics;
5 |
6 | public static class ProcessHelper
7 | {
8 | public static void ExecuteScript(string script_path, string command_line = null, bool headless = false)
9 | {
10 | if (string.IsNullOrWhiteSpace(script_path))
11 | return;
12 |
13 | using (Process process = new Process
14 | {
15 | StartInfo = new ProcessStartInfo
16 | {
17 | FileName = script_path,
18 | Arguments = command_line,
19 | CreateNoWindow = headless,
20 | UseShellExecute = true,
21 | }
22 | })
23 | {
24 | process.Start();
25 | process.WaitForExit();
26 | }
27 | }
28 |
29 | public static void Shutdown(int pid)
30 | {
31 | ProcessObserver.Instance.Accept((process) =>
32 | {
33 | if (!process.HasExited)
34 | {
35 | process.Kill();
36 | process.WaitForExit((int)TimeSpan.FromSeconds(1).TotalMilliseconds);
37 | }
38 | }
39 | , pid);
40 | }
41 |
42 | public static void BringToFront(int pid, bool aggressive)
43 | {
44 | ProcessObserver.Instance.Accept((process) =>
45 | {
46 | if (!process.HasExited && process.MainWindowHandle != IntPtr.Zero)
47 | {
48 | if (GetForegroundWindow() != process.MainWindowHandle)
49 | {
50 | NativeMethods.SwitchToThisWindow(process.MainWindowHandle, true);
51 | NativeMethods.SetForegroundWindow(process.MainWindowHandle);
52 |
53 | if (aggressive)
54 | {
55 | NativeMethods.SetWindowPos(
56 | process.MainWindowHandle,
57 | new IntPtr(-1), //HWND_TOPMOST
58 | 0, 0, 0, 0,
59 | NativeMethods.SetWindowPosFlags.SWP_NOSIZE |
60 | NativeMethods.SetWindowPosFlags.SWP_NOMOVE |
61 | NativeMethods.SetWindowPosFlags.SWP_SHOWWINDOW);
62 | }
63 | }
64 | }
65 | }
66 | , pid);
67 | }
68 |
69 | public static IntPtr GetForegroundWindow()
70 | {
71 | IntPtr foreground = NativeMethods.GetForegroundWindow();
72 |
73 | if (foreground == IntPtr.Zero)
74 | return NativeMethods.GetDesktopWindow();
75 | else
76 | return foreground;
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/libOpenRoC/ProcessManager.cs:
--------------------------------------------------------------------------------
1 | namespace liboroc
2 | {
3 | using System;
4 | using System.Linq;
5 | using System.Collections.Generic;
6 |
7 | public class ProcessManager : IDisposable
8 | {
9 | private Dictionary processMap
10 | = new Dictionary();
11 |
12 | public Action ProcessesChanged;
13 | public Action RunnerAdded;
14 | public Action RunnerRemoved;
15 |
16 | public List Runners
17 | {
18 | get { return processMap.Values.ToList(); }
19 | }
20 |
21 | public List Options
22 | {
23 | get { return Runners.Select(x => x.ProcessOptions).ToList(); }
24 | }
25 |
26 | public void Add(ProcessOptions opts)
27 | {
28 | if (!Contains(opts.Path))
29 | {
30 | ProcessRunner proc = new ProcessRunner(opts);
31 |
32 | proc.StateChanged += OnProcessesChanged;
33 | proc.OptionsChanged += OnProcessesChanged;
34 |
35 | processMap.Add(opts.Path, proc);
36 | RunnerAdded?.Invoke(proc);
37 |
38 | OnProcessesChanged();
39 | }
40 | }
41 |
42 | public void Remove(string path)
43 | {
44 | if (Contains(path))
45 | {
46 | using (ProcessRunner proc = processMap[path])
47 | {
48 | processMap.Remove(path);
49 | RunnerRemoved?.Invoke(proc);
50 | }
51 |
52 | OnProcessesChanged();
53 | }
54 | }
55 |
56 | public bool Contains(string path)
57 | {
58 | return !string.IsNullOrWhiteSpace(path) &&
59 | processMap.ContainsKey(path);
60 | }
61 |
62 | public ProcessRunner Get(string path)
63 | {
64 | if (Contains(path))
65 | return processMap[path];
66 | else
67 | return null;
68 | }
69 |
70 | protected void OnProcessesChanged()
71 | {
72 | ProcessesChanged?.Invoke();
73 | }
74 |
75 | #region IDisposable Support
76 | public bool IsDisposed { get; private set; } = false;
77 |
78 | protected virtual void Dispose(bool disposing)
79 | {
80 | if (!IsDisposed)
81 | {
82 | if (disposing)
83 | {
84 | foreach (var pair in processMap)
85 | pair.Value.Dispose();
86 | }
87 |
88 | IsDisposed = true;
89 | }
90 | }
91 |
92 | public void Dispose()
93 | {
94 | Dispose(true);
95 | }
96 | #endregion
97 |
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/libOpenRoC/ProcessObserver.cs:
--------------------------------------------------------------------------------
1 | namespace liboroc
2 | {
3 | using System;
4 | using System.Management;
5 | using System.Diagnostics;
6 |
7 | public class ProcessObserver
8 | {
9 | public interface IVisitor
10 | {
11 | void Visit(Process process);
12 | }
13 |
14 | private static object mutex = new object();
15 | private static ProcessObserver instance;
16 |
17 | public static ProcessObserver Instance
18 | {
19 | get
20 | {
21 | if (instance == null)
22 | {
23 | lock (mutex)
24 | {
25 | if (instance == null)
26 | {
27 | instance = new ProcessObserver();
28 | }
29 | }
30 | }
31 |
32 | return instance;
33 | }
34 | }
35 |
36 | public void Accept(Action visitor, int pid)
37 | {
38 | using (ExecutorService service = new ExecutorService())
39 | {
40 | service.Accept(() => { execute(visitor, pid); });
41 | }
42 | }
43 |
44 | private void execute(Action visitor, int pid)
45 | {
46 | string query = string.Format("Select * From Win32_Process Where ParentProcessID={0}", pid);
47 | using (ManagementObjectSearcher processSearcher = new ManagementObjectSearcher(query))
48 | using (ManagementObjectCollection processCollection = processSearcher.Get())
49 | {
50 | try
51 | {
52 | using (Process proc = Process.GetProcessById(pid))
53 | {
54 | visitor?.Invoke(proc);
55 | }
56 | }
57 | catch { /* there is nothing we can do about it */ }
58 |
59 | if (processCollection != null)
60 | {
61 | foreach (ManagementObject mo in processCollection)
62 | {
63 | execute(visitor, Convert.ToInt32(mo["ProcessID"]));
64 | }
65 | }
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/libOpenRoC/ProcessOptions.cs:
--------------------------------------------------------------------------------
1 | namespace liboroc
2 | {
3 | using System;
4 | using System.ComponentModel;
5 | using System.Xml.Serialization;
6 | using System.Collections.Generic;
7 |
8 | public class ProcessOptions : INotifyPropertyChanged, ICloneable
9 | {
10 | #region private data holders
11 |
12 | private string path;
13 | private string workingDirectory;
14 | private bool crashedIfNotRunning;
15 | private bool crashedIfUnresponsive;
16 | private bool doubleCheckEnabled;
17 | private uint doubleCheckDuration;
18 | private bool gracePeriodEnabled;
19 | private uint gracePeriodDuration;
20 | private bool preLaunchScriptEnabled;
21 | private string preLaunchScriptPath;
22 | private bool aggressiveCleanupEnabled;
23 | private bool postCrashScriptEnabled;
24 | private string postCrashScriptPath;
25 | private bool screenShotEnabled;
26 | private bool alwaysOnTopEnabled;
27 | private bool commandLineEnabled;
28 | private string commandLine;
29 | private bool environmentVariablesEnabled;
30 | private readonly Dictionary environmentVariables;
31 | private ProcessRunner.Status initialState;
32 |
33 | #endregion
34 |
35 | public ProcessOptions()
36 | {
37 | SetDefaults();
38 | environmentVariables = new Dictionary();
39 | }
40 |
41 | public ProcessOptions(Dictionary variables)
42 | {
43 | SetDefaults();
44 | environmentVariables = variables;
45 | }
46 |
47 | void SetDefaults()
48 | {
49 | path = string.Empty;
50 | workingDirectory = string.Empty;
51 | crashedIfNotRunning = true;
52 | crashedIfUnresponsive = true;
53 | doubleCheckEnabled = false;
54 | doubleCheckDuration = 0;
55 | gracePeriodEnabled = false;
56 | gracePeriodDuration = 0;
57 | preLaunchScriptEnabled = false;
58 | preLaunchScriptPath = string.Empty;
59 | aggressiveCleanupEnabled = true;
60 | postCrashScriptEnabled = false;
61 | postCrashScriptPath = string.Empty;
62 | screenShotEnabled = false;
63 | alwaysOnTopEnabled = false;
64 | commandLineEnabled = false;
65 | commandLine = string.Empty;
66 | environmentVariablesEnabled = false;
67 |
68 | if (environmentVariables != null)
69 | environmentVariables.Clear();
70 |
71 | initialState = ProcessRunner.Status.Stopped;
72 | }
73 |
74 | #region DataBind accessible properties
75 |
76 | public string Path
77 | {
78 | get { return path; }
79 | set
80 | {
81 | if (path == value || !value.IsExecutable())
82 | return;
83 |
84 | path = value;
85 | NotifyPropertyChanged(nameof(Path));
86 | }
87 | }
88 |
89 | public string WorkingDirectory
90 | {
91 | get { return workingDirectory; }
92 | set
93 | {
94 | if (workingDirectory == value || !value.IsDirectory())
95 | return;
96 |
97 | workingDirectory = value;
98 | NotifyPropertyChanged(nameof(WorkingDirectory));
99 | }
100 | }
101 |
102 | public bool CrashedIfNotRunning
103 | {
104 | get { return crashedIfNotRunning; }
105 | set
106 | {
107 | if (crashedIfNotRunning == value)
108 | return;
109 |
110 | crashedIfNotRunning = value;
111 | NotifyPropertyChanged(nameof(CrashedIfNotRunning));
112 | }
113 | }
114 |
115 | public bool CrashedIfUnresponsive
116 | {
117 | get { return crashedIfUnresponsive; }
118 | set
119 | {
120 | if (crashedIfUnresponsive == value)
121 | return;
122 |
123 | crashedIfUnresponsive = value;
124 | NotifyPropertyChanged(nameof(CrashedIfUnresponsive));
125 | }
126 | }
127 |
128 | public bool DoubleCheckEnabled
129 | {
130 | get { return doubleCheckEnabled; }
131 | set
132 | {
133 | if (doubleCheckEnabled == value)
134 | return;
135 |
136 | doubleCheckEnabled = value;
137 | NotifyPropertyChanged(nameof(DoubleCheckEnabled));
138 | }
139 | }
140 |
141 | public uint DoubleCheckDuration
142 | {
143 | get { return doubleCheckDuration; }
144 | set
145 | {
146 | if (doubleCheckDuration == value)
147 | return;
148 |
149 | doubleCheckDuration = value;
150 | NotifyPropertyChanged(nameof(DoubleCheckDuration));
151 | }
152 | }
153 |
154 | public bool GracePeriodEnabled
155 | {
156 | get { return gracePeriodEnabled; }
157 | set
158 | {
159 | if (gracePeriodEnabled == value)
160 | return;
161 |
162 | gracePeriodEnabled = value;
163 | NotifyPropertyChanged(nameof(GracePeriodEnabled));
164 | }
165 | }
166 |
167 | public uint GracePeriodDuration
168 | {
169 | get { return gracePeriodDuration; }
170 | set
171 | {
172 | if (gracePeriodDuration == value)
173 | return;
174 |
175 | gracePeriodDuration = value;
176 | NotifyPropertyChanged(nameof(GracePeriodDuration));
177 | }
178 | }
179 |
180 | public bool PreLaunchScriptEnabled
181 | {
182 | get { return preLaunchScriptEnabled; }
183 | set
184 | {
185 | if (preLaunchScriptEnabled == value)
186 | return;
187 |
188 | preLaunchScriptEnabled = value;
189 | NotifyPropertyChanged(nameof(PreLaunchScriptEnabled));
190 | }
191 | }
192 |
193 | public string PreLaunchScriptPath
194 | {
195 | get { return preLaunchScriptPath; }
196 | set
197 | {
198 | if (preLaunchScriptPath == value || !value.IsFile())
199 | return;
200 |
201 | preLaunchScriptPath = value;
202 | NotifyPropertyChanged(nameof(PreLaunchScriptPath));
203 | }
204 | }
205 |
206 | public bool AggressiveCleanupEnabled
207 | {
208 | get { return aggressiveCleanupEnabled; }
209 | set
210 | {
211 | if (aggressiveCleanupEnabled == value)
212 | return;
213 |
214 | aggressiveCleanupEnabled = value;
215 | NotifyPropertyChanged(nameof(AggressiveCleanupEnabled));
216 | }
217 | }
218 |
219 | public bool PostCrashScriptEnabled
220 | {
221 | get { return postCrashScriptEnabled; }
222 | set
223 | {
224 | if (postCrashScriptEnabled == value)
225 | return;
226 |
227 | postCrashScriptEnabled = value;
228 | NotifyPropertyChanged(nameof(PostCrashScriptEnabled));
229 | }
230 | }
231 |
232 | public string PostCrashScriptPath
233 | {
234 | get { return postCrashScriptPath; }
235 | set
236 | {
237 | if (postCrashScriptPath == value || !value.IsFile())
238 | return;
239 |
240 | postCrashScriptPath = value;
241 | NotifyPropertyChanged(nameof(PostCrashScriptPath));
242 | }
243 | }
244 |
245 | public bool ScreenShotEnabled
246 | {
247 | get { return screenShotEnabled; }
248 | set
249 | {
250 | if (screenShotEnabled == value)
251 | return;
252 |
253 | screenShotEnabled = value;
254 | NotifyPropertyChanged(nameof(ScreenShotEnabled));
255 | }
256 | }
257 |
258 | public bool AlwaysOnTopEnabled
259 | {
260 | get { return alwaysOnTopEnabled; }
261 | set
262 | {
263 | if (alwaysOnTopEnabled == value)
264 | return;
265 |
266 | alwaysOnTopEnabled = value;
267 | NotifyPropertyChanged(nameof(AlwaysOnTopEnabled));
268 | }
269 | }
270 |
271 | public bool CommandLineEnabled
272 | {
273 | get { return commandLineEnabled; }
274 | set
275 | {
276 | if (commandLineEnabled == value)
277 | return;
278 |
279 | commandLineEnabled = value;
280 | NotifyPropertyChanged(nameof(CommandLineEnabled));
281 | }
282 | }
283 |
284 | public string CommandLine
285 | {
286 | get { return commandLine; }
287 | set
288 | {
289 | if (commandLine == value)
290 | return;
291 |
292 | commandLine = value;
293 | NotifyPropertyChanged(nameof(CommandLine));
294 | }
295 | }
296 |
297 | public bool EnvironmentVariablesEnabled
298 | {
299 | get { return environmentVariablesEnabled; }
300 | set
301 | {
302 | if (environmentVariablesEnabled == value)
303 | return;
304 |
305 | environmentVariablesEnabled = value;
306 | NotifyPropertyChanged(nameof(EnvironmentVariablesEnabled));
307 | }
308 | }
309 |
310 | public string EnvironmentVariables
311 | {
312 | get { return environmentVariables.ToColonDelimitedString(); }
313 | set
314 | {
315 | if (environmentVariables.FromColonDelimitedString(value))
316 | NotifyPropertyChanged(nameof(EnvironmentVariables));
317 | }
318 | }
319 |
320 | public string InitialState
321 | {
322 | get { return initialState.ToString(); }
323 | set
324 | {
325 | ProcessRunner.Status status;
326 | if (Enum.TryParse(value, true, out status))
327 | {
328 | if (status == initialState)
329 | return;
330 |
331 | initialState = status;
332 | NotifyPropertyChanged(nameof(InitialState));
333 | }
334 | else
335 | {
336 | initialState = ProcessRunner.Status.Invalid;
337 | NotifyPropertyChanged(nameof(InitialState));
338 | }
339 | }
340 | }
341 |
342 | [XmlIgnore]
343 | public ProcessRunner.Status InitialStateEnumValue
344 | {
345 | get { return initialState; }
346 | set
347 | {
348 | if (value == initialState)
349 | return;
350 |
351 | initialState = value;
352 | NotifyPropertyChanged(nameof(InitialState));
353 | }
354 | }
355 |
356 | [XmlIgnore]
357 | public Dictionary EnvironmentVariablesDictionary
358 | {
359 | get { return environmentVariables; }
360 | }
361 |
362 | #endregion
363 |
364 | #region ICloneable support
365 |
366 | public object Clone()
367 | {
368 | ProcessOptions clone = new ProcessOptions(environmentVariables);
369 |
370 | clone.path = Path;
371 | clone.workingDirectory = WorkingDirectory;
372 | clone.crashedIfNotRunning = CrashedIfNotRunning;
373 | clone.crashedIfUnresponsive = CrashedIfUnresponsive;
374 | clone.doubleCheckEnabled = DoubleCheckEnabled;
375 | clone.doubleCheckDuration = DoubleCheckDuration;
376 | clone.gracePeriodEnabled = GracePeriodEnabled;
377 | clone.gracePeriodDuration = GracePeriodDuration;
378 | clone.preLaunchScriptEnabled = PreLaunchScriptEnabled;
379 | clone.preLaunchScriptPath = PreLaunchScriptPath;
380 | clone.aggressiveCleanupEnabled = AggressiveCleanupEnabled;
381 | clone.postCrashScriptEnabled = PostCrashScriptEnabled;
382 | clone.postCrashScriptPath = PostCrashScriptPath;
383 | clone.screenShotEnabled = ScreenShotEnabled;
384 | clone.alwaysOnTopEnabled = AlwaysOnTopEnabled;
385 | clone.commandLineEnabled = CommandLineEnabled;
386 | clone.commandLine = CommandLine;
387 | clone.environmentVariablesEnabled = EnvironmentVariablesEnabled;
388 | clone.initialState = InitialStateEnumValue;
389 |
390 | return clone;
391 | }
392 |
393 | #endregion
394 |
395 | #region INotifyPropertyChanged support
396 |
397 | public event PropertyChangedEventHandler PropertyChanged;
398 |
399 | protected void NotifyPropertyChanged(string propertyName)
400 | {
401 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
402 | }
403 |
404 | #endregion
405 | }
406 | }
407 |
--------------------------------------------------------------------------------
/libOpenRoC/ProcessRunner.cs:
--------------------------------------------------------------------------------
1 | namespace liboroc
2 | {
3 | using System;
4 | using System.Timers;
5 | using System.Diagnostics;
6 | using System.ComponentModel;
7 | using Signal = System.Threading.ManualResetEventSlim;
8 |
9 | public class ProcessRunner : IDisposable, INotifyPropertyChanged
10 | {
11 | Status currentState;
12 | Status previousState;
13 | Signal crashSignal;
14 | Signal startSignal;
15 | Signal checkSignal;
16 | Signal resetTimer;
17 | Timer gracePeriodTimer;
18 | Timer doubleCheckTimer;
19 | ProcessOptions options;
20 |
21 | public Action StateChanged;
22 | public Action OptionsChanged;
23 | public Action ProcessChanged;
24 | public Action ProcessCrashed;
25 |
26 | public enum Status
27 | {
28 | Running = 0,
29 | Disabled = 1,
30 | Stopped = 2,
31 | Invalid = 3
32 | }
33 |
34 | public Status State
35 | {
36 | get { return currentState; }
37 | set
38 | {
39 | if (value == State)
40 | return;
41 |
42 | options.InitialStateEnumValue = value;
43 | previousState = currentState;
44 | currentState = value;
45 | ResetTimers();
46 |
47 | NotifyPropertyChanged(nameof(State));
48 | }
49 | }
50 |
51 | public Process Process { get; private set; }
52 |
53 | public Stopwatch Stopwatch { get; private set; }
54 |
55 | public bool HasWindow { get; private set; } = false;
56 |
57 | public ProcessOptions ProcessOptions
58 | {
59 | get { return options.Clone() as ProcessOptions; }
60 | set { SwapOptions(value.Clone() as ProcessOptions); }
61 | }
62 |
63 | public ProcessRunner(ProcessOptions opts)
64 | {
65 | Stopwatch = new Stopwatch();
66 | currentState = opts.InitialStateEnumValue;
67 | previousState = Status.Invalid;
68 | resetTimer = new Signal(true);
69 | startSignal = new Signal(false);
70 | checkSignal = new Signal(false);
71 | crashSignal = new Signal(false);
72 | options = opts.Clone() as ProcessOptions;
73 | gracePeriodTimer = new Timer { AutoReset = false, Enabled = false };
74 | doubleCheckTimer = new Timer { AutoReset = false, Enabled = false };
75 | gracePeriodTimer.Elapsed += OnGracePeriodTimeElapsed;
76 | doubleCheckTimer.Elapsed += OnDoubleCheckTimeElapsed;
77 | SetupOptions();
78 | }
79 |
80 | private void SwapOptions(ProcessOptions opts)
81 | {
82 | Stop();
83 | options = opts;
84 | State = opts.InitialStateEnumValue;
85 | SetupOptions();
86 |
87 | NotifyPropertyChanged(nameof(ProcessOptions));
88 | }
89 |
90 | private void SetupOptions()
91 | {
92 | if (currentState == Status.Invalid)
93 | {
94 | currentState = Status.Stopped;
95 | }
96 |
97 | if (options.InitialStateEnumValue == Status.Running)
98 | startSignal.Set();
99 |
100 | if (options.GracePeriodEnabled)
101 | gracePeriodTimer.Interval = TimeSpan.FromSeconds(options.GracePeriodDuration).TotalMilliseconds;
102 |
103 | if (options.DoubleCheckEnabled)
104 | doubleCheckTimer.Interval = TimeSpan.FromSeconds(options.DoubleCheckDuration).TotalMilliseconds;
105 |
106 | ResetTimers();
107 | }
108 |
109 | public void RestoreState()
110 | {
111 | if (previousState == Status.Invalid)
112 | State = Status.Stopped;
113 | else State = previousState;
114 | }
115 |
116 | public void Start()
117 | {
118 | if (Process != null)
119 | {
120 | Stop();
121 | }
122 |
123 | if (options.PreLaunchScriptEnabled)
124 | {
125 | ProcessHelper.ExecuteScript(options.PreLaunchScriptPath);
126 | }
127 |
128 | ProcessStartInfo sinfo = new ProcessStartInfo
129 | {
130 | WorkingDirectory = options.WorkingDirectory,
131 | FileName = options.Path,
132 | UseShellExecute = false
133 | };
134 |
135 | if (options.CommandLineEnabled &&
136 | !string.IsNullOrWhiteSpace(options.CommandLine))
137 | {
138 | sinfo.Arguments = options.CommandLine;
139 | }
140 |
141 | if (options.EnvironmentVariablesEnabled &&
142 | options.EnvironmentVariablesDictionary.Count > 0)
143 | {
144 | foreach (var pair in options.EnvironmentVariablesDictionary)
145 | sinfo.EnvironmentVariables.Add(pair.Key, pair.Value);
146 | }
147 |
148 | Process = new Process
149 | {
150 | StartInfo = sinfo,
151 | EnableRaisingEvents = true
152 | };
153 |
154 | Process.Disposed += OnProcessStopped;
155 | Process.Exited += OnProcessStopped;
156 |
157 | Process.Start();
158 | Process.Refresh();
159 |
160 | try
161 | {
162 | Process.WaitForInputIdle();
163 | HasWindow = true;
164 | }
165 | catch (Exception)
166 | {
167 | HasWindow = false;
168 | }
169 |
170 | if (!HasWindow || Process.Responding)
171 | {
172 | State = Status.Invalid;
173 | State = Status.Running;
174 |
175 | NotifyPropertyChanged(nameof(Process));
176 | }
177 | else
178 | {
179 | Stop();
180 | }
181 | }
182 |
183 | public void Stop()
184 | {
185 | if (Process == null)
186 | {
187 | if (!IsDisposed && State != Status.Stopped)
188 | {
189 | State = Status.Stopped;
190 | }
191 |
192 | return;
193 | }
194 |
195 | HasWindow = false;
196 | gracePeriodTimer.Stop();
197 | doubleCheckTimer.Stop();
198 |
199 | Process.Refresh();
200 |
201 | Process.EnableRaisingEvents = false;
202 | Process.Disposed -= OnProcessStopped;
203 | Process.Exited -= OnProcessStopped;
204 |
205 | int process_id = 0;
206 | var process_exit_timeout = (int)TimeSpan.FromSeconds(1).TotalMilliseconds;
207 |
208 | if (!Process.HasExited)
209 | {
210 | process_id = Process.Id;
211 |
212 | Process.CloseMainWindow();
213 | Process.WaitForExit(process_exit_timeout);
214 |
215 | if (options.AggressiveCleanupEnabled)
216 | {
217 | ProcessHelper.Shutdown(process_id);
218 | }
219 |
220 | if (!Process.HasExited)
221 | {
222 | Process.Kill();
223 | Process.WaitForExit(process_exit_timeout);
224 | }
225 | }
226 |
227 | Process.Dispose();
228 | Process = null;
229 |
230 | NotifyPropertyChanged(nameof(Process));
231 |
232 | if (!IsDisposed)
233 | {
234 | State = Status.Invalid;
235 | State = Status.Stopped;
236 | }
237 |
238 | if (options.PostCrashScriptEnabled)
239 | {
240 | ProcessHelper.ExecuteScript(options.PostCrashScriptPath);
241 | }
242 | }
243 |
244 | public void Monitor()
245 | {
246 | if (crashSignal.IsSet)
247 | {
248 | ProcessCrashed?.Invoke();
249 |
250 | Stop();
251 |
252 | if (options.GracePeriodEnabled)
253 | {
254 | if (!gracePeriodTimer.Enabled)
255 | {
256 | gracePeriodTimer.Start();
257 | }
258 | }
259 | else
260 | {
261 | startSignal.Set();
262 | }
263 |
264 | crashSignal.Reset();
265 | }
266 |
267 | if (resetTimer.IsSet)
268 | {
269 | Stopwatch.Restart();
270 | resetTimer.Reset();
271 | }
272 |
273 | if (ShouldStart)
274 | {
275 | if (startSignal.IsSet)
276 | startSignal.Reset();
277 |
278 | Start();
279 | }
280 |
281 | if (previousState == Status.Running && Process != null)
282 | {
283 | if (currentState != Status.Running)
284 | {
285 | Status previousStateSnapshot = previousState;
286 | Status currentStateSnapshot = currentState;
287 |
288 | Stop();
289 |
290 | State = previousStateSnapshot;
291 | State = currentStateSnapshot;
292 | }
293 | }
294 | else
295 | if (previousState == Status.Stopped && Process == null)
296 | {
297 | if (currentState == Status.Running)
298 | Start();
299 | }
300 | else
301 | if (previousState == Status.Disabled && Process == null)
302 | {
303 | if (currentState == Status.Running)
304 | Start();
305 | }
306 |
307 | if (currentState != Status.Disabled && HasWindow && Process != null)
308 | {
309 | Process.Refresh();
310 |
311 | if (options.CrashedIfUnresponsive && !Process.Responding)
312 | {
313 | if (options.DoubleCheckEnabled)
314 | {
315 | if (checkSignal.IsSet)
316 | {
317 | if (!Process.Responding)
318 | {
319 | startSignal.Set();
320 | }
321 |
322 | checkSignal.Reset();
323 | }
324 | else if (!doubleCheckTimer.Enabled)
325 | {
326 | doubleCheckTimer.Start();
327 | }
328 | }
329 | else
330 | {
331 | startSignal.Set();
332 | }
333 |
334 | if (startSignal.IsSet)
335 | {
336 | Stop();
337 | }
338 | }
339 |
340 | if (options.AlwaysOnTopEnabled && Process != null && Process.Responding)
341 | {
342 | BringToFront(true);
343 | }
344 | }
345 | }
346 |
347 | public void BringToFront(bool aggressive = false)
348 | {
349 | if (Process == null)
350 | return;
351 |
352 | ProcessHelper.BringToFront(Process.Id, aggressive);
353 | }
354 |
355 | private void ResetTimers()
356 | {
357 | resetTimer.Set();
358 | gracePeriodTimer.Stop();
359 | doubleCheckTimer.Stop();
360 | }
361 |
362 | private bool ShouldStart
363 | {
364 | get { return (Process == null) &&
365 | (startSignal.IsSet ||
366 | (State == Status.Running &&
367 | options.CrashedIfNotRunning &&
368 | !gracePeriodTimer.Enabled)); }
369 | }
370 |
371 | #region Event callbacks
372 |
373 | private void OnProcessStopped(object sender, EventArgs e)
374 | {
375 | crashSignal.Set();
376 | gracePeriodTimer.Stop();
377 | }
378 |
379 | private void OnDoubleCheckTimeElapsed(object sender, ElapsedEventArgs e)
380 | {
381 | checkSignal.Set();
382 | doubleCheckTimer.Stop();
383 | }
384 |
385 | private void OnGracePeriodTimeElapsed(object sender, ElapsedEventArgs e)
386 | {
387 | startSignal.Set();
388 | gracePeriodTimer.Stop();
389 | }
390 |
391 | #endregion
392 |
393 | #region INotifyPropertyChanged support
394 |
395 | public event PropertyChangedEventHandler PropertyChanged;
396 |
397 | protected void NotifyPropertyChanged(string propertyName)
398 | {
399 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
400 |
401 | if (propertyName == nameof(State))
402 | StateChanged?.Invoke();
403 |
404 | else if (propertyName == nameof(ProcessOptions))
405 | OptionsChanged?.Invoke();
406 |
407 | else if (propertyName == nameof(Process))
408 | ProcessChanged?.Invoke();
409 | }
410 |
411 | #endregion
412 |
413 | #region IDisposable Support
414 |
415 | public bool IsDisposed { get; private set; } = false;
416 |
417 | protected virtual void Dispose(bool disposing)
418 | {
419 | if (!IsDisposed)
420 | {
421 | IsDisposed = true;
422 |
423 | if (disposing)
424 | {
425 | ResetTimers();
426 | Stop();
427 |
428 | gracePeriodTimer?.Dispose();
429 | doubleCheckTimer?.Dispose();
430 | crashSignal?.Dispose();
431 | startSignal?.Dispose();
432 | checkSignal?.Dispose();
433 | resetTimer?.Dispose();
434 | }
435 |
436 | gracePeriodTimer = null;
437 | doubleCheckTimer = null;
438 | crashSignal = null;
439 | startSignal = null;
440 | checkSignal = null;
441 | resetTimer = null;
442 | }
443 | }
444 |
445 | public void Dispose()
446 | {
447 | Dispose(true);
448 | }
449 |
450 | #endregion
451 | }
452 | }
453 |
--------------------------------------------------------------------------------
/libOpenRoC/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("libOpenRoC")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("libOpenRoC")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("90c91845-e5ae-42d2-8cad-e52564c344d0")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/libOpenRoC/libOpenRoC.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {90C91845-E5AE-42D2-8CAD-E52564C344D0}
8 | Library
9 | Properties
10 | liboroc
11 | libOpenRoC
12 | v4.5.2
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
57 |
--------------------------------------------------------------------------------
/testOpenRoC/.gitignore:
--------------------------------------------------------------------------------
1 | /processes
2 |
--------------------------------------------------------------------------------
/testOpenRoC/ExecutorServiceUnitTests.cs:
--------------------------------------------------------------------------------
1 | namespace testOpenRoC
2 | {
3 | using liboroc;
4 |
5 | using System;
6 | using System.Threading;
7 |
8 | using Microsoft.VisualStudio.TestTools.UnitTesting;
9 |
10 | [TestClass]
11 | public class ExecutorServiceUnitTests
12 | {
13 | [TestMethod]
14 | public void WaitForPending()
15 | {
16 | bool flag1 = false;
17 | bool flag2 = false;
18 |
19 | using (ExecutorService service = new ExecutorService())
20 | {
21 | service.Accept(() => { Thread.Sleep(TimeSpan.FromSeconds(1)); flag1 = true; });
22 | service.Accept(() => { Thread.Sleep(TimeSpan.FromSeconds(1)); flag2 = true; });
23 | }
24 |
25 | Assert.IsTrue(flag1);
26 | Assert.IsTrue(flag2);
27 | }
28 |
29 | [TestMethod]
30 | public void WaitAfterException()
31 | {
32 | bool flag1 = false;
33 | bool flag2 = false;
34 |
35 | using (ExecutorService service = new ExecutorService())
36 | {
37 | service.Accept(() =>
38 | {
39 | Thread.Sleep(TimeSpan.FromSeconds(1));
40 | throw new Exception();
41 |
42 | });
43 | service.Accept(() => { Thread.Sleep(TimeSpan.FromSeconds(1)); flag2 = true; });
44 | }
45 |
46 | Assert.IsFalse(flag1);
47 | Assert.IsTrue(flag2);
48 | }
49 |
50 | [TestMethod]
51 | public void ExceptionPropagation()
52 | {
53 | Exception ex1 = new Exception();
54 | Exception ex2 = null;
55 |
56 | using (ExecutorService service = new ExecutorService())
57 | {
58 | service.ExceptionReceived += (ex) =>
59 | {
60 | ex2 = ex;
61 | };
62 |
63 | service.Accept(() =>
64 | {
65 | Thread.Sleep(TimeSpan.FromSeconds(1));
66 | throw ex1;
67 |
68 | });
69 | }
70 |
71 | Assert.IsTrue(ReferenceEquals(ex1, ex2));
72 | }
73 |
74 | [TestMethod]
75 | public void DiposedAccess()
76 | {
77 | bool flag1 = false;
78 | bool flag2 = false;
79 |
80 | using (ExecutorService service = new ExecutorService())
81 | {
82 | service.Dispose();
83 | service.Accept(() => { Thread.Sleep(TimeSpan.FromSeconds(1)); flag1 = true; });
84 | service.Accept(() => { Thread.Sleep(TimeSpan.FromSeconds(1)); flag2 = true; });
85 | service.Wait();
86 | }
87 |
88 | Assert.IsFalse(flag1);
89 | Assert.IsFalse(flag2);
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/testOpenRoC/ProcessManagerUnitTests.cs:
--------------------------------------------------------------------------------
1 | namespace testOpenRoC
2 | {
3 | using liboroc;
4 |
5 | using System.Linq;
6 |
7 | using Microsoft.VisualStudio.TestTools.UnitTesting;
8 |
9 | [TestClass]
10 | public class ProcessManagerUnitTests
11 | {
12 | [TestMethod]
13 | public void AddingRunners()
14 | {
15 | using (var manager = new ProcessManager())
16 | {
17 | int addedCount = 0;
18 | bool addedEventCalled = false;
19 | bool changeEventCalled = false;
20 |
21 | manager.ProcessesChanged += () => { changeEventCalled = true; };
22 | manager.RunnerAdded += (runner) => { addedEventCalled = true; ++addedCount; };
23 | manager.Add(ProcessRunnerUnitTests.ResponsiveWindowedProcessOptions);
24 |
25 | Assert.IsTrue(manager.Contains(ProcessRunnerUnitTests.TestProcessWindowedPath));
26 | Assert.IsTrue(manager.Runners.Contains(manager.Get(ProcessRunnerUnitTests.TestProcessWindowedPath)));
27 | Assert.IsTrue(manager.Options.Select(opt => opt.Path).Contains(ProcessRunnerUnitTests.TestProcessWindowedPath));
28 | Assert.IsTrue(addedEventCalled);
29 | Assert.IsTrue(changeEventCalled);
30 |
31 | manager.Add(ProcessRunnerUnitTests.ResponsiveWindowedProcessOptions);
32 | Assert.AreEqual(addedCount, 1);
33 |
34 | Assert.IsFalse(manager.Contains(null));
35 | Assert.IsFalse(manager.Contains(""));
36 | }
37 | }
38 |
39 | [TestMethod]
40 | public void RemovingRunners()
41 | {
42 | using (var manager = new ProcessManager())
43 | {
44 | int removedCount = 0;
45 | bool removedEventCalled = false;
46 | bool changeEventCalled = false;
47 |
48 | manager.RunnerRemoved += (runner) => { removedEventCalled = true; ++removedCount; };
49 | manager.Add(ProcessRunnerUnitTests.ResponsiveWindowedProcessOptions);
50 | manager.ProcessesChanged += () => { changeEventCalled = true; };
51 |
52 | manager.Remove(ProcessRunnerUnitTests.TestProcessWindowedPath);
53 | Assert.IsTrue(removedEventCalled);
54 | Assert.IsTrue(changeEventCalled);
55 |
56 | manager.Remove(ProcessRunnerUnitTests.TestProcessWindowedPath);
57 | Assert.AreEqual(removedCount, 1);
58 | }
59 | }
60 |
61 | [TestMethod]
62 | public void DisposingRemovedRunners()
63 | {
64 | using (var manager = new ProcessManager())
65 | {
66 | manager.Add(ProcessRunnerUnitTests.ResponsiveWindowedProcessOptions);
67 | var runner = manager.Get(ProcessRunnerUnitTests.TestProcessWindowedPath);
68 | manager.Remove(ProcessRunnerUnitTests.TestProcessWindowedPath);
69 |
70 | Assert.IsTrue(runner.IsDisposed);
71 | }
72 | }
73 |
74 | [TestMethod]
75 | public void GettingRunners()
76 | {
77 | using (var manager = new ProcessManager())
78 | {
79 | Assert.IsNull(manager.Get(ProcessRunnerUnitTests.TestProcessWindowedPath));
80 | manager.Add(ProcessRunnerUnitTests.ResponsiveWindowedProcessOptions);
81 | Assert.IsNotNull(manager.Get(ProcessRunnerUnitTests.TestProcessWindowedPath));
82 | }
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/testOpenRoC/ProcessOptionsUnitTests.cs:
--------------------------------------------------------------------------------
1 | namespace testOpenRoC
2 | {
3 | using liboroc;
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 |
6 | [TestClass]
7 | public class ProcessOptionsUnitTests
8 | {
9 | [TestMethod]
10 | public void EnvironmentVariableValidFormat()
11 | {
12 | ProcessOptions options = new ProcessOptions();
13 |
14 | const string var1_name = "var1";
15 | const string var2_name = "var2";
16 | const string var1_value = "val1";
17 | const string var2_value = "val2";
18 | string variables = string.Format("{0}={1};{2}={3}",
19 | var1_name, var1_value, var2_name, var2_value);
20 |
21 | options.EnvironmentVariables = variables;
22 |
23 | Assert.AreEqual(options.EnvironmentVariablesDictionary.Count, 2);
24 | Assert.AreEqual(options.EnvironmentVariablesDictionary[var1_name], var1_value);
25 | Assert.AreEqual(options.EnvironmentVariablesDictionary[var2_name], var2_value);
26 | }
27 |
28 | [TestMethod]
29 | public void EnvironmentVariableFromDictionary()
30 | {
31 | ProcessOptions options = new ProcessOptions();
32 |
33 | const string var1_name = "var1";
34 | const string var2_name = "var2";
35 | const string var1_value = "val1";
36 | const string var2_value = "val2";
37 | string variables = string.Format("{0}={1};{2}={3}",
38 | var1_name, var1_value, var2_name, var2_value);
39 |
40 | options.EnvironmentVariablesDictionary.Add(var1_name, var1_value);
41 | options.EnvironmentVariablesDictionary.Add(var2_name, var2_value);
42 |
43 | Assert.AreEqual(options.EnvironmentVariables, variables);
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/testOpenRoC/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("testOpenRoC")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("testOpenRoC")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("67901a36-b033-42d1-9651-02e1535fd389")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/testOpenRoC/testOpenRoC.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {67901A36-B033-42D1-9651-02E1535FD389}
7 | Library
8 | Properties
9 | testOpenRoC
10 | testOpenRoC
11 | v4.5.2
12 | 512
13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 10.0
15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
17 | False
18 | UnitTest
19 |
20 |
21 | true
22 | full
23 | false
24 | bin\Debug\
25 | DEBUG;TRACE
26 | prompt
27 | 4
28 |
29 |
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
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 | {90c91845-e5ae-42d2-8cad-e52564c344d0}
62 | libOpenRoC
63 |
64 |
65 |
66 |
67 |
68 |
69 | False
70 |
71 |
72 | False
73 |
74 |
75 | False
76 |
77 |
78 | False
79 |
80 |
81 |
82 |
83 |
84 |
85 |
92 |
--------------------------------------------------------------------------------