Implemented basic monitoring of Windows explorer and added event controller module.

This commit is contained in:
dbuechel 2017-07-26 14:36:20 +02:00
parent 8e4f818159
commit 9ab04ecc77
22 changed files with 259 additions and 82 deletions

View file

@ -0,0 +1,23 @@
/*
* 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.Contracts.Behaviour
{
public interface IEventController
{
/// <summary>
/// Wires up the event handling, i.e. subscribes to all relevant application events.
/// </summary>
void Start();
/// <summary>
/// Removes all event subscriptions.
/// </summary>
void Stop();
}
}

View file

@ -27,9 +27,12 @@ namespace SafeExamBrowser.Contracts.I18n
SplashScreen_InitializeWorkingArea,
SplashScreen_RestoreWorkingArea,
SplashScreen_ShutdownProcedure,
SplashScreen_StartEventHandling,
SplashScreen_StartupProcedure,
SplashScreen_StopEventHandling,
SplashScreen_StopProcessMonitoring,
SplashScreen_StopWindowMonitoring,
SplashScreen_TerminateBrowser,
SplashScreen_WaitExplorerStartup,
SplashScreen_WaitExplorerTermination,
Version

View file

@ -14,7 +14,7 @@ namespace SafeExamBrowser.Contracts.Logging
public enum LogLevel
{
Info = 1,
Warn = 2,
Warning = 2,
Error = 3
}
}

View file

@ -8,8 +8,16 @@
namespace SafeExamBrowser.Contracts.Monitoring
{
public delegate void ExplorerStartedHandler();
public interface IProcessMonitor
{
/// <summary>
/// Event fired when the process monitor observes that a new instance of
/// the Windows explorer has been started.
/// </summary>
event ExplorerStartedHandler ExplorerStarted;
/// <summary>
/// Starts a new instance of the Windows explorer shell.
/// </summary>
@ -17,7 +25,7 @@ namespace SafeExamBrowser.Contracts.Monitoring
/// <summary>
/// Starts monitoring the Windows explorer, i.e. any newly created instances of
/// <c>explorer.exe</c> will automatically be terminated.
/// <c>explorer.exe</c> will trigger the <c>ExplorerStarted</c> event.
/// </summary>
void StartMonitoringExplorer();

View file

@ -59,6 +59,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Behaviour\IApplicationController.cs" />
<Compile Include="Behaviour\IEventController.cs" />
<Compile Include="Behaviour\INotificationController.cs" />
<Compile Include="Behaviour\IOperation.cs" />
<Compile Include="Configuration\IIconResource.cs" />

View file

@ -25,5 +25,10 @@ namespace SafeExamBrowser.Contracts.UserInterface
/// Returns the absolute height of the taskbar (i.e. in physical pixels).
/// </summary>
int GetAbsoluteHeight();
/// <summary>
/// Moves the taskbar to the bottom of and resizes it according to the current working area.
/// </summary>
void InitializeBounds();
}
}

View file

@ -38,7 +38,7 @@ namespace SafeExamBrowser.Core.UnitTests.Logging
Assert.IsTrue((log[0] as ILogMessage).Severity == LogLevel.Info);
Assert.IsTrue(warn.Equals((log[1] as ILogMessage).Message));
Assert.IsTrue((log[1] as ILogMessage).Severity == LogLevel.Warn);
Assert.IsTrue((log[1] as ILogMessage).Severity == LogLevel.Warning);
Assert.IsTrue(error.Equals((log[2] as ILogMessage).Message));
Assert.IsTrue((log[2] as ILogMessage).Severity == LogLevel.Error);
@ -122,7 +122,7 @@ namespace SafeExamBrowser.Core.UnitTests.Logging
Assert.IsTrue((messages[0] as ILogMessage).Severity == LogLevel.Info);
Assert.IsTrue(message.Equals((messages[0] as ILogMessage).Message));
Assert.IsTrue((messages[1] as ILogMessage).Severity == LogLevel.Warn);
Assert.IsTrue((messages[1] as ILogMessage).Severity == LogLevel.Warning);
Assert.IsTrue(message.Equals((messages[1] as ILogMessage).Message));
}

View file

@ -0,0 +1,53 @@
/*
* 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 SafeExamBrowser.Contracts.Behaviour;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.Monitoring;
using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Core.Behaviour
{
public class EventController : IEventController
{
private IProcessMonitor processMonitor;
private ITaskbar taskbar;
private IWorkingArea workingArea;
private ILogger logger;
public EventController(ILogger logger, IProcessMonitor processMonitor, ITaskbar taskbar, IWorkingArea workingArea)
{
this.logger = logger;
this.processMonitor = processMonitor;
this.taskbar = taskbar;
this.workingArea = workingArea;
}
public void Start()
{
processMonitor.ExplorerStarted += ProcessMonitor_ExplorerStarted;
}
public void Stop()
{
processMonitor.ExplorerStarted -= ProcessMonitor_ExplorerStarted;
}
private void ProcessMonitor_ExplorerStarted()
{
logger.Info("Trying to shut down explorer...");
processMonitor.CloseExplorerShell();
logger.Info("Reinitializing working area...");
workingArea.InitializeFor(taskbar);
logger.Info("Reinitializing taskbar bounds...");
taskbar.InitializeBounds();
logger.Info("Desktop successfully restored!");
}
}
}

View file

@ -14,7 +14,7 @@ using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Core.Behaviour.Operations
{
public class BrowserInitializationOperation : IOperation
public class BrowserOperation : IOperation
{
private IApplicationController browserController;
private IApplicationInfo browserInfo;
@ -24,7 +24,7 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
public ISplashScreen SplashScreen { private get; set; }
public BrowserInitializationOperation(
public BrowserOperation(
IApplicationController browserController,
IApplicationInfo browserInfo,
ILogger logger,
@ -49,14 +49,14 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
browserController.RegisterApplicationButton(browserButton);
taskbar.AddButton(browserButton);
logger.Info("Browser successfully initialized.");
}
public void Revert()
{
logger.Info("Terminating browser...");
SplashScreen.UpdateText(Key.SplashScreen_TerminateBrowser);
browserController.Terminate();
logger.Info("Browser successfully terminated.");
}
}
}

View file

@ -0,0 +1,45 @@
/*
* 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 SafeExamBrowser.Contracts.Behaviour;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Core.Behaviour.Operations
{
public class EventControllerOperation : IOperation
{
private ILogger logger;
private IEventController controller;
public ISplashScreen SplashScreen { private get; set; }
public EventControllerOperation(IEventController controller, ILogger logger)
{
this.controller = controller;
this.logger = logger;
}
public void Perform()
{
logger.Info("Starting event handling...");
SplashScreen.UpdateText(Key.SplashScreen_StartEventHandling);
controller.Start();
}
public void Revert()
{
logger.Info("Stopping event handling...");
SplashScreen.UpdateText(Key.SplashScreen_StopEventHandling);
controller.Stop();
}
}
}

View file

@ -14,14 +14,14 @@ using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Core.Behaviour.Operations
{
public class ProcessMonitoringOperation : IOperation
public class ProcessMonitorOperation : IOperation
{
private ILogger logger;
private IProcessMonitor processMonitor;
public ISplashScreen SplashScreen { private get; set; }
public ProcessMonitoringOperation(ILogger logger, IProcessMonitor processMonitor)
public ProcessMonitorOperation(ILogger logger, IProcessMonitor processMonitor)
{
this.logger = logger;
this.processMonitor = processMonitor;

View file

@ -14,7 +14,7 @@ using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Core.Behaviour.Operations
{
public class TaskbarInitializationOperation : IOperation
public class TaskbarOperation : IOperation
{
private ILogger logger;
private ITaskbar taskbar;
@ -23,7 +23,7 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
public ISplashScreen SplashScreen { private get; set; }
public TaskbarInitializationOperation(ILogger logger, INotificationInfo aboutInfo, ITaskbar taskbar, IUiElementFactory uiFactory)
public TaskbarOperation(ILogger logger, INotificationInfo aboutInfo, ITaskbar taskbar, IUiElementFactory uiFactory)
{
this.logger = logger;
this.aboutInfo = aboutInfo;

View file

@ -14,14 +14,14 @@ using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Core.Behaviour.Operations
{
public class WindowMonitoringOperation : IOperation
public class WindowMonitorOperation : IOperation
{
private ILogger logger;
private IWindowMonitor windowMonitor;
public ISplashScreen SplashScreen { private get; set; }
public WindowMonitoringOperation(ILogger logger, IWindowMonitor windowMonitor)
public WindowMonitorOperation(ILogger logger, IWindowMonitor windowMonitor)
{
this.logger = logger;
this.windowMonitor = windowMonitor;

View file

@ -37,18 +37,18 @@ namespace SafeExamBrowser.Core.Behaviour
{
try
{
InitializeSplashScreen();
RevertOperations(operations);
FinishFinalization();
Initialize();
Revert(operations);
Finish();
}
catch (Exception e)
{
LogAndShowException(e);
FinishFinalization(false);
Finish(false);
}
}
private void RevertOperations(Queue<IOperation> operations)
private void Revert(Queue<IOperation> operations)
{
foreach (var operation in operations)
{
@ -60,13 +60,15 @@ namespace SafeExamBrowser.Core.Behaviour
}
}
private void InitializeSplashScreen()
private void Initialize()
{
logger.Log(string.Empty);
logger.Info("--- Initiating shutdown procedure ---");
splashScreen = uiFactory.CreateSplashScreen(settings, text);
splashScreen.SetIndeterminate();
splashScreen.UpdateText(Key.SplashScreen_ShutdownProcedure);
splashScreen.InvokeShow();
logger.Info("--- Initiating shutdown procedure ---");
}
private void LogAndShowException(Exception e)
@ -75,7 +77,7 @@ namespace SafeExamBrowser.Core.Behaviour
uiFactory.Show(text.Get(Key.MessageBox_ShutdownError), text.Get(Key.MessageBox_ShutdownErrorTitle), icon: MessageBoxIcon.Error);
}
private void FinishFinalization(bool success = true)
private void Finish(bool success = true)
{
if (success)
{

View file

@ -40,12 +40,9 @@ namespace SafeExamBrowser.Core.Behaviour
{
try
{
InitializeApplicationLog();
InitializeSplashScreen(operations.Count);
Initialize(operations.Count);
Perform(operations);
FinishInitialization();
Finish();
return true;
}
@ -53,7 +50,7 @@ namespace SafeExamBrowser.Core.Behaviour
{
LogAndShowException(e);
RevertOperations();
FinishInitialization(false);
Finish(false);
return false;
}
@ -89,7 +86,7 @@ namespace SafeExamBrowser.Core.Behaviour
}
}
private void InitializeApplicationLog()
private void Initialize(int operationCount)
{
var titleLine = $"/* {settings.ProgramTitle}, Version {settings.ProgramVersion}{Environment.NewLine}";
var copyrightLine = $"/* {settings.ProgramCopyright}{Environment.NewLine}";
@ -99,10 +96,7 @@ namespace SafeExamBrowser.Core.Behaviour
logger.Log($"{titleLine}{copyrightLine}{emptyLine}{githubLine}");
logger.Log($"{Environment.NewLine}# Application started at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}{Environment.NewLine}");
logger.Info("--- Initiating startup procedure ---");
}
private void InitializeSplashScreen(int operationCount)
{
splashScreen = uiFactory.CreateSplashScreen(settings, text);
splashScreen.SetMaxProgress(operationCount);
splashScreen.UpdateText(Key.SplashScreen_StartupProcedure);
@ -116,11 +110,12 @@ namespace SafeExamBrowser.Core.Behaviour
logger.Info("Reverting operations...");
}
private void FinishInitialization(bool success = true)
private void Finish(bool success = true)
{
if (success)
{
logger.Info("--- Application successfully initialized! ---");
logger.Log(string.Empty);
splashScreen?.InvokeClose();
}
else

View file

@ -1,21 +1,24 @@
<?xml version="1.0" encoding="utf-8" ?>
<Text>
<MessageBox_ShutdownError>An unexpected error occurred during the shutdown procedure! Please consult the application log for more information...</MessageBox_ShutdownError>
<MessageBox_ShutdownErrorTitle>Shutdown Error</MessageBox_ShutdownErrorTitle>
<MessageBox_StartupError>An unexpected error occurred during the startup procedure! Please consult the application log for more information...</MessageBox_StartupError>
<MessageBox_StartupErrorTitle>Startup Error</MessageBox_StartupErrorTitle>
<Notification_AboutTooltip>About Safe Exam Browser</Notification_AboutTooltip>
<SplashScreen_InitializeBrowser>Initializing browser</SplashScreen_InitializeBrowser>
<SplashScreen_InitializeProcessMonitoring>Initializing process monitoring</SplashScreen_InitializeProcessMonitoring>
<SplashScreen_InitializeTaskbar>Initializing taskbar</SplashScreen_InitializeTaskbar>
<SplashScreen_InitializeWindowMonitoring>Initializing window monitoring</SplashScreen_InitializeWindowMonitoring>
<SplashScreen_InitializeWorkingArea>Initializing working area</SplashScreen_InitializeWorkingArea>
<SplashScreen_RestoreWorkingArea>Restoring working area</SplashScreen_RestoreWorkingArea>
<SplashScreen_ShutdownProcedure>Initiating shutdown procedure</SplashScreen_ShutdownProcedure>
<SplashScreen_StartupProcedure>Initiating startup procedure</SplashScreen_StartupProcedure>
<SplashScreen_StopProcessMonitoring>Stopping process monitoring</SplashScreen_StopProcessMonitoring>
<SplashScreen_StopWindowMonitoring>Stopping window monitoring</SplashScreen_StopWindowMonitoring>
<SplashScreen_WaitExplorerStartup>Waiting for Windows explorer to start up</SplashScreen_WaitExplorerStartup>
<SplashScreen_WaitExplorerTermination>Waiting for Windows explorer to shut down</SplashScreen_WaitExplorerTermination>
<Version>Version</Version>
<MessageBox_ShutdownError>An unexpected error occurred during the shutdown procedure! Please consult the application log for more information...</MessageBox_ShutdownError>
<MessageBox_ShutdownErrorTitle>Shutdown Error</MessageBox_ShutdownErrorTitle>
<MessageBox_StartupError>An unexpected error occurred during the startup procedure! Please consult the application log for more information...</MessageBox_StartupError>
<MessageBox_StartupErrorTitle>Startup Error</MessageBox_StartupErrorTitle>
<Notification_AboutTooltip>About Safe Exam Browser</Notification_AboutTooltip>
<SplashScreen_InitializeBrowser>Initializing browser</SplashScreen_InitializeBrowser>
<SplashScreen_InitializeProcessMonitoring>Initializing process monitoring</SplashScreen_InitializeProcessMonitoring>
<SplashScreen_InitializeTaskbar>Initializing taskbar</SplashScreen_InitializeTaskbar>
<SplashScreen_InitializeWindowMonitoring>Initializing window monitoring</SplashScreen_InitializeWindowMonitoring>
<SplashScreen_InitializeWorkingArea>Initializing working area</SplashScreen_InitializeWorkingArea>
<SplashScreen_RestoreWorkingArea>Restoring working area</SplashScreen_RestoreWorkingArea>
<SplashScreen_ShutdownProcedure>Initiating shutdown procedure</SplashScreen_ShutdownProcedure>
<SplashScreen_StartEventHandling>Starting event handling</SplashScreen_StartEventHandling>
<SplashScreen_StartupProcedure>Initiating startup procedure</SplashScreen_StartupProcedure>
<SplashScreen_StopEventHandling>Stopping event handling</SplashScreen_StopEventHandling>
<SplashScreen_StopProcessMonitoring>Stopping process monitoring</SplashScreen_StopProcessMonitoring>
<SplashScreen_StopWindowMonitoring>Stopping window monitoring</SplashScreen_StopWindowMonitoring>
<SplashScreen_TerminateBrowser>Terminating browser</SplashScreen_TerminateBrowser>
<SplashScreen_WaitExplorerStartup>Waiting for Windows explorer to start up</SplashScreen_WaitExplorerStartup>
<SplashScreen_WaitExplorerTermination>Waiting for Windows explorer to shut down</SplashScreen_WaitExplorerTermination>
<Version>Version</Version>
</Text>

View file

@ -29,7 +29,7 @@ namespace SafeExamBrowser.Core.Logging
public void Warn(string message)
{
Add(LogLevel.Warn, message);
Add(LogLevel.Warning, message);
}
public void Error(string message)

View file

@ -58,10 +58,12 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Behaviour\Operations\BrowserInitializationOperation.cs" />
<Compile Include="Behaviour\Operations\ProcessMonitoringOperation.cs" />
<Compile Include="Behaviour\Operations\TaskbarInitializationOperation.cs" />
<Compile Include="Behaviour\Operations\WindowMonitoringOperation.cs" />
<Compile Include="Behaviour\EventController.cs" />
<Compile Include="Behaviour\Operations\BrowserOperation.cs" />
<Compile Include="Behaviour\Operations\EventControllerOperation.cs" />
<Compile Include="Behaviour\Operations\ProcessMonitorOperation.cs" />
<Compile Include="Behaviour\Operations\TaskbarOperation.cs" />
<Compile Include="Behaviour\Operations\WindowMonitorOperation.cs" />
<Compile Include="Behaviour\Operations\WorkingAreaOperation.cs" />
<Compile Include="Behaviour\ShutdownController.cs" />
<Compile Include="Behaviour\StartupController.cs" />

View file

@ -10,6 +10,7 @@ using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Threading;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.Monitoring;
@ -20,6 +21,9 @@ namespace SafeExamBrowser.Monitoring.Processes
public class ProcessMonitor : IProcessMonitor
{
private ILogger logger;
private ManagementEventWatcher explorerWatcher;
public event ExplorerStartedHandler ExplorerStarted;
public ProcessMonitor(ILogger logger)
{
@ -49,12 +53,14 @@ namespace SafeExamBrowser.Monitoring.Processes
public void StartMonitoringExplorer()
{
// TODO
explorerWatcher = new ManagementEventWatcher(@"\\.\root\CIMV2", GetQueryFor("explorer.exe"));
explorerWatcher.EventArrived += new EventArrivedEventHandler(ExplorerWatcher_EventArrived);
explorerWatcher.Start();
}
public void StopMonitoringExplorer()
{
// TODO
explorerWatcher?.Stop();
}
public void CloseExplorerShell()
@ -81,5 +87,26 @@ namespace SafeExamBrowser.Monitoring.Processes
logger.Info("The explorer shell seems to already be terminated. Skipping this step...");
}
}
private void ExplorerWatcher_EventArrived(object sender, EventArrivedEventArgs e)
{
var eventName = e.NewEvent.ClassPath.ClassName;
if (eventName == "__InstanceCreationEvent")
{
logger.Warn("A new instance of Windows explorer has been started!");
ExplorerStarted?.Invoke();
}
}
private string GetQueryFor(string processName)
{
return $@"
SELECT *
FROM __InstanceOperationEvent
WITHIN 2
WHERE TargetInstance ISA 'Win32_Process'
AND TargetInstance.Name = '{processName}'";
}
}
}

View file

@ -50,6 +50,7 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Management" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />

View file

@ -20,14 +20,7 @@ namespace SafeExamBrowser.UserInterface
{
InitializeComponent();
Loaded += Taskbar_Loaded;
}
private void Taskbar_Loaded(object sender, RoutedEventArgs e)
{
Width = SystemParameters.WorkArea.Right;
Left = SystemParameters.WorkArea.Right - Width;
Top = SystemParameters.WorkArea.Bottom;
Loaded += (o, args) => InitializeBounds();
}
public void AddButton(ITaskbarButton button)
@ -52,22 +45,35 @@ namespace SafeExamBrowser.UserInterface
// to get the real height of the taskbar (in absolute, device-specific pixels).
// Source: https://stackoverflow.com/questions/3286175/how-do-i-convert-a-wpf-size-to-physical-pixels
Matrix transformToDevice;
var source = PresentationSource.FromVisual(this);
return Dispatcher.Invoke(() =>
{
Matrix transformToDevice;
var source = PresentationSource.FromVisual(this);
if (source != null)
{
transformToDevice = source.CompositionTarget.TransformToDevice;
}
else
{
using (var newSource = new HwndSource(new HwndSourceParameters()))
if (source != null)
{
transformToDevice = newSource.CompositionTarget.TransformToDevice;
transformToDevice = source.CompositionTarget.TransformToDevice;
}
else
{
using (var newSource = new HwndSource(new HwndSourceParameters()))
{
transformToDevice = newSource.CompositionTarget.TransformToDevice;
}
}
}
return (int) transformToDevice.Transform((Vector) new Size(Width, Height)).Y;
return (int)transformToDevice.Transform((Vector)new Size(Width, Height)).Y;
});
}
public void InitializeBounds()
{
Dispatcher.Invoke(() =>
{
Width = SystemParameters.WorkArea.Right;
Left = SystemParameters.WorkArea.Right - Width;
Top = SystemParameters.WorkArea.Bottom;
});
}
private void ApplicationScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)

View file

@ -29,6 +29,7 @@ namespace SafeExamBrowser
{
private IApplicationController browserController;
private IApplicationInfo browserInfo;
private IEventController eventController;
private ILogger logger;
private INotificationInfo aboutInfo;
private IProcessMonitor processMonitor;
@ -61,15 +62,17 @@ namespace SafeExamBrowser
processMonitor = new ProcessMonitor(new ModuleLogger(logger, typeof(ProcessMonitor)));
windowMonitor = new WindowMonitor(new ModuleLogger(logger, typeof(WindowMonitor)));
workingArea = new WorkingArea(new ModuleLogger(logger, typeof(WorkingArea)));
eventController = new EventController(new ModuleLogger(logger, typeof(EventController)), processMonitor, Taskbar, workingArea);
ShutdownController = new ShutdownController(logger, settings, text, uiFactory);
StartupController = new StartupController(logger, settings, text, uiFactory);
StartupOperations = new Queue<IOperation>();
StartupOperations.Enqueue(new WindowMonitoringOperation(logger, windowMonitor));
StartupOperations.Enqueue(new ProcessMonitoringOperation(logger, processMonitor));
StartupOperations.Enqueue(new WindowMonitorOperation(logger, windowMonitor));
StartupOperations.Enqueue(new ProcessMonitorOperation(logger, processMonitor));
StartupOperations.Enqueue(new WorkingAreaOperation(logger, Taskbar, workingArea));
StartupOperations.Enqueue(new TaskbarInitializationOperation(logger, aboutInfo, Taskbar, uiFactory));
StartupOperations.Enqueue(new BrowserInitializationOperation(browserController, browserInfo, logger, Taskbar, uiFactory));
StartupOperations.Enqueue(new TaskbarOperation(logger, aboutInfo, Taskbar, uiFactory));
StartupOperations.Enqueue(new BrowserOperation(browserController, browserInfo, logger, Taskbar, uiFactory));
StartupOperations.Enqueue(new EventControllerOperation(eventController, logger));
}
}
}