internal GameStateWatcher(string gameInstallFolder, string gameOptionsFolder, string journalFolder, INativeMethods nativeMethods) { var gif = new GameInstallFolder(gameInstallFolder); var gof = new GameOptionsFolder(gameOptionsFolder); var jf = new JournalFolder(journalFolder); _journalWatcher = new JournalWatcher(jf); _journalWatcher.Started += JournalWatcher_Started; _journalWatcher.EntryAdded += JournalWatcher_EntryAdded; _statusWatcher = new StatusWatcher(jf); _statusWatcher.Changed += StatusWatcher_Changed; _bindingsWatcher = new BindingsWatcher(gif, gof); _bindingsWatcher.Changed += BindingsWatcher_Changed; _graphicsConfig = new GraphicsConfigWatcher(gif, gof); _graphicsConfig.Changed += GraphicsConfig_Changed; _modifierKeysWatcher = new ModifierKeysWatcher(nativeMethods); _modifierKeysWatcher.Changed += ModifierKeysWatcher_Changed; _gameProcessWatcher = new GameProcessWatcher(gif, nativeMethods); _gameProcessWatcher.Changed += GameProcessWatcher_Changed; _gameState = new GameState(); }
public void WatchesForGameProcessChanges() { var nm = new NativeMethodsMock() { Processes = { [0] = "System", [1000] = "Process 1000", [2000] = _gif.MainExecutable.FullName, }, }; using var gpw = new GameProcessWatcher(_gif, nm); var evs = new EventCollector <GameProcessState>(h => gpw.Changed += h, h => gpw.Changed -= h, nameof(WatchesForGameProcessChanges)); var pss = evs.Wait(3, () => { InvokeTimerElapsed(gpw); nm.ForegroundWindow = new IntPtr(2000); InvokeTimerElapsed(gpw); nm.ForegroundWindow = new IntPtr(1000); InvokeTimerElapsed(gpw); }); Assert.Equal(GameProcessState.NotRunning, pss[0]); Assert.Equal(GameProcessState.InForeground, pss[1]); Assert.Equal(GameProcessState.InBackground, pss[2]); }
private static void InvokeTimerElapsed(GameProcessWatcher instance) { // HACK: Hopefully will no longer be needed when .NET 5.0 arrives (https://github.com/dotnet/runtime/issues/31204) var e = (ElapsedEventArgs)_ciElapsedEventArgs.Invoke(new object[] { DateTime.Now.ToFileTime() }); _miTimerElapsed.Invoke(instance, new object[] { instance, e }); }
public void DoesNotThrowWhenDisposingTwice() { var pw = new GameProcessWatcher(_gif, new NativeMethodsMock()); #pragma warning disable IDISP016, IDISP017 pw.Dispose(); pw.Dispose(); #pragma warning restore IDISP016, IDISP017 }
public void StartAndStopAreNotReentrant() { using var gpw = new GameProcessWatcher(_gif, new NativeMethodsMock()); bool IsRunning() => gpw.GetPrivateField <bool>("_running"); Assert.False(IsRunning()); gpw.Start(); Assert.True(IsRunning()); gpw.Start(); Assert.True(IsRunning()); gpw.Stop(); Assert.False(IsRunning()); gpw.Stop(); Assert.False(IsRunning()); }
public void OnChangedIsNotReentrant() { var nm = new NativeMethodsMock() { Processes = { [0] = "System", [1000] = "Process 1000", [2000] = _gif.MainExecutable.FullName, }, }; using var gpw = new GameProcessWatcher(_gif, nm); var nOnChangedCalls = 0; using var mre = new ManualResetEventSlim(); gpw.Changed += (sender, e) => { Interlocked.Increment(ref nOnChangedCalls); mre.Wait(); }; void TimerElapsed(int pid) { nm.ForegroundWindow = new IntPtr(pid); InvokeTimerElapsed(gpw); mre.Set(); } Task.WaitAll(new[] { Task.Run(() => TimerElapsed(1000)), Task.Run(() => TimerElapsed(2000)), }); Assert.Equal(1, nOnChangedCalls); }