diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeOperationTests.cs index 91db0ff1..7740fdaf 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeOperationTests.cs @@ -63,34 +63,38 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var getCurrrent = 0; var createNew = 0; var activate = 0; + var hide = 0; var setStartup = 0; - var suspend = 0; + var terminate = 0; nextSettings.Security.KioskMode = KioskMode.CreateNewDesktop; desktopFactory.Setup(f => f.GetCurrent()).Callback(() => getCurrrent = ++order).Returns(originalDesktop.Object); desktopFactory.Setup(f => f.CreateNew(It.IsAny())).Callback(() => createNew = ++order).Returns(newDesktop.Object); + explorerShell.Setup(s => s.HideAllWindows()).Callback(() => hide = ++order); + explorerShell.Setup(s => s.Terminate()).Callback(() => terminate = ++order); newDesktop.Setup(d => d.Activate()).Callback(() => activate = ++order); processFactory.SetupSet(f => f.StartupDesktop = It.IsAny()).Callback(() => setStartup = ++order); - explorerShell.Setup(s => s.Suspend()).Callback(() => suspend = ++order); var result = sut.Perform(); desktopFactory.Verify(f => f.GetCurrent(), Times.Once); desktopFactory.Verify(f => f.CreateNew(It.IsAny()), Times.Once); + explorerShell.Verify(s => s.Start(), Times.Never); + explorerShell.Verify(s => s.Terminate(), Times.Once); + explorerShell.Verify(s => s.HideAllWindows(), Times.Once); + explorerShell.Verify(s => s.RestoreAllWindows(), Times.Never); newDesktop.Verify(d => d.Activate(), Times.Once); processFactory.VerifySet(f => f.StartupDesktop = newDesktop.Object, Times.Once); - explorerShell.Verify(s => s.Suspend(), Times.Once); - explorerShell.Verify(s => s.Terminate(), Times.Never); - explorerShell.Verify(s => s.HideAllWindows(), Times.Never); Assert.AreEqual(OperationResult.Success, result); - Assert.AreEqual(1, getCurrrent); - Assert.AreEqual(2, createNew); - Assert.AreEqual(3, activate); - Assert.AreEqual(4, setStartup); - Assert.AreEqual(5, suspend); + Assert.AreEqual(1, hide); + Assert.AreEqual(2, terminate); + Assert.AreEqual(3, getCurrrent); + Assert.AreEqual(4, createNew); + Assert.AreEqual(5, activate); + Assert.AreEqual(6, setStartup); } [TestMethod] @@ -111,62 +115,236 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations } [TestMethod] - public void Repeat_MustCorrectlySwitchToNewKioskMode() + public void Repeat_MustCorrectlySwitchFromCreateNewDesktopToDisableExplorerShell() { var newDesktop = new Mock(); var originalDesktop = new Mock(); - var result = default(OperationResult); + var order = 0; + var activate = 0; + var close = 0; + var startup = 0; desktopFactory.Setup(f => f.GetCurrent()).Returns(originalDesktop.Object); desktopFactory.Setup(f => f.CreateNew(It.IsAny())).Returns(newDesktop.Object); nextSettings.Security.KioskMode = KioskMode.CreateNewDesktop; - result = sut.Perform(); + sut.Perform(); + + desktopFactory.Reset(); + explorerShell.Reset(); + newDesktop.Reset(); + newDesktop.Setup(d => d.Close()).Callback(() => close = ++order); + originalDesktop.Reset(); + originalDesktop.Setup(d => d.Activate()).Callback(() => activate = ++order); + processFactory.Reset(); + processFactory.SetupSet(f => f.StartupDesktop = It.Is(d => d == originalDesktop.Object)).Callback(() => startup = ++order); + nextSettings.Security.KioskMode = KioskMode.DisableExplorerShell; + + var result = sut.Repeat(); + + desktopFactory.VerifyNoOtherCalls(); + explorerShell.VerifyNoOtherCalls(); + newDesktop.Verify(d => d.Close(), Times.Once); + originalDesktop.Verify(d => d.Activate(), Times.Once); + processFactory.VerifySet(f => f.StartupDesktop = It.Is(d => d == originalDesktop.Object), Times.Once); Assert.AreEqual(OperationResult.Success, result); + Assert.AreEqual(1, activate); + Assert.AreEqual(2, startup); + Assert.AreEqual(3, close); + } - explorerShell.Verify(s => s.Terminate(), Times.Never); - explorerShell.Verify(s => s.Start(), Times.Never); - explorerShell.Verify(s => s.Resume(), Times.Never); - explorerShell.Verify(s => s.Suspend(), Times.Once); - explorerShell.Verify(s => s.HideAllWindows(), Times.Never); - explorerShell.Verify(s => s.RestoreAllWindows(), Times.Never); - newDesktop.Verify(d => d.Activate(), Times.Once); - newDesktop.Verify(d => d.Close(), Times.Never); - originalDesktop.Verify(d => d.Activate(), Times.Never); + [TestMethod] + public void Repeat_MustCorrectlySwitchFromCreateNewDesktopToNone() + { + var newDesktop = new Mock(); + var originalDesktop = new Mock(); + var order = 0; + var activate = 0; + var close = 0; + var restore = 0; + var start = 0; + var startupDesktop = 0; + + desktopFactory.Setup(f => f.GetCurrent()).Returns(originalDesktop.Object); + desktopFactory.Setup(f => f.CreateNew(It.IsAny())).Returns(newDesktop.Object); + nextSettings.Security.KioskMode = KioskMode.CreateNewDesktop; + + sut.Perform(); + + desktopFactory.Reset(); + explorerShell.Reset(); + explorerShell.Setup(s => s.RestoreAllWindows()).Callback(() => restore = ++order); + explorerShell.Setup(s => s.Start()).Callback(() => start = ++order); + newDesktop.Reset(); + newDesktop.Setup(d => d.Close()).Callback(() => close = ++order); + originalDesktop.Reset(); + originalDesktop.Setup(d => d.Activate()).Callback(() => activate = ++order); + processFactory.Reset(); + processFactory.SetupSet(f => f.StartupDesktop = It.Is(d => d == originalDesktop.Object)).Callback(() => startupDesktop = ++order); + nextSettings.Security.KioskMode = KioskMode.None; + + var result = sut.Repeat(); + + desktopFactory.VerifyNoOtherCalls(); + explorerShell.Verify(s => s.RestoreAllWindows(), Times.Once); + explorerShell.Verify(s => s.Start(), Times.Once); + newDesktop.Verify(d => d.Close(), Times.Once); + originalDesktop.Verify(d => d.Activate(), Times.Once); + processFactory.VerifySet(f => f.StartupDesktop = It.Is(d => d == originalDesktop.Object), Times.Once); + + Assert.AreEqual(OperationResult.Success, result); + Assert.AreEqual(1, activate); + Assert.AreEqual(2, startupDesktop); + Assert.AreEqual(3, close); + Assert.AreEqual(4, start); + Assert.AreEqual(5, restore); + } + + [TestMethod] + public void Repeat_MustCorrectlySwitchFromDisableExplorerShellToCreateNewDesktop() + { + var newDesktop = new Mock(); + var originalDesktop = new Mock(); + var order = 0; + var activate = 0; + var current = 0; + var startup = 0; nextSettings.Security.KioskMode = KioskMode.DisableExplorerShell; - result = sut.Repeat(); + sut.Perform(); - Assert.AreEqual(OperationResult.Success, result); - - explorerShell.Verify(s => s.Terminate(), Times.Once); - explorerShell.Verify(s => s.Start(), Times.Never); - explorerShell.Verify(s => s.Resume(), Times.Once); - explorerShell.Verify(s => s.Suspend(), Times.Once); - explorerShell.Verify(s => s.HideAllWindows(), Times.Once); - explorerShell.Verify(s => s.RestoreAllWindows(), Times.Never); - newDesktop.Verify(d => d.Activate(), Times.Once); - newDesktop.Verify(d => d.Close(), Times.Once); - originalDesktop.Verify(d => d.Activate(), Times.Once); - - currentSettings.Security.KioskMode = nextSettings.Security.KioskMode; + desktopFactory.Reset(); + desktopFactory.Setup(f => f.GetCurrent()).Returns(originalDesktop.Object).Callback(() => current = ++order); + desktopFactory.Setup(f => f.CreateNew(It.IsAny())).Returns(newDesktop.Object); + explorerShell.Reset(); + newDesktop.Reset(); + newDesktop.Setup(d => d.Activate()).Callback(() => activate = ++order); + originalDesktop.Reset(); + processFactory.Reset(); + processFactory.SetupSet(f => f.StartupDesktop = It.Is(d => d == newDesktop.Object)).Callback(() => startup = ++order); nextSettings.Security.KioskMode = KioskMode.CreateNewDesktop; - result = sut.Repeat(); + var result = sut.Repeat(); + + desktopFactory.Verify(f => f.GetCurrent(), Times.Once); + desktopFactory.Verify(f => f.CreateNew(It.IsAny()), Times.Once); + explorerShell.VerifyNoOtherCalls(); + newDesktop.Verify(d => d.Activate(), Times.Once); + originalDesktop.VerifyNoOtherCalls(); + processFactory.VerifySet(f => f.StartupDesktop = It.Is(d => d == newDesktop.Object), Times.Once); Assert.AreEqual(OperationResult.Success, result); + Assert.AreEqual(1, current); + Assert.AreEqual(2, activate); + Assert.AreEqual(3, startup); + } - explorerShell.Verify(s => s.Terminate(), Times.Once); - explorerShell.Verify(s => s.Start(), Times.Once); - explorerShell.Verify(s => s.Resume(), Times.Once); - explorerShell.Verify(s => s.Suspend(), Times.Exactly(2)); - explorerShell.Verify(s => s.HideAllWindows(), Times.Once); + [TestMethod] + public void Repeat_MustCorrectlySwitchFromDisableExplorerShellToNone() + { + var order = 0; + var restore = 0; + var start = 0; + + nextSettings.Security.KioskMode = KioskMode.DisableExplorerShell; + + sut.Perform(); + + explorerShell.Reset(); + explorerShell.Setup(s => s.RestoreAllWindows()).Callback(() => restore = ++order); + explorerShell.Setup(s => s.Start()).Callback(() => start = ++order); + processFactory.Reset(); + nextSettings.Security.KioskMode = KioskMode.None; + + var result = sut.Repeat(); + + desktopFactory.VerifyNoOtherCalls(); explorerShell.Verify(s => s.RestoreAllWindows(), Times.Once); - newDesktop.Verify(d => d.Activate(), Times.Exactly(2)); - newDesktop.Verify(d => d.Close(), Times.Once); - originalDesktop.Verify(d => d.Activate(), Times.Once); + explorerShell.Verify(s => s.Start(), Times.Once); + processFactory.VerifySet(f => f.StartupDesktop = It.IsAny(), Times.Never); + + Assert.AreEqual(OperationResult.Success, result); + Assert.AreEqual(1, start); + Assert.AreEqual(2, restore); + } + + [TestMethod] + public void Repeat_MustCorrectlySwitchFromNoneToCreateNewDesktop() + { + var newDesktop = new Mock(); + var originalDesktop = new Mock(); + var order = 0; + var activate = 0; + var current = 0; + var hide = 0; + var startup = 0; + var terminate = 0; + + nextSettings.Security.KioskMode = KioskMode.None; + + sut.Perform(); + + desktopFactory.Reset(); + desktopFactory.Setup(f => f.GetCurrent()).Returns(originalDesktop.Object).Callback(() => current = ++order); + desktopFactory.Setup(f => f.CreateNew(It.IsAny())).Returns(newDesktop.Object); + explorerShell.Reset(); + explorerShell.Setup(s => s.HideAllWindows()).Callback(() => hide = ++order); + explorerShell.Setup(s => s.Terminate()).Callback(() => terminate = ++order); + newDesktop.Reset(); + newDesktop.Setup(d => d.Activate()).Callback(() => activate = ++order); + originalDesktop.Reset(); + processFactory.Reset(); + processFactory.SetupSet(f => f.StartupDesktop = It.Is(d => d == newDesktop.Object)).Callback(() => startup = ++order); + nextSettings.Security.KioskMode = KioskMode.CreateNewDesktop; + + var result = sut.Repeat(); + + desktopFactory.Verify(f => f.GetCurrent(), Times.Once); + desktopFactory.Verify(f => f.CreateNew(It.IsAny()), Times.Once); + explorerShell.Verify(s => s.HideAllWindows(), Times.Once); + explorerShell.Verify(s => s.Terminate(), Times.Once); + newDesktop.Verify(d => d.Activate(), Times.Once); + originalDesktop.VerifyNoOtherCalls(); + processFactory.VerifySet(f => f.StartupDesktop = It.Is(d => d == newDesktop.Object), Times.Once); + + Assert.AreEqual(OperationResult.Success, result); + Assert.AreEqual(1, hide); + Assert.AreEqual(2, terminate); + Assert.AreEqual(3, current); + Assert.AreEqual(4, activate); + Assert.AreEqual(5, startup); + } + + [TestMethod] + public void Repeat_MustCorrectlySwitchFromNoneToDisableExplorerShell() + { + var order = 0; + var hide = 0; + var terminate = 0; + + nextSettings.Security.KioskMode = KioskMode.None; + + sut.Perform(); + + desktopFactory.Reset(); + explorerShell.Reset(); + explorerShell.Setup(s => s.HideAllWindows()).Callback(() => hide = ++order); + explorerShell.Setup(s => s.Terminate()).Callback(() => terminate = ++order); + processFactory.Reset(); + nextSettings.Security.KioskMode = KioskMode.DisableExplorerShell; + + var result = sut.Repeat(); + + desktopFactory.VerifyNoOtherCalls(); + explorerShell.Verify(s => s.HideAllWindows(), Times.Once); + explorerShell.Verify(s => s.Terminate(), Times.Once); + processFactory.VerifySet(f => f.StartupDesktop = It.IsAny(), Times.Never); + + Assert.AreEqual(OperationResult.Success, result); + Assert.AreEqual(1, hide); + Assert.AreEqual(2, terminate); } [TestMethod] @@ -196,8 +374,10 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations newDesktop.Verify(d => d.Activate(), Times.Once); newDesktop.Verify(d => d.Close(), Times.Never); processFactory.VerifySet(f => f.StartupDesktop = newDesktop.Object, Times.Once); - explorerShell.Verify(s => s.Suspend(), Times.Once); - explorerShell.Verify(s => s.Resume(), Times.Never); + explorerShell.Verify(s => s.Start(), Times.Never); + explorerShell.Verify(s => s.Terminate(), Times.Once); + explorerShell.Verify(s => s.HideAllWindows(), Times.Once); + explorerShell.Verify(s => s.RestoreAllWindows(), Times.Never); } [TestMethod] @@ -230,36 +410,48 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var originalDesktop = new Mock(); var order = 0; var activate = 0; + var restore = 0; var setStartup = 0; var close = 0; - var resume = 0; + var start = 0; currentSettings.Security.KioskMode = KioskMode.CreateNewDesktop; nextSettings.Security.KioskMode = KioskMode.CreateNewDesktop; - desktopFactory.Setup(f => f.GetCurrent()).Returns(originalDesktop.Object); desktopFactory.Setup(f => f.CreateNew(It.IsAny())).Returns(newDesktop.Object); - originalDesktop.Setup(d => d.Activate()).Callback(() => activate = ++order); - processFactory.SetupSet(f => f.StartupDesktop = It.Is(d => d == originalDesktop.Object)).Callback(() => setStartup = ++order); - newDesktop.Setup(d => d.Close()).Callback(() => close = ++order); - explorerShell.Setup(s => s.Resume()).Callback(() => resume = ++order); var performResult = sut.Perform(); + + Assert.AreEqual(OperationResult.Success, performResult); + + desktopFactory.Reset(); + originalDesktop.Reset(); + originalDesktop.Setup(d => d.Activate()).Callback(() => activate = ++order); + processFactory.SetupSet(f => f.StartupDesktop = It.Is(d => d == originalDesktop.Object)).Callback(() => setStartup = ++order); + newDesktop.Reset(); + newDesktop.Setup(d => d.Close()).Callback(() => close = ++order); + explorerShell.Reset(); + explorerShell.Setup(s => s.Start()).Callback(() => start = ++order); + explorerShell.Setup(s => s.RestoreAllWindows()).Callback(() => restore = ++order); + var revertResult = sut.Revert(); + desktopFactory.VerifyNoOtherCalls(); originalDesktop.Verify(d => d.Activate(), Times.Once); processFactory.VerifySet(f => f.StartupDesktop = originalDesktop.Object, Times.Once); newDesktop.Verify(d => d.Close(), Times.Once); - explorerShell.Verify(s => s.Resume(), Times.Once); - explorerShell.Verify(s => s.Start(), Times.Never); - explorerShell.Verify(s => s.RestoreAllWindows(), Times.Never); + explorerShell.Verify(s => s.Start(), Times.Once); + explorerShell.Verify(s => s.Terminate(), Times.Never); + explorerShell.Verify(s => s.HideAllWindows(), Times.Never); + explorerShell.Verify(s => s.RestoreAllWindows(), Times.Once); Assert.AreEqual(OperationResult.Success, performResult); Assert.AreEqual(OperationResult.Success, revertResult); Assert.AreEqual(1, activate); Assert.AreEqual(2, setStartup); Assert.AreEqual(3, close); - Assert.AreEqual(4, resume); + Assert.AreEqual(4, start); + Assert.AreEqual(5, restore); } [TestMethod] @@ -289,6 +481,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations Assert.AreEqual(OperationResult.Success, sut.Perform()); Assert.AreEqual(OperationResult.Success, sut.Repeat()); + Assert.AreEqual(OperationResult.Success, sut.Repeat()); + Assert.AreEqual(OperationResult.Success, sut.Repeat()); + Assert.AreEqual(OperationResult.Success, sut.Repeat()); Assert.AreEqual(OperationResult.Success, sut.Revert()); desktopFactory.VerifyNoOtherCalls(); diff --git a/SafeExamBrowser.Runtime/Operations/KioskModeOperation.cs b/SafeExamBrowser.Runtime/Operations/KioskModeOperation.cs index 0a0217ed..1e1549a6 100644 --- a/SafeExamBrowser.Runtime/Operations/KioskModeOperation.cs +++ b/SafeExamBrowser.Runtime/Operations/KioskModeOperation.cs @@ -51,6 +51,7 @@ namespace SafeExamBrowser.Runtime.Operations switch (Context.Next.Settings.Security.KioskMode) { case KioskMode.CreateNewDesktop: + TerminateExplorerShell(); CreateNewDesktop(); break; case KioskMode.DisableExplorerShell: @@ -64,7 +65,6 @@ namespace SafeExamBrowser.Runtime.Operations public override OperationResult Repeat() { var newMode = Context.Next.Settings.Security.KioskMode; - var result = OperationResult.Success; if (activeMode == newMode) { @@ -72,15 +72,33 @@ namespace SafeExamBrowser.Runtime.Operations } else { - result = Revert(); + logger.Info($"Switching from kiosk mode '{activeMode}' to '{newMode}'..."); + StatusChanged?.Invoke(TextKey.OperationStatus_InitializeKioskMode); - if (result == OperationResult.Success) + switch (activeMode) { - result = Perform(); + case KioskMode.CreateNewDesktop: + CloseNewDesktop(); + break; + case KioskMode.None: + TerminateExplorerShell(); + break; + } + + activeMode = newMode; + + switch (newMode) + { + case KioskMode.CreateNewDesktop: + CreateNewDesktop(); + break; + case KioskMode.None: + RestartExplorerShell(); + break; } } - return result; + return OperationResult.Success; } public override OperationResult Revert() @@ -92,6 +110,7 @@ namespace SafeExamBrowser.Runtime.Operations { case KioskMode.CreateNewDesktop: CloseNewDesktop(); + RestartExplorerShell(); break; case KioskMode.DisableExplorerShell: RestartExplorerShell(); @@ -112,8 +131,6 @@ namespace SafeExamBrowser.Runtime.Operations newDesktop.Activate(); processFactory.StartupDesktop = newDesktop; logger.Info("Successfully activated new desktop."); - - explorerShell.Suspend(); } private void CloseNewDesktop() @@ -138,8 +155,6 @@ namespace SafeExamBrowser.Runtime.Operations { logger.Warn($"No new desktop found to close!"); } - - explorerShell.Resume(); } private void TerminateExplorerShell() diff --git a/SafeExamBrowser.SystemComponents/UserInfo.cs b/SafeExamBrowser.SystemComponents/UserInfo.cs index d32af919..196283f4 100644 --- a/SafeExamBrowser.SystemComponents/UserInfo.cs +++ b/SafeExamBrowser.SystemComponents/UserInfo.cs @@ -89,11 +89,12 @@ namespace SafeExamBrowser.SystemComponents { var process = new Process(); - process.StartInfo.FileName = "cmd.exe"; process.StartInfo.Arguments = string.Format("/c \"wmic useraccount where name='{0}' get sid\"", userName); - process.StartInfo.UseShellExecute = false; - process.StartInfo.RedirectStandardOutput = true; process.StartInfo.CreateNoWindow = true; + process.StartInfo.FileName = "cmd.exe"; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.UseShellExecute = false; + process.StartInfo.WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Windows); process.Start(); process.WaitForExit(5000); diff --git a/SafeExamBrowser.WindowsApi.Contracts/IExplorerShell.cs b/SafeExamBrowser.WindowsApi.Contracts/IExplorerShell.cs index 9de42b42..15556652 100644 --- a/SafeExamBrowser.WindowsApi.Contracts/IExplorerShell.cs +++ b/SafeExamBrowser.WindowsApi.Contracts/IExplorerShell.cs @@ -23,21 +23,11 @@ namespace SafeExamBrowser.WindowsApi.Contracts /// void RestoreAllWindows(); - /// - /// Resumes the explorer shell process, if it was previously suspended. - /// - void Resume(); - /// /// Starts the Windows explorer shell, if it isn't already running. /// void Start(); - /// - /// Suspends the explorer shell process, if it is running. - /// - void Suspend(); - /// /// Gracefully terminates the Windows explorer shell, if it is running. /// diff --git a/SafeExamBrowser.WindowsApi/ExplorerShell.cs b/SafeExamBrowser.WindowsApi/ExplorerShell.cs index b692c058..599b1083 100644 --- a/SafeExamBrowser.WindowsApi/ExplorerShell.cs +++ b/SafeExamBrowser.WindowsApi/ExplorerShell.cs @@ -23,14 +23,12 @@ namespace SafeExamBrowser.WindowsApi private ILogger logger; private INativeMethods nativeMethods; private IList minimizedWindows = new List(); - private IList suspendedThreads; public ExplorerShell(ILogger logger, INativeMethods nativeMethods) { this.logger = logger; this.nativeMethods = nativeMethods; this.minimizedWindows = new List(); - this.suspendedThreads = new List(); } public void HideAllWindows() @@ -68,32 +66,6 @@ namespace SafeExamBrowser.WindowsApi logger.Info("Minimized windows successfully restored."); } - public void Resume() - { - const int MAX_ATTEMPTS = 3; - - logger.Debug($"Attempting to resume all {suspendedThreads.Count} previously suspended explorer shell threads..."); - - for (var attempts = 0; suspendedThreads.Any(); attempts++) - { - var thread = suspendedThreads.First(); - var success = nativeMethods.ResumeThread(thread.Id); - - if (success || attempts == MAX_ATTEMPTS) - { - attempts = 0; - suspendedThreads.Remove(thread); - - if (!success) - { - logger.Warn($"Failed to resume explorer shell thread with ID = {thread.Id} within {MAX_ATTEMPTS} attempts!"); - } - } - } - - logger.Info($"Successfully resumed explorer shell process."); - } - public void Start() { var process = new System.Diagnostics.Process(); @@ -103,6 +75,8 @@ namespace SafeExamBrowser.WindowsApi process.StartInfo.CreateNoWindow = true; process.StartInfo.FileName = explorerPath; + process.StartInfo.UseShellExecute = false; + process.StartInfo.WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Windows); process.Start(); logger.Debug("Waiting for explorer shell to initialize..."); @@ -117,39 +91,6 @@ namespace SafeExamBrowser.WindowsApi process.Close(); } - public void Suspend() - { - var processId = nativeMethods.GetShellProcessId(); - var explorerProcesses = System.Diagnostics.Process.GetProcessesByName("explorer"); - var process = explorerProcesses.FirstOrDefault(p => p.Id == processId); - - if (process != null) - { - logger.Debug($"Found explorer shell processes with PID = {processId} and {process.Threads.Count} threads."); - - foreach (ProcessThread thread in process.Threads) - { - var success = nativeMethods.SuspendThread(thread.Id); - - if (success) - { - suspendedThreads.Add(thread); - } - else - { - logger.Warn($"Failed to suspend explorer shell thread with ID = {thread.Id}!"); - } - } - - logger.Info($"Successfully suspended explorer shell process with PID = {processId}."); - process.Close(); - } - else - { - logger.Info("The explorer shell can't be suspended, as it seems to not be running."); - } - } - public void Terminate() { const int THREE_SECONDS = 3000; @@ -205,7 +146,9 @@ namespace SafeExamBrowser.WindowsApi process.StartInfo.Arguments = $"/F /PID {processId}"; process.StartInfo.CreateNoWindow = true; process.StartInfo.FileName = taskkillPath; + process.StartInfo.UseShellExecute = false; process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; + process.StartInfo.WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Windows); process.Start(); process.WaitForExit(); } diff --git a/SafeExamBrowser.WindowsApi/ProcessFactory.cs b/SafeExamBrowser.WindowsApi/ProcessFactory.cs index 11899c47..f44982f4 100644 --- a/SafeExamBrowser.WindowsApi/ProcessFactory.cs +++ b/SafeExamBrowser.WindowsApi/ProcessFactory.cs @@ -168,12 +168,15 @@ namespace SafeExamBrowser.WindowsApi private System.Diagnostics.Process StartNormal(string path, params string[] args) { - return System.Diagnostics.Process.Start(new ProcessStartInfo - { - Arguments = string.Join(" ", args), - FileName = path, - UseShellExecute = false - }); + var process = new System.Diagnostics.Process(); + + process.StartInfo.Arguments = string.Join(" ", args); + process.StartInfo.FileName = path; + process.StartInfo.UseShellExecute = false; + process.StartInfo.WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Windows); + process.Start(); + + return process; } private System.Diagnostics.Process StartOnDesktop(string path, params string[] args)