SEBWIN-221: Moved hide & restore windows mechanism for Disable Explorer Shell to IExplorerShell and made reconfiguration dialogs modal to respective browser window.
This commit is contained in:
parent
bae7ed8a25
commit
b4f468a2b4
16 changed files with 142 additions and 68 deletions
|
@ -63,7 +63,7 @@ namespace SafeExamBrowser.Browser
|
|||
var downloadLogger = logger.CloneFor($"{nameof(DownloadHandler)} {Id}");
|
||||
var downloadHandler = new DownloadHandler(appConfig, settings, downloadLogger);
|
||||
|
||||
downloadHandler.ConfigurationDownloadRequested += (fileName, args) => ConfigurationDownloadRequested?.Invoke(fileName, args);
|
||||
downloadHandler.ConfigurationDownloadRequested += DownloadHandler_ConfigurationDownloadRequested;
|
||||
|
||||
control = new BrowserControl(appConfig, settings, controlLogger, text);
|
||||
control.AddressChanged += Control_AddressChanged;
|
||||
|
@ -101,6 +101,13 @@ namespace SafeExamBrowser.Browser
|
|||
NameChanged?.Invoke(title);
|
||||
}
|
||||
|
||||
private void DownloadHandler_ConfigurationDownloadRequested(string fileName, DownloadEventArgs args)
|
||||
{
|
||||
args.BrowserWindow = window;
|
||||
|
||||
ConfigurationDownloadRequested?.Invoke(fileName, args);
|
||||
}
|
||||
|
||||
private void Window_AddressChanged(string address)
|
||||
{
|
||||
logger.Debug($"The user requested to navigate to '{address}'.");
|
||||
|
|
|
@ -82,6 +82,7 @@ namespace SafeExamBrowser.Browser.Handlers
|
|||
{
|
||||
var args = new DownloadEventArgs();
|
||||
|
||||
logger.Debug($"Detected download request for configuration file '{downloadItem.Url}'.");
|
||||
ConfigurationDownloadRequested?.Invoke(downloadItem.SuggestedFileName, args);
|
||||
logger.Debug($"Download of configuration file '{downloadItem.Url}' was {(args.AllowDownload ? "granted" : "denied")}.");
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
|
||||
sut.Perform();
|
||||
|
||||
windowMonitorMock.Verify(w => w.HideAllWindows(), Times.Never);
|
||||
windowMonitorMock.Verify(w => w.StartMonitoringWindows(), Times.Once);
|
||||
}
|
||||
|
||||
|
@ -47,7 +46,6 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
sut.Revert();
|
||||
|
||||
windowMonitorMock.Verify(w => w.StopMonitoringWindows(), Times.Once);
|
||||
windowMonitorMock.Verify(w => w.RestoreHiddenWindows(), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -57,7 +55,6 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
|
||||
sut.Perform();
|
||||
|
||||
windowMonitorMock.Verify(w => w.HideAllWindows(), Times.Never);
|
||||
windowMonitorMock.Verify(w => w.StartMonitoringWindows(), Times.Once);
|
||||
}
|
||||
|
||||
|
@ -69,7 +66,6 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
sut.Revert();
|
||||
|
||||
windowMonitorMock.Verify(w => w.StopMonitoringWindows(), Times.Once);
|
||||
windowMonitorMock.Verify(w => w.RestoreHiddenWindows(), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
|
|
@ -206,9 +206,11 @@ namespace SafeExamBrowser.Client
|
|||
{
|
||||
if (Settings.ConfigurationMode == ConfigurationMode.ConfigureClient)
|
||||
{
|
||||
logger.Info($"Detected download request for configuration file '{fileName}'.");
|
||||
logger.Debug($"Received download request for configuration file '{fileName}'. Asking user to confirm the reconfiguration...");
|
||||
|
||||
var result = messageBox.Show(TextKey.MessageBox_ReconfigurationQuestion, TextKey.MessageBox_ReconfigurationQuestionTitle, MessageBoxAction.YesNo, MessageBoxIcon.Question);
|
||||
var message = TextKey.MessageBox_ReconfigurationQuestion;
|
||||
var title = TextKey.MessageBox_ReconfigurationQuestionTitle;
|
||||
var result = messageBox.Show(message, title, MessageBoxAction.YesNo, MessageBoxIcon.Question, args.BrowserWindow);
|
||||
var reconfigure = result == MessageBoxResult.Yes;
|
||||
|
||||
logger.Info($"The user chose to {(reconfigure ? "start" : "abort")} the reconfiguration.");
|
||||
|
@ -223,7 +225,7 @@ namespace SafeExamBrowser.Client
|
|||
else
|
||||
{
|
||||
logger.Info($"Denied download request for configuration file '{fileName}' due to '{Settings.ConfigurationMode}' mode.");
|
||||
messageBox.Show(TextKey.MessageBox_ReconfigurationDenied, TextKey.MessageBox_ReconfigurationDeniedTitle);
|
||||
messageBox.Show(TextKey.MessageBox_ReconfigurationDenied, TextKey.MessageBox_ReconfigurationDeniedTitle, parent: args.BrowserWindow);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Contracts.UserInterface.Browser;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.Browser
|
||||
{
|
||||
/// <summary>
|
||||
/// The event arguments used for all download events fired by the <see cref="IBrowserApplicationController"/>.
|
||||
/// The event arguments used for all download events.
|
||||
/// </summary>
|
||||
public class DownloadEventArgs
|
||||
{
|
||||
|
@ -18,6 +20,11 @@ namespace SafeExamBrowser.Contracts.Browser
|
|||
/// </summary>
|
||||
public bool AllowDownload { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The browser window from which the download request originated.
|
||||
/// </summary>
|
||||
public IBrowserWindow BrowserWindow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Callback executed once a download has been finished.
|
||||
/// </summary>
|
||||
|
|
|
@ -31,16 +31,6 @@ namespace SafeExamBrowser.Contracts.Monitoring
|
|||
/// </summary>
|
||||
bool Hide(IntPtr window);
|
||||
|
||||
/// <summary>
|
||||
/// Hides all currently opened windows.
|
||||
/// </summary>
|
||||
void HideAllWindows();
|
||||
|
||||
/// <summary>
|
||||
/// Restores all windows which were hidden during the startup procedure.
|
||||
/// </summary>
|
||||
void RestoreHiddenWindows();
|
||||
|
||||
/// <summary>
|
||||
/// Starts monitoring application windows by subscribing to specific system events.
|
||||
/// If a window is shown which is not supposed to do so, it will be automatically hidden.
|
||||
|
|
|
@ -13,6 +13,16 @@ namespace SafeExamBrowser.Contracts.WindowsApi
|
|||
/// </summary>
|
||||
public interface IExplorerShell
|
||||
{
|
||||
/// <summary>
|
||||
/// Hides all currently opened windows. The explorer shell needs to be running in order to execute this operation!
|
||||
/// </summary>
|
||||
void HideAllWindows();
|
||||
|
||||
/// <summary>
|
||||
/// Restores all previously hidden windows. The explorer shell needs to be running in order to execute this operation!
|
||||
/// </summary>
|
||||
void RestoreAllWindows();
|
||||
|
||||
/// <summary>
|
||||
/// Resumes the explorer shell process, if it was previously suspended.
|
||||
/// </summary>
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
<Compile Include="Mouse\MouseInterceptor.cs" />
|
||||
<Compile Include="Processes\ProcessMonitor.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Windows\Window.cs" />
|
||||
<Compile Include="Windows\WindowMonitor.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.Monitoring;
|
||||
using SafeExamBrowser.Contracts.Monitoring.Events;
|
||||
|
@ -21,7 +20,6 @@ namespace SafeExamBrowser.Monitoring.Windows
|
|||
private Guid? captureHookId;
|
||||
private Guid? foregroundHookId;
|
||||
private ILogger logger;
|
||||
private IList<Window> minimizedWindows = new List<Window>();
|
||||
private INativeMethods nativeMethods;
|
||||
|
||||
public event WindowChangedEventHandler WindowChanged;
|
||||
|
@ -57,40 +55,6 @@ namespace SafeExamBrowser.Monitoring.Windows
|
|||
return success;
|
||||
}
|
||||
|
||||
public void HideAllWindows()
|
||||
{
|
||||
logger.Info("Searching for windows to be minimized...");
|
||||
|
||||
foreach (var handle in nativeMethods.GetOpenWindows())
|
||||
{
|
||||
var window = new Window
|
||||
{
|
||||
Handle = handle,
|
||||
Title = nativeMethods.GetWindowTitle(handle)
|
||||
};
|
||||
|
||||
minimizedWindows.Add(window);
|
||||
logger.Info($"Found window '{window.Title}' with handle = {window.Handle}.");
|
||||
}
|
||||
|
||||
logger.Info("Minimizing all open windows...");
|
||||
nativeMethods.MinimizeAllOpenWindows();
|
||||
logger.Info("Open windows successfully minimized.");
|
||||
}
|
||||
|
||||
public void RestoreHiddenWindows()
|
||||
{
|
||||
logger.Info("Restoring all minimized windows...");
|
||||
|
||||
foreach (var window in minimizedWindows)
|
||||
{
|
||||
nativeMethods.RestoreWindow(window.Handle);
|
||||
logger.Info($"Restored window '{window.Title}' with handle = {window.Handle}.");
|
||||
}
|
||||
|
||||
logger.Info("Minimized windows successfully restored.");
|
||||
}
|
||||
|
||||
public void StartMonitoringWindows()
|
||||
{
|
||||
captureHookId = nativeMethods.RegisterSystemCaptureStartEvent(OnWindowChanged);
|
||||
|
|
|
@ -80,6 +80,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
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.AreSame(sessionContext.NewDesktop, newDesktop.Object);
|
||||
Assert.AreSame(sessionContext.OriginalDesktop, originalDesktop.Object);
|
||||
|
@ -93,10 +95,15 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void MustCorrectlyInitializeDisableExplorerShell()
|
||||
{
|
||||
var order = 0;
|
||||
|
||||
nextSettings.KioskMode = KioskMode.DisableExplorerShell;
|
||||
explorerShell.Setup(s => s.HideAllWindows()).Callback(() => Assert.AreEqual(1, ++order));
|
||||
explorerShell.Setup(s => s.Terminate()).Callback(() => Assert.AreEqual(2, ++order));
|
||||
|
||||
sut.Perform();
|
||||
|
||||
explorerShell.Verify(s => s.HideAllWindows(), Times.Once);
|
||||
explorerShell.Verify(s => s.Terminate(), Times.Once);
|
||||
}
|
||||
|
||||
|
@ -128,6 +135,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
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);
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, performResult);
|
||||
Assert.AreEqual(OperationResult.Success, revertResult);
|
||||
|
@ -140,13 +149,18 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void MustCorrectlyRevertDisableExplorerShell()
|
||||
{
|
||||
var order = 0;
|
||||
|
||||
currentSettings.KioskMode = KioskMode.DisableExplorerShell;
|
||||
nextSettings.KioskMode = KioskMode.DisableExplorerShell;
|
||||
explorerShell.Setup(s => s.Start()).Callback(() => Assert.AreEqual(1, ++order));
|
||||
explorerShell.Setup(s => s.RestoreAllWindows()).Callback(() => Assert.AreEqual(2, ++order));
|
||||
|
||||
var performResult = sut.Perform();
|
||||
var revertResult = sut.Revert();
|
||||
|
||||
explorerShell.Verify(s => s.Start(), Times.Once);
|
||||
explorerShell.Verify(s => s.RestoreAllWindows(), Times.Once);
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, performResult);
|
||||
Assert.AreEqual(OperationResult.Success, revertResult);
|
||||
|
@ -171,6 +185,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
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);
|
||||
|
@ -181,10 +197,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
|
||||
explorerShell.Verify(s => s.Resume(), Times.Never);
|
||||
explorerShell.Verify(s => s.Terminate(), Times.Once);
|
||||
explorerShell.Verify(s => s.Suspend(), Times.Once);
|
||||
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.Once);
|
||||
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);
|
||||
|
@ -196,10 +214,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
|
||||
explorerShell.Verify(s => s.Resume(), Times.Never);
|
||||
explorerShell.Verify(s => s.Terminate(), Times.Once);
|
||||
explorerShell.Verify(s => s.Suspend(), Times.Exactly(2));
|
||||
explorerShell.Verify(s => s.Start(), Times.Never);
|
||||
explorerShell.Verify(s => s.Resume(), Times.Never);
|
||||
explorerShell.Verify(s => s.Suspend(), Times.Exactly(2));
|
||||
explorerShell.Verify(s => s.HideAllWindows(), Times.Once);
|
||||
explorerShell.Verify(s => s.RestoreAllWindows(), Times.Never);
|
||||
newDesktop.Verify(d => d.Activate(), Times.Exactly(2));
|
||||
newDesktop.Verify(d => d.Close(), Times.Never);
|
||||
originalDesktop.Verify(d => d.Activate(), Times.Never);
|
||||
|
|
|
@ -88,6 +88,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
explorerShell.Verify(s => s.Start(), Times.Once);
|
||||
explorerShell.Verify(s => s.Suspend(), Times.Never);
|
||||
explorerShell.Verify(s => s.Terminate(), Times.Never);
|
||||
explorerShell.Verify(s => s.HideAllWindows(), Times.Never);
|
||||
explorerShell.Verify(s => s.RestoreAllWindows(), Times.Once);
|
||||
newDesktop.Verify(d => d.Activate(), Times.Never);
|
||||
newDesktop.Verify(d => d.Close(), Times.Never);
|
||||
originalDesktop.Verify(d => d.Activate(), Times.Never);
|
||||
|
@ -103,6 +105,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
explorerShell.Verify(s => s.Start(), Times.Once);
|
||||
explorerShell.Verify(s => s.Suspend(), Times.Never);
|
||||
explorerShell.Verify(s => s.Terminate(), Times.Never);
|
||||
explorerShell.Verify(s => s.HideAllWindows(), Times.Never);
|
||||
explorerShell.Verify(s => s.RestoreAllWindows(), Times.Once);
|
||||
newDesktop.Verify(d => d.Activate(), Times.Never);
|
||||
newDesktop.Verify(d => d.Close(), Times.Once);
|
||||
originalDesktop.Verify(d => d.Activate(), Times.Once);
|
||||
|
@ -118,6 +122,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
explorerShell.Verify(s => s.Start(), Times.Exactly(2));
|
||||
explorerShell.Verify(s => s.Suspend(), Times.Never);
|
||||
explorerShell.Verify(s => s.Terminate(), Times.Never);
|
||||
explorerShell.Verify(s => s.HideAllWindows(), Times.Never);
|
||||
explorerShell.Verify(s => s.RestoreAllWindows(), Times.Exactly(2));
|
||||
newDesktop.Verify(d => d.Activate(), Times.Never);
|
||||
newDesktop.Verify(d => d.Close(), Times.Once);
|
||||
originalDesktop.Verify(d => d.Activate(), Times.Once);
|
||||
|
@ -126,7 +132,45 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
|||
[TestMethod]
|
||||
public void MustNotTerminateKioskModeIfSameInNextSesssion()
|
||||
{
|
||||
var newDesktop = new Mock<IDesktop>();
|
||||
var originalDesktop = new Mock<IDesktop>();
|
||||
var result = default(OperationResult);
|
||||
|
||||
sessionContext.NewDesktop = newDesktop.Object;
|
||||
sessionContext.OriginalDesktop = originalDesktop.Object;
|
||||
sessionContext.ActiveMode = KioskMode.DisableExplorerShell;
|
||||
nextSettings.KioskMode = KioskMode.DisableExplorerShell;
|
||||
|
||||
result = sut.Repeat();
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
|
||||
explorerShell.Verify(s => s.Resume(), Times.Never);
|
||||
explorerShell.Verify(s => s.Start(), Times.Never);
|
||||
explorerShell.Verify(s => s.Suspend(), Times.Never);
|
||||
explorerShell.Verify(s => s.Terminate(), Times.Never);
|
||||
explorerShell.Verify(s => s.HideAllWindows(), Times.Never);
|
||||
explorerShell.Verify(s => s.RestoreAllWindows(), Times.Never);
|
||||
newDesktop.Verify(d => d.Activate(), Times.Never);
|
||||
newDesktop.Verify(d => d.Close(), Times.Never);
|
||||
originalDesktop.Verify(d => d.Activate(), Times.Never);
|
||||
|
||||
sessionContext.ActiveMode = KioskMode.CreateNewDesktop;
|
||||
nextSettings.KioskMode = KioskMode.CreateNewDesktop;
|
||||
|
||||
result = sut.Repeat();
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
|
||||
explorerShell.Verify(s => s.Resume(), Times.Never);
|
||||
explorerShell.Verify(s => s.Start(), Times.Never);
|
||||
explorerShell.Verify(s => s.Suspend(), Times.Never);
|
||||
explorerShell.Verify(s => s.Terminate(), Times.Never);
|
||||
explorerShell.Verify(s => s.HideAllWindows(), Times.Never);
|
||||
explorerShell.Verify(s => s.RestoreAllWindows(), Times.Never);
|
||||
newDesktop.Verify(d => d.Activate(), Times.Never);
|
||||
newDesktop.Verify(d => d.Close(), Times.Never);
|
||||
originalDesktop.Verify(d => d.Activate(), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
|
|
@ -158,17 +158,16 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
{
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_WaitExplorerTermination);
|
||||
|
||||
// TODO: Hiding all windows must be done here, as the explorer shell is needed to do so!
|
||||
|
||||
explorerShell.HideAllWindows();
|
||||
explorerShell.Terminate();
|
||||
}
|
||||
|
||||
private void RestartExplorerShell()
|
||||
{
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_WaitExplorerStartup);
|
||||
explorerShell.Start();
|
||||
|
||||
// TODO: Restore all hidden windows!
|
||||
explorerShell.Start();
|
||||
explorerShell.RestoreAllWindows();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -448,9 +448,6 @@ namespace SafeExamBrowser.Runtime
|
|||
runtimeWindow?.UpdateStatus(status, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Move to utility in core library and use in client controller!
|
||||
/// </summary>
|
||||
private void MapProgress(IProgressIndicator progressIndicator, ProgressChangedEventArgs args)
|
||||
{
|
||||
if (args.CurrentValue.HasValue)
|
||||
|
|
|
@ -14,6 +14,7 @@ using System.Linq;
|
|||
using System.Threading;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.WindowsApi;
|
||||
using SafeExamBrowser.WindowsApi.Types;
|
||||
|
||||
namespace SafeExamBrowser.WindowsApi
|
||||
{
|
||||
|
@ -21,15 +22,51 @@ 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()
|
||||
{
|
||||
logger.Info("Searching for windows to be minimized...");
|
||||
|
||||
foreach (var handle in nativeMethods.GetOpenWindows())
|
||||
{
|
||||
var window = new Window
|
||||
{
|
||||
Handle = handle,
|
||||
Title = nativeMethods.GetWindowTitle(handle)
|
||||
};
|
||||
|
||||
minimizedWindows.Add(window);
|
||||
logger.Info($"Found window '{window.Title}' with handle = {window.Handle}.");
|
||||
}
|
||||
|
||||
logger.Info("Minimizing all open windows...");
|
||||
nativeMethods.MinimizeAllOpenWindows();
|
||||
logger.Info("Open windows successfully minimized.");
|
||||
}
|
||||
|
||||
public void RestoreAllWindows()
|
||||
{
|
||||
logger.Info("Restoring all minimized windows...");
|
||||
|
||||
foreach (var window in minimizedWindows)
|
||||
{
|
||||
nativeMethods.RestoreWindow(window.Handle);
|
||||
logger.Info($"Restored window '{window.Title}' with handle = {window.Handle}.");
|
||||
}
|
||||
|
||||
logger.Info("Minimized windows successfully restored.");
|
||||
}
|
||||
|
||||
public void Resume()
|
||||
{
|
||||
const int MAX_ATTEMPTS = 3;
|
||||
|
|
|
@ -83,6 +83,7 @@
|
|||
<Compile Include="Types\PROCESS_INFORMATION.cs" />
|
||||
<Compile Include="Types\RECT.cs" />
|
||||
<Compile Include="Types\STARTUPINFO.cs" />
|
||||
<Compile Include="Types\Window.cs" />
|
||||
<Compile Include="User32.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace SafeExamBrowser.Monitoring.Windows
|
||||
namespace SafeExamBrowser.WindowsApi.Types
|
||||
{
|
||||
internal struct Window
|
||||
{
|
Loading…
Reference in a new issue