diff --git a/SafeExamBrowser.Contracts/Monitoring/IWindowMonitor.cs b/SafeExamBrowser.Contracts/Monitoring/IWindowMonitor.cs
index 92a90720..53f66c4f 100644
--- a/SafeExamBrowser.Contracts/Monitoring/IWindowMonitor.cs
+++ b/SafeExamBrowser.Contracts/Monitoring/IWindowMonitor.cs
@@ -10,5 +10,25 @@ namespace SafeExamBrowser.Contracts.Monitoring
{
public interface IWindowMonitor
{
+ ///
+ /// Hides all currently opened windows.
+ ///
+ void HideAllWindows();
+
+ ///
+ /// Restores all windows which were hidden during the startup procedure.
+ ///
+ void RestoreHiddenWindows();
+
+ ///
+ /// 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.
+ ///
+ void StartMonitoringWindows();
+
+ ///
+ /// Stops monitoring windows and deregisters from any subscribed system events.
+ ///
+ void StopMonitoringWindows();
}
}
diff --git a/SafeExamBrowser.Core/Behaviour/Operations/ProcessMonitoringOperation.cs b/SafeExamBrowser.Core/Behaviour/Operations/ProcessMonitoringOperation.cs
index 16c17e63..862a947c 100644
--- a/SafeExamBrowser.Core/Behaviour/Operations/ProcessMonitoringOperation.cs
+++ b/SafeExamBrowser.Core/Behaviour/Operations/ProcessMonitoringOperation.cs
@@ -30,6 +30,11 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
public void Perform()
{
logger.Info("--- Initializing process monitoring ---");
+ SplashScreen.UpdateText(Key.SplashScreen_WaitExplorerTermination, true);
+
+ processMonitor.CloseExplorerShell();
+ processMonitor.StartMonitoringExplorer();
+
SplashScreen.UpdateText(Key.SplashScreen_InitializeProcessMonitoring);
// TODO
@@ -41,6 +46,11 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
SplashScreen.UpdateText(Key.SplashScreen_StopProcessMonitoring);
// TODO
+
+ SplashScreen.UpdateText(Key.SplashScreen_WaitExplorerStartup, true);
+
+ processMonitor.StopMonitoringExplorer();
+ processMonitor.StartExplorerShell();
}
}
}
diff --git a/SafeExamBrowser.Core/Behaviour/Operations/WorkingAreaOperation.cs b/SafeExamBrowser.Core/Behaviour/Operations/WorkingAreaOperation.cs
index 1f995241..af911eb4 100644
--- a/SafeExamBrowser.Core/Behaviour/Operations/WorkingAreaOperation.cs
+++ b/SafeExamBrowser.Core/Behaviour/Operations/WorkingAreaOperation.cs
@@ -10,7 +10,6 @@ using SafeExamBrowser.Contracts.Behaviour;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.Monitoring;
using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Core.Behaviour.Operations
@@ -18,16 +17,14 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
public class WorkingAreaOperation : IOperation
{
private ILogger logger;
- private IProcessMonitor processMonitor;
private ITaskbar taskbar;
private IWorkingArea workingArea;
public ISplashScreen SplashScreen { private get; set; }
- public WorkingAreaOperation(ILogger logger, IProcessMonitor processMonitor, ITaskbar taskbar, IWorkingArea workingArea)
+ public WorkingAreaOperation(ILogger logger, ITaskbar taskbar, IWorkingArea workingArea)
{
this.logger = logger;
- this.processMonitor = processMonitor;
this.taskbar = taskbar;
this.workingArea = workingArea;
}
@@ -35,16 +32,11 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
public void Perform()
{
logger.Info("--- Initializing working area ---");
- SplashScreen.UpdateText(Key.SplashScreen_WaitExplorerTermination, true);
-
- processMonitor.CloseExplorerShell();
- processMonitor.StartMonitoringExplorer();
+ SplashScreen.UpdateText(Key.SplashScreen_InitializeWorkingArea);
// TODO
- // - Minimizing all open windows
// - Emptying clipboard
- SplashScreen.UpdateText(Key.SplashScreen_InitializeWorkingArea);
workingArea.InitializeFor(taskbar);
}
@@ -54,15 +46,9 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
SplashScreen.UpdateText(Key.SplashScreen_RestoreWorkingArea);
// TODO
- // - Restore all windows?
// - Emptying clipboard
workingArea.Reset();
-
- SplashScreen.UpdateText(Key.SplashScreen_WaitExplorerStartup, true);
-
- processMonitor.StopMonitoringExplorer();
- processMonitor.StartExplorerShell();
}
}
}
diff --git a/SafeExamBrowser.Monitoring/SafeExamBrowser.Monitoring.csproj b/SafeExamBrowser.Monitoring/SafeExamBrowser.Monitoring.csproj
index 52b83b7b..5ae6e5ef 100644
--- a/SafeExamBrowser.Monitoring/SafeExamBrowser.Monitoring.csproj
+++ b/SafeExamBrowser.Monitoring/SafeExamBrowser.Monitoring.csproj
@@ -42,6 +42,7 @@
+
@@ -56,7 +57,6 @@
-
\ No newline at end of file
diff --git a/SafeExamBrowser.Monitoring/Windows/WindowMonitor.cs b/SafeExamBrowser.Monitoring/Windows/WindowMonitor.cs
new file mode 100644
index 00000000..86240d43
--- /dev/null
+++ b/SafeExamBrowser.Monitoring/Windows/WindowMonitor.cs
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+using System;
+using SafeExamBrowser.Contracts.Logging;
+using SafeExamBrowser.Contracts.Monitoring;
+using SafeExamBrowser.WindowsApi;
+
+namespace SafeExamBrowser.Monitoring.Windows
+{
+ public class WindowMonitor : IWindowMonitor
+ {
+ private ILogger logger;
+
+ public WindowMonitor(ILogger logger)
+ {
+ this.logger = logger;
+
+ // TODO: Make operation for window monitor OR operation for all desktop initialization?!
+ // ...
+ }
+
+ public void HideAllWindows()
+ {
+ logger.Info("Minimizing all open windows...");
+ User32.MinimizeAllOpenWindows();
+ logger.Info("Open windows successfully minimized.");
+ }
+
+ public void RestoreHiddenWindows()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void StartMonitoringWindows()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void StopMonitoringWindows()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/SafeExamBrowser.WindowsApi/Constants/Constant.cs b/SafeExamBrowser.WindowsApi/Constants/Constant.cs
new file mode 100644
index 00000000..1cbb46d0
--- /dev/null
+++ b/SafeExamBrowser.WindowsApi/Constants/Constant.cs
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+namespace SafeExamBrowser.WindowsApi.Constants
+{
+ static class Constant
+ {
+ internal const int WM_COMMAND = 0x111;
+ internal const int MIN_ALL = 419;
+ }
+}
diff --git a/SafeExamBrowser.WindowsApi/SafeExamBrowser.WindowsApi.csproj b/SafeExamBrowser.WindowsApi/SafeExamBrowser.WindowsApi.csproj
index d7a99b2d..074f5027 100644
--- a/SafeExamBrowser.WindowsApi/SafeExamBrowser.WindowsApi.csproj
+++ b/SafeExamBrowser.WindowsApi/SafeExamBrowser.WindowsApi.csproj
@@ -40,6 +40,7 @@
+
diff --git a/SafeExamBrowser.WindowsApi/User32.cs b/SafeExamBrowser.WindowsApi/User32.cs
index f8e71093..926f12d6 100644
--- a/SafeExamBrowser.WindowsApi/User32.cs
+++ b/SafeExamBrowser.WindowsApi/User32.cs
@@ -35,7 +35,7 @@ namespace SafeExamBrowser.WindowsApi
///
public static uint GetShellProcessId()
{
- var handle = FindWindow("Shell_TrayWnd", null);
+ var handle = GetShellWindowHandle();
var threadId = GetWindowThreadProcessId(handle, out uint processId);
return processId;
@@ -60,6 +60,16 @@ namespace SafeExamBrowser.WindowsApi
return workingArea;
}
+ ///
+ /// Minimizes all open windows.
+ ///
+ public static void MinimizeAllOpenWindows()
+ {
+ var handle = GetShellWindowHandle();
+
+ SendMessage(handle, Constant.WM_COMMAND, (IntPtr) Constant.MIN_ALL, IntPtr.Zero);
+ }
+
///
/// Instructs the main Windows explorer process to shut down.
///
@@ -72,8 +82,8 @@ namespace SafeExamBrowser.WindowsApi
///
public static void PostCloseMessageToShell()
{
- var taskbarHandle = FindWindow("Shell_TrayWnd", null);
- var success = PostMessage(taskbarHandle, 0x5B4, IntPtr.Zero, IntPtr.Zero);
+ var handle = GetShellWindowHandle();
+ var success = PostMessage(handle, 0x5B4, IntPtr.Zero, IntPtr.Zero);
if (!success)
{
@@ -107,6 +117,9 @@ namespace SafeExamBrowser.WindowsApi
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
+ [DllImport("user32.dll", EntryPoint = "SendMessage")]
+ private static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
+
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, ref RECT pvParam, SPIF fWinIni);
diff --git a/SafeExamBrowser/CompositionRoot.cs b/SafeExamBrowser/CompositionRoot.cs
index 761bd7b7..0a54ae71 100644
--- a/SafeExamBrowser/CompositionRoot.cs
+++ b/SafeExamBrowser/CompositionRoot.cs
@@ -20,6 +20,7 @@ using SafeExamBrowser.Core.Behaviour.Operations;
using SafeExamBrowser.Core.I18n;
using SafeExamBrowser.Core.Logging;
using SafeExamBrowser.Monitoring.Processes;
+using SafeExamBrowser.Monitoring.Windows;
using SafeExamBrowser.UserInterface;
namespace SafeExamBrowser
@@ -36,6 +37,7 @@ namespace SafeExamBrowser
private IText text;
private ITextResource textResource;
private IUiElementFactory uiFactory;
+ private IWindowMonitor windowMonitor;
private IWorkingArea workingArea;
public IShutdownController ShutdownController { get; private set; }
@@ -59,13 +61,14 @@ namespace SafeExamBrowser
text = new Text(textResource);
aboutInfo = new AboutNotificationInfo(text);
processMonitor = new ProcessMonitor(new ModuleLogger(logger, typeof(ProcessMonitor)));
+ windowMonitor = new WindowMonitor(new ModuleLogger(logger, typeof(WindowMonitor)));
workingArea = new WorkingArea(new ModuleLogger(logger, typeof(WorkingArea)));
ShutdownController = new ShutdownController(logger, messageBox, processMonitor, settings, text, uiFactory, workingArea);
StartupController = new StartupController(browserController, browserInfo, logger, messageBox, aboutInfo, processMonitor, settings, Taskbar, text, uiFactory, workingArea);
StartupOperations = new Queue();
StartupOperations.Enqueue(new ProcessMonitoringOperation(logger, processMonitor));
- StartupOperations.Enqueue(new WorkingAreaOperation(logger, processMonitor, Taskbar, workingArea));
+ StartupOperations.Enqueue(new WorkingAreaOperation(logger, Taskbar, workingArea));
StartupOperations.Enqueue(new TaskbarInitializationOperation(logger, aboutInfo, Taskbar, uiFactory));
StartupOperations.Enqueue(new BrowserInitializationOperation(browserController, browserInfo, logger, Taskbar, uiFactory));
}