Improved window handling and replaced whitespaces in log file names with underscores.
This commit is contained in:
parent
25105d61b1
commit
8c32d3bc4a
11 changed files with 134 additions and 50 deletions
|
@ -16,16 +16,16 @@ namespace SafeExamBrowser.Configuration
|
||||||
public class Settings : ISettings
|
public class Settings : ISettings
|
||||||
{
|
{
|
||||||
private const string AppDataFolder = "SafeExamBrowser";
|
private const string AppDataFolder = "SafeExamBrowser";
|
||||||
private static readonly string LogFileDate = DateTime.Now.ToString("yyyy-MM-dd HH\\hmm\\mss\\s");
|
private static readonly string LogFileDate = DateTime.Now.ToString("yyyy-MM-dd\\_HH\\hmm\\mss\\s");
|
||||||
|
|
||||||
public string ApplicationLogFile
|
public string ApplicationLogFile
|
||||||
{
|
{
|
||||||
get { return Path.Combine(LogFolderPath, $"{LogFileDate} Application.txt"); }
|
get { return Path.Combine(LogFolderPath, $"{LogFileDate}_Application.txt"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string BrowserLogFile
|
public string BrowserLogFile
|
||||||
{
|
{
|
||||||
get { return Path.Combine(LogFolderPath, $"{LogFileDate} Browser.txt"); }
|
get { return Path.Combine(LogFolderPath, $"{LogFileDate}_Browser.txt"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string BrowserCachePath
|
public string BrowserCachePath
|
||||||
|
|
|
@ -20,17 +20,16 @@ namespace SafeExamBrowser.Contracts.Monitoring
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event ExplorerStartedHandler ExplorerStarted;
|
event ExplorerStartedHandler ExplorerStarted;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a check whether the process associated to the given window is allowed.
|
||||||
|
/// </summary>
|
||||||
|
bool BelongsToAllowedProcess(IntPtr window);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Terminates the Windows explorer shell, i.e. the taskbar.
|
/// Terminates the Windows explorer shell, i.e. the taskbar.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void CloseExplorerShell();
|
void CloseExplorerShell();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Performs a check whether the process associated to the given window is allowed,
|
|
||||||
/// i.e. whether the specified window should be hidden.
|
|
||||||
/// </summary>
|
|
||||||
void OnWindowChanged(IntPtr window, out bool hide);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Starts a new instance of the Windows explorer shell.
|
/// Starts a new instance of the Windows explorer shell.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -10,7 +10,7 @@ using System;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Contracts.Monitoring
|
namespace SafeExamBrowser.Contracts.Monitoring
|
||||||
{
|
{
|
||||||
public delegate void WindowChangedHandler(IntPtr window, out bool hide);
|
public delegate void WindowChangedHandler(IntPtr window);
|
||||||
|
|
||||||
public interface IWindowMonitor
|
public interface IWindowMonitor
|
||||||
{
|
{
|
||||||
|
@ -19,6 +19,16 @@ namespace SafeExamBrowser.Contracts.Monitoring
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event WindowChangedHandler WindowChanged;
|
event WindowChangedHandler WindowChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Forcefully closes the specified window.
|
||||||
|
/// </summary>
|
||||||
|
void Close(IntPtr window);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hides the specified window. Returns <c>true</c> if the window was successfully hidden, otherwise <c>false</c>.
|
||||||
|
/// </summary>
|
||||||
|
bool Hide(IntPtr window);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hides all currently opened windows.
|
/// Hides all currently opened windows.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -54,9 +54,9 @@ namespace SafeExamBrowser.Contracts.WindowsApi
|
||||||
RECT GetWorkingArea();
|
RECT GetWorkingArea();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hides the given window.
|
/// Hides the given window. Returns <c>true</c> if successful, otherwise <c>false</c>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void HideWindow(IntPtr window);
|
bool HideWindow(IntPtr window);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Minimizes all open windows.
|
/// Minimizes all open windows.
|
||||||
|
@ -88,6 +88,11 @@ namespace SafeExamBrowser.Contracts.WindowsApi
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void RestoreWindow(IntPtr window);
|
void RestoreWindow(IntPtr window);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a close message to the given window.
|
||||||
|
/// </summary>
|
||||||
|
void SendCloseMessageTo(IntPtr window);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the working area of the primary screen according to the given dimensions.
|
/// Sets the working area of the primary screen according to the given dimensions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using SafeExamBrowser.Contracts.Behaviour;
|
using SafeExamBrowser.Contracts.Behaviour;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
@ -39,13 +40,13 @@ namespace SafeExamBrowser.Core.Behaviour
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
processMonitor.ExplorerStarted += ProcessMonitor_ExplorerStarted;
|
processMonitor.ExplorerStarted += ProcessMonitor_ExplorerStarted;
|
||||||
windowMonitor.WindowChanged += processMonitor.OnWindowChanged;
|
windowMonitor.WindowChanged += WindowMonitor_WindowChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
processMonitor.ExplorerStarted -= ProcessMonitor_ExplorerStarted;
|
processMonitor.ExplorerStarted -= ProcessMonitor_ExplorerStarted;
|
||||||
windowMonitor.WindowChanged -= processMonitor.OnWindowChanged;
|
windowMonitor.WindowChanged -= WindowMonitor_WindowChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessMonitor_ExplorerStarted()
|
private void ProcessMonitor_ExplorerStarted()
|
||||||
|
@ -56,7 +57,22 @@ namespace SafeExamBrowser.Core.Behaviour
|
||||||
workingArea.InitializeFor(taskbar);
|
workingArea.InitializeFor(taskbar);
|
||||||
logger.Info("Reinitializing taskbar bounds...");
|
logger.Info("Reinitializing taskbar bounds...");
|
||||||
taskbar.InitializeBounds();
|
taskbar.InitializeBounds();
|
||||||
logger.Info("Desktop successfully restored!");
|
logger.Info("Desktop successfully restored.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WindowMonitor_WindowChanged(IntPtr window)
|
||||||
|
{
|
||||||
|
var allowed = processMonitor.BelongsToAllowedProcess(window);
|
||||||
|
|
||||||
|
if (!allowed)
|
||||||
|
{
|
||||||
|
var success = windowMonitor.Hide(window);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
windowMonitor.Close(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,26 @@ namespace SafeExamBrowser.Monitoring.Processes
|
||||||
this.nativeMethods = nativeMethods;
|
this.nativeMethods = nativeMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool BelongsToAllowedProcess(IntPtr window)
|
||||||
|
{
|
||||||
|
var processId = nativeMethods.GetProcessIdFor(window);
|
||||||
|
var process = Process.GetProcessById(Convert.ToInt32(processId));
|
||||||
|
|
||||||
|
if (process != null)
|
||||||
|
{
|
||||||
|
var allowed = process.ProcessName == "SafeExamBrowser";
|
||||||
|
|
||||||
|
if (!allowed)
|
||||||
|
{
|
||||||
|
logger.Warn($"Window with handle = {window} belongs to not allowed process '{process.ProcessName}'!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void CloseExplorerShell()
|
public void CloseExplorerShell()
|
||||||
{
|
{
|
||||||
var processId = nativeMethods.GetShellProcessId();
|
var processId = nativeMethods.GetShellProcessId();
|
||||||
|
@ -58,21 +78,6 @@ namespace SafeExamBrowser.Monitoring.Processes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnWindowChanged(IntPtr window, out bool hide)
|
|
||||||
{
|
|
||||||
var processId = nativeMethods.GetProcessIdFor(window);
|
|
||||||
var process = Process.GetProcessById(Convert.ToInt32(processId));
|
|
||||||
|
|
||||||
if (process != null)
|
|
||||||
{
|
|
||||||
hide = process.ProcessName != "SafeExamBrowser";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hide = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void StartExplorerShell()
|
public void StartExplorerShell()
|
||||||
{
|
{
|
||||||
var process = new Process();
|
var process = new Process();
|
||||||
|
|
|
@ -30,6 +30,31 @@ namespace SafeExamBrowser.Monitoring.Windows
|
||||||
this.nativeMethods = nativeMethods;
|
this.nativeMethods = nativeMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Close(IntPtr window)
|
||||||
|
{
|
||||||
|
var title = nativeMethods.GetWindowTitle(window);
|
||||||
|
|
||||||
|
nativeMethods.SendCloseMessageTo(window);
|
||||||
|
logger.Info($"Sent close message to window '{title}' with handle = {window}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Hide(IntPtr window)
|
||||||
|
{
|
||||||
|
var title = nativeMethods.GetWindowTitle(window);
|
||||||
|
var success = nativeMethods.HideWindow(window);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
logger.Info($"Hid window '{title}' with handle = {window}.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.Warn($"Failed to hide window '{title}' with handle = {window}!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
public void HideAllWindows()
|
public void HideAllWindows()
|
||||||
{
|
{
|
||||||
logger.Info("Saving windows to be minimized...");
|
logger.Info("Saving windows to be minimized...");
|
||||||
|
@ -90,18 +115,7 @@ namespace SafeExamBrowser.Monitoring.Windows
|
||||||
|
|
||||||
private void OnWindowChanged(IntPtr window)
|
private void OnWindowChanged(IntPtr window)
|
||||||
{
|
{
|
||||||
if (WindowChanged != null)
|
WindowChanged?.Invoke(window);
|
||||||
{
|
|
||||||
WindowChanged.Invoke(window, out bool hide);
|
|
||||||
|
|
||||||
if (hide)
|
|
||||||
{
|
|
||||||
var title = nativeMethods.GetWindowTitle(window);
|
|
||||||
|
|
||||||
nativeMethods.HideWindow(window);
|
|
||||||
logger.Info($"Hid window '{title}' with handle = {window}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct Window
|
private struct Window
|
||||||
|
|
|
@ -48,5 +48,13 @@ namespace SafeExamBrowser.WindowsApi.Constants
|
||||||
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms647591(v=vs.85).aspx.
|
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms647591(v=vs.85).aspx.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal const int WM_COMMAND = 0x111;
|
internal const int WM_COMMAND = 0x111;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A window receives this message when the user chooses a command from the Window menu (formerly known as the system or control
|
||||||
|
/// menu) or when the user chooses the maximize button, minimize button, restore button, or close button.
|
||||||
|
///
|
||||||
|
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms646360(v=vs.85).aspx.
|
||||||
|
/// </summary>
|
||||||
|
internal const int WM_SYSCOMMAND = 0x112;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
21
SafeExamBrowser.WindowsApi/Constants/SystemCommand.cs
Normal file
21
SafeExamBrowser.WindowsApi/Constants/SystemCommand.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms646360(v=vs.85).aspx.
|
||||||
|
/// </summary>
|
||||||
|
internal enum SystemCommand
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Closes the window.
|
||||||
|
/// </summary>
|
||||||
|
CLOSE = 0xF060
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
|
* Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
@ -92,9 +92,9 @@ namespace SafeExamBrowser.WindowsApi
|
||||||
return workingArea;
|
return workingArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void HideWindow(IntPtr window)
|
public bool HideWindow(IntPtr window)
|
||||||
{
|
{
|
||||||
User32.ShowWindow(window, (int)ShowWindowCommand.Hide);
|
return User32.ShowWindow(window, (int) ShowWindowCommand.Hide);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MinimizeAllOpenWindows()
|
public void MinimizeAllOpenWindows()
|
||||||
|
@ -157,6 +157,11 @@ namespace SafeExamBrowser.WindowsApi
|
||||||
User32.ShowWindow(window, (int)ShowWindowCommand.Restore);
|
User32.ShowWindow(window, (int)ShowWindowCommand.Restore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SendCloseMessageTo(IntPtr window)
|
||||||
|
{
|
||||||
|
User32.SendMessage(window, Constant.WM_SYSCOMMAND, (IntPtr) SystemCommand.CLOSE, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetWorkingArea(RECT bounds)
|
public void SetWorkingArea(RECT bounds)
|
||||||
{
|
{
|
||||||
var success = User32.SystemParametersInfo(SPI.SETWORKAREA, 0, ref bounds, SPIF.UPDATEANDCHANGE);
|
var success = User32.SystemParametersInfo(SPI.SETWORKAREA, 0, ref bounds, SPIF.UPDATEANDCHANGE);
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Constants\Constant.cs" />
|
<Compile Include="Constants\Constant.cs" />
|
||||||
<Compile Include="Constants\ShowWindowCommand.cs" />
|
<Compile Include="Constants\ShowWindowCommand.cs" />
|
||||||
|
<Compile Include="Constants\SystemCommand.cs" />
|
||||||
<Compile Include="NativeMethods.cs" />
|
<Compile Include="NativeMethods.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Constants\SPI.cs" />
|
<Compile Include="Constants\SPI.cs" />
|
||||||
|
|
Loading…
Reference in a new issue