diff --git a/Emby.Common.Implementations/BaseApplicationHost.cs b/Emby.Common.Implementations/BaseApplicationHost.cs
index 2fe82e5a4f..897557efd3 100644
--- a/Emby.Common.Implementations/BaseApplicationHost.cs
+++ b/Emby.Common.Implementations/BaseApplicationHost.cs
@@ -27,11 +27,16 @@ using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Extensions;
using Emby.Common.Implementations.Cryptography;
+using Emby.Common.Implementations.Diagnostics;
+using Emby.Common.Implementations.Threading;
using MediaBrowser.Common;
using MediaBrowser.Common.IO;
using MediaBrowser.Model.Cryptography;
+using MediaBrowser.Model.Diagnostics;
using MediaBrowser.Model.System;
using MediaBrowser.Model.Tasks;
+using MediaBrowser.Model.Threading;
+
#if NETSTANDARD1_6
using System.Runtime.Loader;
#endif
@@ -146,6 +151,9 @@ namespace Emby.Common.Implementations
protected ISystemEvents SystemEvents { get; private set; }
+ protected IProcessFactory ProcessFactory { get; private set; }
+ protected ITimerFactory TimerFactory { get; private set; }
+
///
/// Gets the name.
///
@@ -535,6 +543,12 @@ return null;
IsoManager = new IsoManager();
RegisterSingleInstance(IsoManager);
+ ProcessFactory = new ProcessFactory();
+ RegisterSingleInstance(ProcessFactory);
+
+ TimerFactory = new TimerFactory();
+ RegisterSingleInstance(TimerFactory);
+
return Task.FromResult(true);
}
diff --git a/Emby.Common.Implementations/Diagnostics/CommonProcess.cs b/Emby.Common.Implementations/Diagnostics/CommonProcess.cs
new file mode 100644
index 0000000000..06677bc298
--- /dev/null
+++ b/Emby.Common.Implementations/Diagnostics/CommonProcess.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using MediaBrowser.Model.Diagnostics;
+
+namespace Emby.Common.Implementations.Diagnostics
+{
+ public class CommonProcess : IProcess
+ {
+ public event EventHandler Exited;
+
+ private readonly ProcessOptions _options;
+ private readonly Process _process;
+
+ public CommonProcess(ProcessOptions options)
+ {
+ _options = options;
+
+ var startInfo = new ProcessStartInfo
+ {
+ Arguments = options.Arguments,
+ FileName = options.FileName,
+ WorkingDirectory = options.WorkingDirectory,
+ UseShellExecute = options.UseShellExecute,
+ CreateNoWindow = options.CreateNoWindow,
+ RedirectStandardError = options.RedirectStandardError,
+ RedirectStandardInput = options.RedirectStandardInput,
+ RedirectStandardOutput = options.RedirectStandardOutput
+ };
+
+#if NET46
+ startInfo.ErrorDialog = options.ErrorDialog;
+
+ if (options.IsHidden)
+ {
+ startInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ }
+#endif
+
+ _process = new Process
+ {
+ StartInfo = startInfo
+ };
+
+ if (options.EnableRaisingEvents)
+ {
+ _process.EnableRaisingEvents = true;
+ _process.Exited += _process_Exited;
+ }
+ }
+
+ private void _process_Exited(object sender, EventArgs e)
+ {
+ if (Exited != null)
+ {
+ Exited(_process, e);
+ }
+ }
+
+ public ProcessOptions StartInfo
+ {
+ get { return _options; }
+ }
+
+ public StreamWriter StandardInput
+ {
+ get { return _process.StandardInput; }
+ }
+
+ public StreamReader StandardError
+ {
+ get { return _process.StandardError; }
+ }
+
+ public StreamReader StandardOutput
+ {
+ get { return _process.StandardOutput; }
+ }
+
+ public int ExitCode
+ {
+ get { return _process.ExitCode; }
+ }
+
+ public void Start()
+ {
+ _process.Start();
+ }
+
+ public void Kill()
+ {
+ _process.Kill();
+ }
+
+ public bool WaitForExit(int timeMs)
+ {
+ return _process.WaitForExit(timeMs);
+ }
+
+ public void Dispose()
+ {
+ _process.Dispose();
+ }
+ }
+}
diff --git a/Emby.Common.Implementations/Diagnostics/ProcessFactory.cs b/Emby.Common.Implementations/Diagnostics/ProcessFactory.cs
new file mode 100644
index 0000000000..292da023c7
--- /dev/null
+++ b/Emby.Common.Implementations/Diagnostics/ProcessFactory.cs
@@ -0,0 +1,12 @@
+using MediaBrowser.Model.Diagnostics;
+
+namespace Emby.Common.Implementations.Diagnostics
+{
+ public class ProcessFactory : IProcessFactory
+ {
+ public IProcess Create(ProcessOptions options)
+ {
+ return new CommonProcess(options);
+ }
+ }
+}
diff --git a/Emby.Common.Implementations/Threading/CommonTimer.cs b/Emby.Common.Implementations/Threading/CommonTimer.cs
new file mode 100644
index 0000000000..8895f6798a
--- /dev/null
+++ b/Emby.Common.Implementations/Threading/CommonTimer.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Model.Threading;
+
+namespace Emby.Common.Implementations.Threading
+{
+ public class CommonTimer : ITimer
+ {
+ private readonly Timer _timer;
+
+ public CommonTimer(Action