SEBWIN-373: Fixed system freeze caused by kiosk mode Create New Desktop due to it freezing the Windows shell. Thus, the Windows shell will henceforth be terminated for both kiosk modes. Furthermore ensured that processes started by SEB do not retain handles to the SEB directory.
This commit is contained in:
parent
ba4d4cec81
commit
5f01973b57
6 changed files with 293 additions and 146 deletions
|
@ -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<string>())).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<IDesktop>()).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<string>()), 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<IDesktop>();
|
||||
var originalDesktop = new Mock<IDesktop>();
|
||||
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<string>())).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<IDesktop>(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<IDesktop>(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<IDesktop>();
|
||||
var originalDesktop = new Mock<IDesktop>();
|
||||
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<string>())).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<IDesktop>(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<IDesktop>(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<IDesktop>();
|
||||
var originalDesktop = new Mock<IDesktop>();
|
||||
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<string>())).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<IDesktop>(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<string>()), Times.Once);
|
||||
explorerShell.VerifyNoOtherCalls();
|
||||
newDesktop.Verify(d => d.Activate(), Times.Once);
|
||||
originalDesktop.VerifyNoOtherCalls();
|
||||
processFactory.VerifySet(f => f.StartupDesktop = It.Is<IDesktop>(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<IDesktop>(), Times.Never);
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
Assert.AreEqual(1, start);
|
||||
Assert.AreEqual(2, restore);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Repeat_MustCorrectlySwitchFromNoneToCreateNewDesktop()
|
||||
{
|
||||
var newDesktop = new Mock<IDesktop>();
|
||||
var originalDesktop = new Mock<IDesktop>();
|
||||
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<string>())).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<IDesktop>(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<string>()), 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<IDesktop>(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<IDesktop>(), 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<IDesktop>();
|
||||
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<string>())).Returns(newDesktop.Object);
|
||||
originalDesktop.Setup(d => d.Activate()).Callback(() => activate = ++order);
|
||||
processFactory.SetupSet(f => f.StartupDesktop = It.Is<IDesktop>(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<IDesktop>(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();
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -23,21 +23,11 @@ namespace SafeExamBrowser.WindowsApi.Contracts
|
|||
/// </summary>
|
||||
void RestoreAllWindows();
|
||||
|
||||
/// <summary>
|
||||
/// Resumes the explorer shell process, if it was previously suspended.
|
||||
/// </summary>
|
||||
void Resume();
|
||||
|
||||
/// <summary>
|
||||
/// Starts the Windows explorer shell, if it isn't already running.
|
||||
/// </summary>
|
||||
void Start();
|
||||
|
||||
/// <summary>
|
||||
/// Suspends the explorer shell process, if it is running.
|
||||
/// </summary>
|
||||
void Suspend();
|
||||
|
||||
/// <summary>
|
||||
/// Gracefully terminates the Windows explorer shell, if it is running.
|
||||
/// </summary>
|
||||
|
|
|
@ -23,14 +23,12 @@ namespace SafeExamBrowser.WindowsApi
|
|||
private ILogger logger;
|
||||
private INativeMethods nativeMethods;
|
||||
private IList<Window> minimizedWindows = new List<Window>();
|
||||
private IList<ProcessThread> suspendedThreads;
|
||||
|
||||
public ExplorerShell(ILogger logger, INativeMethods nativeMethods)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.nativeMethods = nativeMethods;
|
||||
this.minimizedWindows = new List<Window>();
|
||||
this.suspendedThreads = new List<ProcessThread>();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue