diff --git a/SafeExamBrowser.Core/Behaviour/StartupController.cs b/SafeExamBrowser.Core/Behaviour/StartupController.cs index 95d71155..58ee5534 100644 --- a/SafeExamBrowser.Core/Behaviour/StartupController.cs +++ b/SafeExamBrowser.Core/Behaviour/StartupController.cs @@ -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 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); + } } } diff --git a/SafeExamBrowser.UserInterface/SplashScreen.xaml.cs b/SafeExamBrowser.UserInterface/SplashScreen.xaml.cs index c340e95c..6d4c6c25 100644 --- a/SafeExamBrowser.UserInterface/SplashScreen.xaml.cs +++ b/SafeExamBrowser.UserInterface/SplashScreen.xaml.cs @@ -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; + } } } diff --git a/SafeExamBrowser/App.cs b/SafeExamBrowser/App.cs index a0335e1d..508aa06f 100644 --- a/SafeExamBrowser/App.cs +++ b/SafeExamBrowser/App.cs @@ -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(); } } } diff --git a/SafeExamBrowser/CompositionRoot.cs b/SafeExamBrowser/CompositionRoot.cs index 8e41a7ab..b352e79b 100644 --- a/SafeExamBrowser/CompositionRoot.cs +++ b/SafeExamBrowser/CompositionRoot.cs @@ -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); } } }