Found solution to multi-threading issue at application startup and created draft of startup procedure.
This commit is contained in:
parent
8adb72bb0f
commit
d86bd79252
4 changed files with 181 additions and 80 deletions
|
@ -7,6 +7,8 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using SafeExamBrowser.Contracts.Behaviour;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
|
@ -27,6 +29,23 @@ namespace SafeExamBrowser.Core.Behaviour
|
|||
private IText text;
|
||||
private IUiElementFactory uiFactory;
|
||||
|
||||
private IEnumerable<Action> StartupOperations
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return InitializeApplicationLog;
|
||||
yield return HandleCommandLineArguments;
|
||||
yield return DetectOperatingSystem;
|
||||
yield return EstablishWcfServiceConnection;
|
||||
yield return DeactivateWindowsFeatures;
|
||||
yield return InitializeProcessMonitoring;
|
||||
yield return InitializeWorkArea;
|
||||
yield return InitializeTaskbar;
|
||||
yield return InitializeBrowser;
|
||||
yield return FinishInitialization;
|
||||
}
|
||||
}
|
||||
|
||||
public StartupController(IApplicationInfo browserInfo, ILogger logger, IMessageBox messageBox, ISettings settings, ISplashScreen splashScreen, ITaskbar taskbar, IText text, IUiElementFactory uiFactory)
|
||||
{
|
||||
this.browserInfo = browserInfo;
|
||||
|
@ -43,47 +62,15 @@ namespace SafeExamBrowser.Core.Behaviour
|
|||
{
|
||||
try
|
||||
{
|
||||
logger.Log(settings.LogHeader);
|
||||
logger.Log($"{Environment.NewLine}# Application started at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}{Environment.NewLine}");
|
||||
logger.Info("Initiating startup procedure.");
|
||||
logger.Subscribe(splashScreen);
|
||||
foreach (var operation in StartupOperations)
|
||||
{
|
||||
operation();
|
||||
|
||||
splashScreen.SetMaxProgress(3);
|
||||
logger.Info("Initializing browser.");
|
||||
splashScreen.UpdateProgress();
|
||||
|
||||
var browserButton = uiFactory.CreateButton(browserInfo);
|
||||
|
||||
taskbar.AddButton(browserButton);
|
||||
|
||||
splashScreen.UpdateProgress();
|
||||
|
||||
// TODO (depending on specification):
|
||||
// - WCF service connection, termination if not available
|
||||
|
||||
// TODO:
|
||||
// - Parse command line arguments
|
||||
// - Detecting operating system and log that information
|
||||
// - Logging of all running processes
|
||||
// - Setting of wallpaper
|
||||
// - Initialization of taskbar
|
||||
// - Killing explorer.exe
|
||||
// - Minimizing all open windows
|
||||
// - Emptying clipboard
|
||||
// - Activation of process monitoring
|
||||
|
||||
Thread.Sleep(1000);
|
||||
|
||||
splashScreen.UpdateProgress();
|
||||
logger.Info("Baapa-dee boopa-dee!");
|
||||
|
||||
Thread.Sleep(1000);
|
||||
|
||||
splashScreen.UpdateProgress();
|
||||
logger.Info("Closing splash screen.");
|
||||
|
||||
Thread.Sleep(1000);
|
||||
logger.Unsubscribe(splashScreen);
|
||||
logger.Info("Application successfully initialized!");
|
||||
// TODO: Remove!
|
||||
Thread.Sleep(250);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -95,5 +82,88 @@ namespace SafeExamBrowser.Core.Behaviour
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeApplicationLog()
|
||||
{
|
||||
logger.Log(settings.LogHeader);
|
||||
logger.Log($"{Environment.NewLine}# Application started at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}{Environment.NewLine}");
|
||||
logger.Info("Initiating startup procedure.");
|
||||
logger.Subscribe(splashScreen);
|
||||
|
||||
splashScreen.SetMaxProgress(StartupOperations.Count());
|
||||
}
|
||||
|
||||
private void HandleCommandLineArguments()
|
||||
{
|
||||
logger.Info("Parsing command line arguments.");
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
private void DetectOperatingSystem()
|
||||
{
|
||||
logger.Info("Detecting operating system.");
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
private void EstablishWcfServiceConnection()
|
||||
{
|
||||
logger.Info("Establishing connection to WCF service.");
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
private void DeactivateWindowsFeatures()
|
||||
{
|
||||
logger.Info("Deactivating Windows Update.");
|
||||
|
||||
// TODO
|
||||
|
||||
logger.Info("Disabling lock screen options.");
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
private void InitializeProcessMonitoring()
|
||||
{
|
||||
logger.Info("Initializing process monitoring.");
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
private void InitializeWorkArea()
|
||||
{
|
||||
logger.Info("Initializing work area.");
|
||||
|
||||
// TODO
|
||||
// - Killing explorer.exe
|
||||
// - Minimizing all open windows
|
||||
// - Emptying clipboard
|
||||
}
|
||||
|
||||
private void InitializeTaskbar()
|
||||
{
|
||||
logger.Info("Initializing taskbar.");
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
private void InitializeBrowser()
|
||||
{
|
||||
logger.Info("Initializing browser.");
|
||||
|
||||
var browserButton = uiFactory.CreateButton(browserInfo);
|
||||
|
||||
// TODO
|
||||
|
||||
taskbar.AddButton(browserButton);
|
||||
}
|
||||
|
||||
private void FinishInitialization()
|
||||
{
|
||||
logger.Info("Application successfully initialized!");
|
||||
logger.Unsubscribe(splashScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,14 +22,7 @@ namespace SafeExamBrowser.UserInterface
|
|||
public SplashScreen(ISettings settings)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
StatusTextBlock.DataContext = model;
|
||||
ProgressBar.DataContext = model;
|
||||
|
||||
InfoTextBlock.Inlines.Add(new Run($"Version {settings.ProgramVersion}") { FontStyle = FontStyles.Italic });
|
||||
InfoTextBlock.Inlines.Add(new LineBreak());
|
||||
InfoTextBlock.Inlines.Add(new LineBreak());
|
||||
InfoTextBlock.Inlines.Add(new Run(settings.CopyrightInfo) { FontSize = 10 });
|
||||
InitializeSplashScreen(settings);
|
||||
}
|
||||
|
||||
public void Notify(ILogContent content)
|
||||
|
@ -49,5 +42,19 @@ namespace SafeExamBrowser.UserInterface
|
|||
{
|
||||
model.CurrentProgress += amount;
|
||||
}
|
||||
|
||||
private void InitializeSplashScreen(ISettings settings)
|
||||
{
|
||||
InfoTextBlock.Inlines.Add(new Run($"Version {settings.ProgramVersion}") { FontStyle = FontStyles.Italic });
|
||||
InfoTextBlock.Inlines.Add(new LineBreak());
|
||||
InfoTextBlock.Inlines.Add(new LineBreak());
|
||||
InfoTextBlock.Inlines.Add(new Run(settings.CopyrightInfo) { FontSize = 10 });
|
||||
|
||||
StatusTextBlock.DataContext = model;
|
||||
ProgressBar.DataContext = model;
|
||||
|
||||
// To prevent the progress bar going from max to min value at startup...
|
||||
model.MaxProgress = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace SafeExamBrowser
|
|||
public class App : Application
|
||||
{
|
||||
private static readonly Mutex mutex = new Mutex(true, "safe_exam_browser_single_instance_mutex");
|
||||
private CompositionRoot instances;
|
||||
private CompositionRoot instances = new CompositionRoot();
|
||||
|
||||
[STAThread]
|
||||
public static void Main()
|
||||
|
@ -51,17 +51,8 @@ namespace SafeExamBrowser
|
|||
{
|
||||
base.OnStartup(e);
|
||||
|
||||
var initializationThread = new Thread(Initialize);
|
||||
|
||||
instances = new CompositionRoot();
|
||||
instances.BuildObjectGraph();
|
||||
instances.SplashScreen.Show();
|
||||
|
||||
MainWindow = instances.SplashScreen;
|
||||
|
||||
initializationThread.SetApartmentState(ApartmentState.STA);
|
||||
initializationThread.Name = "Initialization Thread";
|
||||
initializationThread.Start();
|
||||
ShowSplashScreen();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
protected override void OnExit(ExitEventArgs e)
|
||||
|
@ -73,22 +64,43 @@ namespace SafeExamBrowser
|
|||
|
||||
private void Initialize()
|
||||
{
|
||||
instances.BuildObjectGraph();
|
||||
|
||||
var success = instances.StartupController.TryInitializeApplication();
|
||||
|
||||
if (success)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
MainWindow = instances.Taskbar;
|
||||
MainWindow.Show();
|
||||
});
|
||||
MainWindow = instances.Taskbar;
|
||||
MainWindow.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
Dispatcher.Invoke(Shutdown);
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
Dispatcher.Invoke(instances.SplashScreen.Close);
|
||||
instances.SplashScreen?.Dispatcher.InvokeAsync(instances.SplashScreen.Close);
|
||||
}
|
||||
|
||||
private void ShowSplashScreen()
|
||||
{
|
||||
var splashReadyEvent = new AutoResetEvent(false);
|
||||
var splashScreenThread = new Thread(() =>
|
||||
{
|
||||
instances.SplashScreen = new UserInterface.SplashScreen(instances.Settings);
|
||||
instances.SplashScreen.Closed += (o, args) => instances.SplashScreen.Dispatcher.InvokeShutdown();
|
||||
instances.SplashScreen.Show();
|
||||
|
||||
splashReadyEvent.Set();
|
||||
|
||||
System.Windows.Threading.Dispatcher.Run();
|
||||
});
|
||||
|
||||
splashScreenThread.SetApartmentState(ApartmentState.STA);
|
||||
splashScreenThread.Name = "Splash Screen Thread";
|
||||
splashScreenThread.IsBackground = true;
|
||||
splashScreenThread.Start();
|
||||
|
||||
splashReadyEvent.WaitOne();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
|
||||
using SafeExamBrowser.Browser;
|
||||
using SafeExamBrowser.Contracts.Behaviour;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Core.Behaviour;
|
||||
using SafeExamBrowser.Core.Configuration;
|
||||
using SafeExamBrowser.Core.I18n;
|
||||
|
@ -18,27 +22,35 @@ namespace SafeExamBrowser
|
|||
{
|
||||
internal class CompositionRoot
|
||||
{
|
||||
public IShutdownController ShutdownController { get; set; }
|
||||
public IStartupController StartupController { get; private set; }
|
||||
private IApplicationInfo browserInfo;
|
||||
private IMessageBox messageBox;
|
||||
private ILogger logger;
|
||||
private IUiElementFactory uiFactory;
|
||||
private IText text;
|
||||
|
||||
public SplashScreen SplashScreen { get; private set; }
|
||||
public ISettings Settings { get; private set; }
|
||||
public IShutdownController ShutdownController { get; private set; }
|
||||
public IStartupController StartupController { get; private set; }
|
||||
public SplashScreen SplashScreen { get; set; }
|
||||
public Taskbar Taskbar { get; private set; }
|
||||
|
||||
public CompositionRoot()
|
||||
{
|
||||
browserInfo = new BrowserApplicationInfo();
|
||||
messageBox = new WpfMessageBox();
|
||||
logger = new Logger();
|
||||
Settings = new Settings();
|
||||
Taskbar = new Taskbar();
|
||||
uiFactory = new UiElementFactory();
|
||||
}
|
||||
|
||||
public void BuildObjectGraph()
|
||||
{
|
||||
var browserInfo = new BrowserApplicationInfo();
|
||||
var messageBox = new WpfMessageBox();
|
||||
var settings = new Settings();
|
||||
var logger = new Logger();
|
||||
var text = new Text(new XmlTextResource());
|
||||
var uiFactory = new UiElementFactory();
|
||||
|
||||
logger.Subscribe(new LogFileWriter(settings));
|
||||
logger.Subscribe(new LogFileWriter(Settings));
|
||||
|
||||
Taskbar = new Taskbar();
|
||||
SplashScreen = new SplashScreen(settings);
|
||||
text = new Text(new XmlTextResource());
|
||||
ShutdownController = new ShutdownController(logger, messageBox, text);
|
||||
StartupController = new StartupController(browserInfo, logger, messageBox, settings, SplashScreen, Taskbar, text, uiFactory);
|
||||
StartupController = new StartupController(browserInfo, logger, messageBox, Settings, SplashScreen, Taskbar, text, uiFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue