Restore SEBPatch
This commit is contained in:
14
SafeExamBrowser.ResetUtility/App.config
Normal file
14
SafeExamBrowser.ResetUtility/App.config
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
|
||||
</startup>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Win32.Registry" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
93
SafeExamBrowser.ResetUtility/CompositionRoot.cs
Normal file
93
SafeExamBrowser.ResetUtility/CompositionRoot.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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 System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SafeExamBrowser.Lockdown;
|
||||
using SafeExamBrowser.Lockdown.Contracts;
|
||||
using SafeExamBrowser.Logging;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.ResetUtility.Procedure;
|
||||
using SafeExamBrowser.Settings.Logging;
|
||||
using SafeExamBrowser.SystemComponents;
|
||||
|
||||
namespace SafeExamBrowser.ResetUtility
|
||||
{
|
||||
internal class CompositionRoot
|
||||
{
|
||||
private ProcedureContext context;
|
||||
private ILogger logger;
|
||||
|
||||
internal ProcedureStep InitialStep { get; private set; }
|
||||
internal NativeMethods NativeMethods { get; private set; }
|
||||
|
||||
internal void BuildObjectGraph()
|
||||
{
|
||||
InitializeLogging();
|
||||
InitializeContext();
|
||||
|
||||
InitialStep = new Initialization(context);
|
||||
NativeMethods = new NativeMethods();
|
||||
}
|
||||
|
||||
internal void LogStartupInformation()
|
||||
{
|
||||
logger.Log($"# Application started at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
|
||||
logger.Log(string.Empty);
|
||||
}
|
||||
|
||||
internal void LogShutdownInformation()
|
||||
{
|
||||
logger.Log(string.Empty);
|
||||
logger?.Log($"# Application terminated at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
|
||||
}
|
||||
|
||||
private IList<MainMenuOption> BuildMainMenu(ProcedureContext context)
|
||||
{
|
||||
return new List<MainMenuOption>
|
||||
{
|
||||
new MainMenuOption { IsSelected = true, NextStep = new Restore(context), Result = ProcedureStepResult.Continue, Text = "Restore system configuration via backup mechanism" },
|
||||
new MainMenuOption { NextStep = new Reset(context), Result = ProcedureStepResult.Continue, Text = "Reset system configuration to default values" },
|
||||
new MainMenuOption { NextStep = new Procedure.Version(context), Result = ProcedureStepResult.Continue, Text = "Show version information" },
|
||||
new MainMenuOption { NextStep = new Log(context), Result = ProcedureStepResult.Continue, Text = "Show application log" },
|
||||
new MainMenuOption { Result = ProcedureStepResult.Terminate, Text = "Exit" }
|
||||
};
|
||||
}
|
||||
|
||||
private IFeatureConfigurationBackup CreateBackup(string filePath)
|
||||
{
|
||||
return new FeatureConfigurationBackup(filePath, new ModuleLogger(logger, nameof(FeatureConfigurationBackup)));
|
||||
}
|
||||
|
||||
private void InitializeContext()
|
||||
{
|
||||
context = new ProcedureContext();
|
||||
context.ConfigurationFactory = new FeatureConfigurationFactory(new ModuleLogger(logger, nameof(FeatureConfigurationFactory)));
|
||||
context.CreateBackup = CreateBackup;
|
||||
context.Logger = logger;
|
||||
context.MainMenu = BuildMainMenu(context);
|
||||
context.Update = new SystemConfigurationUpdate(new ModuleLogger(logger, nameof(SystemConfigurationUpdate)));
|
||||
context.UserInfo = new UserInfo(new ModuleLogger(logger, nameof(UserInfo)));
|
||||
}
|
||||
|
||||
private void InitializeLogging()
|
||||
{
|
||||
var appDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), nameof(SafeExamBrowser));
|
||||
var logFolder = Path.Combine(appDataFolder, "Logs");
|
||||
var logFilePrefix = DateTime.Now.ToString("yyyy-MM-dd\\_HH\\hmm\\mss\\s");
|
||||
var logFilePath = Path.Combine(logFolder, $"{logFilePrefix}_{nameof(ResetUtility)}.log");
|
||||
var logFileWriter = new LogFileWriter(new DefaultLogFormatter(), logFilePath);
|
||||
|
||||
logger = new Logger();
|
||||
logger.LogLevel = LogLevel.Debug;
|
||||
logger.Subscribe(logFileWriter);
|
||||
logFileWriter.Initialize();
|
||||
}
|
||||
}
|
||||
}
|
52
SafeExamBrowser.ResetUtility/NativeMethods.cs
Normal file
52
SafeExamBrowser.ResetUtility/NativeMethods.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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 System.Runtime.InteropServices;
|
||||
|
||||
namespace SafeExamBrowser.ResetUtility
|
||||
{
|
||||
internal class NativeMethods
|
||||
{
|
||||
private const int GWL_STYLE = -16;
|
||||
private const int MF_BYCOMMAND = 0x0;
|
||||
private const int SC_MAXIMIZE = 0xF030;
|
||||
private const int SC_MINIMIZE = 0xF020;
|
||||
private const int SC_SIZE = 0xF000;
|
||||
private const int WS_MAXIMIZEBOX = 0x10000;
|
||||
private const int WS_MINIMIZEBOX = 0x20000;
|
||||
|
||||
internal void TryDisableSystemMenu()
|
||||
{
|
||||
try
|
||||
{
|
||||
// DeleteMenu(GetSystemMenu(GetConsoleWindow(), false), SC_MINIMIZE, MF_BYCOMMAND);
|
||||
DeleteMenu(GetSystemMenu(GetConsoleWindow(), false), SC_MAXIMIZE, MF_BYCOMMAND);
|
||||
DeleteMenu(GetSystemMenu(GetConsoleWindow(), false), SC_SIZE, MF_BYCOMMAND);
|
||||
// SetWindowLong(GetConsoleWindow(), GWL_STYLE, GetWindowLong(GetConsoleWindow(), GWL_STYLE) & ~WS_MINIMIZEBOX);
|
||||
SetWindowLong(GetConsoleWindow(), GWL_STYLE, GetWindowLong(GetConsoleWindow(), GWL_STYLE) & ~WS_MAXIMIZEBOX);
|
||||
}
|
||||
catch(Exception) { }
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int DeleteMenu(IntPtr hMenu, int nPosition, int wFlags);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr GetConsoleWindow();
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
|
||||
}
|
||||
}
|
96
SafeExamBrowser.ResetUtility/Procedure/Initialization.cs
Normal file
96
SafeExamBrowser.ResetUtility/Procedure/Initialization.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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 System.Security.Principal;
|
||||
using System.Threading;
|
||||
using SafeExamBrowser.Configuration.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.ResetUtility.Procedure
|
||||
{
|
||||
internal class Initialization : ProcedureStep
|
||||
{
|
||||
private static readonly Mutex mutex = new Mutex(true, AppConfig.SERVICE_MUTEX_NAME);
|
||||
|
||||
public Initialization(ProcedureContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
internal override ProcedureStepResult Execute()
|
||||
{
|
||||
InitializeConsole();
|
||||
|
||||
if (IsSingleInstance() && HasAdminPrivileges() && SebNotRunning())
|
||||
{
|
||||
return ProcedureStepResult.Continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ProcedureStepResult.Terminate;
|
||||
}
|
||||
}
|
||||
|
||||
internal override ProcedureStep GetNextStep()
|
||||
{
|
||||
return new MainMenu(Context);
|
||||
}
|
||||
|
||||
private bool IsSingleInstance()
|
||||
{
|
||||
var isSingle = mutex.WaitOne(TimeSpan.Zero, true);
|
||||
|
||||
if (isSingle)
|
||||
{
|
||||
Logger.Info("There is currently no other instance running.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error("There is currently another instance running! Terminating...");
|
||||
ShowError("You can only run one instance of the Reset Utility at a time! Press any key to exit...");
|
||||
}
|
||||
|
||||
return isSingle;
|
||||
}
|
||||
|
||||
private bool HasAdminPrivileges()
|
||||
{
|
||||
var identity = WindowsIdentity.GetCurrent();
|
||||
var principal = new WindowsPrincipal(identity);
|
||||
var isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
|
||||
|
||||
if (isAdmin)
|
||||
{
|
||||
Logger.Info($"User '{identity.Name}' is running the application with administrator privileges.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error($"User '{identity.Name}' is running the application without administrator privileges! Terminating...");
|
||||
ShowError("This application must be run with administrator privileges! Press any key to exit...");
|
||||
}
|
||||
|
||||
return isAdmin;
|
||||
}
|
||||
|
||||
private bool SebNotRunning()
|
||||
{
|
||||
var isRunning = Mutex.TryOpenExisting(AppConfig.RUNTIME_MUTEX_NAME, out _);
|
||||
|
||||
if (isRunning)
|
||||
{
|
||||
Logger.Error("SEB is currently running! Terminating...");
|
||||
ShowError("This application must not be run while SEB is running! Press any key to exit...");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info("SEB is currently not running.");
|
||||
}
|
||||
|
||||
return !isRunning;
|
||||
}
|
||||
}
|
||||
}
|
143
SafeExamBrowser.ResetUtility/Procedure/Log.cs
Normal file
143
SafeExamBrowser.ResetUtility/Procedure/Log.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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 System.Collections.Generic;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Settings.Logging;
|
||||
|
||||
namespace SafeExamBrowser.ResetUtility.Procedure
|
||||
{
|
||||
internal class Log : ProcedureStep
|
||||
{
|
||||
public Log(ProcedureContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
internal override ProcedureStepResult Execute()
|
||||
{
|
||||
var log = Logger.GetLog();
|
||||
var offset = 0;
|
||||
|
||||
for (var key = default(ConsoleKey); key != ConsoleKey.Enter; key = Console.ReadKey(true).Key)
|
||||
{
|
||||
offset = UpdateOffset(key, offset, log.Count);
|
||||
|
||||
InitializeConsole();
|
||||
PrintInstructions();
|
||||
PrintLogSection(log, offset);
|
||||
}
|
||||
|
||||
return ProcedureStepResult.Continue;
|
||||
}
|
||||
|
||||
internal override ProcedureStep GetNextStep()
|
||||
{
|
||||
return new MainMenu(Context);
|
||||
}
|
||||
|
||||
private void PrintInstructions()
|
||||
{
|
||||
Console.WriteLine("Use the up/down arrow keys to scroll. Press enter to return to the main menu.");
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
private void PrintLogSection(IList<ILogContent> log, int offset)
|
||||
{
|
||||
var count = 0;
|
||||
|
||||
foreach (var item in log)
|
||||
{
|
||||
if (offset > log.IndexOf(item))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item is ILogMessage message)
|
||||
{
|
||||
PrintMessage(message);
|
||||
}
|
||||
|
||||
if (item is ILogText text)
|
||||
{
|
||||
PrintText(text);
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
if (Console.CursorTop >= Console.BufferHeight - 3)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Console.SetCursorPosition(0, Console.BufferHeight - 3);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Showing entries {offset + 1} - {offset + count} of total {log.Count}.");
|
||||
}
|
||||
|
||||
private int UpdateOffset(ConsoleKey key, int offset, int total)
|
||||
{
|
||||
if (key == ConsoleKey.DownArrow)
|
||||
{
|
||||
offset = offset == total - 1 ? offset : offset + 1;
|
||||
}
|
||||
|
||||
if (key == ConsoleKey.UpArrow)
|
||||
{
|
||||
offset = offset == 0 ? offset : offset - 1;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
private void PrintMessage(ILogMessage message)
|
||||
{
|
||||
var date = message.DateTime.ToString("HH:mm:ss.fff");
|
||||
var severity = message.Severity.ToString().ToUpper();
|
||||
var threadId = message.ThreadInfo.Id < 10 ? $"0{message.ThreadInfo.Id}" : message.ThreadInfo.Id.ToString();
|
||||
var threadName = message.ThreadInfo.HasName ? ": " + message.ThreadInfo.Name : string.Empty;
|
||||
var threadInfo = $"[{threadId}{threadName}]";
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.DarkGray;
|
||||
Console.Write($"{date} {threadInfo} - ");
|
||||
Console.ForegroundColor = GetColorFor(message.Severity);
|
||||
Console.WriteLine($"{severity}: { message.Message}");
|
||||
Console.ForegroundColor = ForegroundColor;
|
||||
}
|
||||
|
||||
private void PrintText(ILogText text)
|
||||
{
|
||||
var isHeader = text.Text.StartsWith("/* ");
|
||||
var isComment = text.Text.StartsWith("# ");
|
||||
|
||||
if (isHeader || isComment)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.DarkGreen;
|
||||
}
|
||||
|
||||
Console.WriteLine(text.Text);
|
||||
Console.ForegroundColor = ForegroundColor;
|
||||
}
|
||||
|
||||
private ConsoleColor GetColorFor(LogLevel severity)
|
||||
{
|
||||
switch (severity)
|
||||
{
|
||||
case LogLevel.Debug:
|
||||
return ConsoleColor.DarkGray;
|
||||
case LogLevel.Error:
|
||||
return ConsoleColor.Red;
|
||||
case LogLevel.Warning:
|
||||
return ConsoleColor.DarkYellow;
|
||||
default:
|
||||
return ConsoleColor.DarkBlue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
32
SafeExamBrowser.ResetUtility/Procedure/MainMenu.cs
Normal file
32
SafeExamBrowser.ResetUtility/Procedure/MainMenu.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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.Linq;
|
||||
|
||||
namespace SafeExamBrowser.ResetUtility.Procedure
|
||||
{
|
||||
internal class MainMenu : ProcedureStep
|
||||
{
|
||||
public MainMenu(ProcedureContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
internal override ProcedureStepResult Execute()
|
||||
{
|
||||
InitializeConsole();
|
||||
ShowMenu(Context.MainMenu.Cast<MenuOption>().ToList(), true);
|
||||
|
||||
return Context.MainMenu.First(o => o.IsSelected).Result;
|
||||
}
|
||||
|
||||
internal override ProcedureStep GetNextStep()
|
||||
{
|
||||
return Context.MainMenu.First(o => o.IsSelected).NextStep;
|
||||
}
|
||||
}
|
||||
}
|
16
SafeExamBrowser.ResetUtility/Procedure/MainMenuOption.cs
Normal file
16
SafeExamBrowser.ResetUtility/Procedure/MainMenuOption.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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.ResetUtility.Procedure
|
||||
{
|
||||
internal class MainMenuOption : MenuOption
|
||||
{
|
||||
internal ProcedureStep NextStep { get; set; }
|
||||
internal ProcedureStepResult Result { get; set; }
|
||||
}
|
||||
}
|
21
SafeExamBrowser.ResetUtility/Procedure/MenuOption.cs
Normal file
21
SafeExamBrowser.ResetUtility/Procedure/MenuOption.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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.ResetUtility.Procedure
|
||||
{
|
||||
internal class MenuOption
|
||||
{
|
||||
internal bool IsSelected { get; set; }
|
||||
internal string Text { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{(IsSelected ? "x" : " ")}] {Text}";
|
||||
}
|
||||
}
|
||||
}
|
26
SafeExamBrowser.ResetUtility/Procedure/ProcedureContext.cs
Normal file
26
SafeExamBrowser.ResetUtility/Procedure/ProcedureContext.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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 System.Collections.Generic;
|
||||
using SafeExamBrowser.Lockdown.Contracts;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.SystemComponents.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.ResetUtility.Procedure
|
||||
{
|
||||
internal class ProcedureContext
|
||||
{
|
||||
internal IFeatureConfigurationFactory ConfigurationFactory { get; set; }
|
||||
internal Func<string, IFeatureConfigurationBackup> CreateBackup { get; set; }
|
||||
internal ILogger Logger { get; set; }
|
||||
internal IList<MainMenuOption> MainMenu { get; set; }
|
||||
internal ISystemConfigurationUpdate Update { get; set; }
|
||||
internal IUserInfo UserInfo { get; set; }
|
||||
}
|
||||
}
|
207
SafeExamBrowser.ResetUtility/Procedure/ProcedureStep.cs
Normal file
207
SafeExamBrowser.ResetUtility/Procedure/ProcedureStep.cs
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.ResetUtility.Procedure
|
||||
{
|
||||
internal abstract class ProcedureStep
|
||||
{
|
||||
private CancellationTokenSource progressAnimationToken;
|
||||
private Task progressAnimation;
|
||||
|
||||
protected ProcedureContext Context { get; }
|
||||
protected ILogger Logger => Context.Logger;
|
||||
protected ConsoleColor BackgroundColor => ConsoleColor.White;
|
||||
protected ConsoleColor ForegroundColor => ConsoleColor.Black;
|
||||
|
||||
internal ProcedureStep(ProcedureContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
internal abstract ProcedureStepResult Execute();
|
||||
internal abstract ProcedureStep GetNextStep();
|
||||
|
||||
protected void InitializeConsole()
|
||||
{
|
||||
var title = "SEB Reset Utility";
|
||||
var height = Console.LargestWindowHeight > 40 ? 40 : Console.LargestWindowHeight;
|
||||
var width = Console.LargestWindowWidth > 160 ? 160 : Console.LargestWindowWidth;
|
||||
|
||||
Console.SetBufferSize(width, height);
|
||||
Console.SetWindowSize(width, height);
|
||||
Console.BackgroundColor = BackgroundColor;
|
||||
Console.ForegroundColor = ForegroundColor;
|
||||
Console.Clear();
|
||||
Console.BackgroundColor = ConsoleColor.Gray;
|
||||
Console.ForegroundColor = ConsoleColor.Black;
|
||||
Console.Write(new String(' ', Console.BufferWidth));
|
||||
Console.Write(new String(' ', (int) Math.Floor((Console.BufferWidth - title.Length) / 2.0)));
|
||||
Console.Write(title);
|
||||
Console.Write(new String(' ', (int) Math.Ceiling((Console.BufferWidth - title.Length) / 2.0)));
|
||||
Console.Write(new String(' ', Console.BufferWidth));
|
||||
Console.BackgroundColor = BackgroundColor;
|
||||
Console.ForegroundColor = ForegroundColor;
|
||||
Console.SetCursorPosition(0, 4);
|
||||
Console.CursorVisible = false;
|
||||
}
|
||||
|
||||
protected void ClearLine(int top)
|
||||
{
|
||||
Console.SetCursorPosition(0, top);
|
||||
Console.WriteLine(new String(' ', Console.BufferWidth));
|
||||
Console.SetCursorPosition(0, top);
|
||||
}
|
||||
|
||||
protected string ReadLine()
|
||||
{
|
||||
Console.Write("> ");
|
||||
Console.CursorVisible = true;
|
||||
|
||||
var input = Console.ReadLine();
|
||||
|
||||
Console.CursorVisible = false;
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
protected void ShowError(string message)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine(message);
|
||||
Console.ForegroundColor = ForegroundColor;
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
protected void ShowMenu(IList<MenuOption> options, bool showInstructions = false)
|
||||
{
|
||||
var left = Console.CursorLeft;
|
||||
var top = Console.CursorTop;
|
||||
|
||||
PrintMenu(options, left, top, showInstructions);
|
||||
|
||||
for (var key = Console.ReadKey(true).Key; key != ConsoleKey.Enter; key = Console.ReadKey(true).Key)
|
||||
{
|
||||
if (key == ConsoleKey.UpArrow || key == ConsoleKey.DownArrow)
|
||||
{
|
||||
SelectNextOption(key, options);
|
||||
PrintMenu(options, left, top, showInstructions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void ShowProgress(int current, int total)
|
||||
{
|
||||
var scale = Console.BufferWidth - 8.0;
|
||||
var progress = Math.Floor(current * scale / total);
|
||||
var remaining = Math.Ceiling((total - current) * scale / total);
|
||||
|
||||
Console.SetCursorPosition(0, Console.CursorTop);
|
||||
Console.Write($"[{new String('■', (int) progress)}{new String('─', (int) remaining)}] {current * 100 / total}%");
|
||||
}
|
||||
|
||||
protected void StartProgressAnimation()
|
||||
{
|
||||
progressAnimationToken = new CancellationTokenSource();
|
||||
progressAnimation = Task.Run(new Action(ProgressAnimation));
|
||||
}
|
||||
|
||||
protected void StopProgressAnimation()
|
||||
{
|
||||
progressAnimationToken?.Cancel();
|
||||
progressAnimation?.Wait();
|
||||
}
|
||||
|
||||
private void PrintMenu(IList<MenuOption> options, int left, int top, bool showInstructions)
|
||||
{
|
||||
Console.SetCursorPosition(left, top);
|
||||
|
||||
if (showInstructions)
|
||||
{
|
||||
Console.WriteLine("Please choose one of the following options:");
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
foreach (var option in options)
|
||||
{
|
||||
Console.WriteLine(option.ToString());
|
||||
}
|
||||
|
||||
if (showInstructions)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Use the up/down arrow keys and enter to navigate the menu.");
|
||||
}
|
||||
}
|
||||
|
||||
private void ProgressAnimation()
|
||||
{
|
||||
var length = 12;
|
||||
var max = Console.BufferWidth - 8;
|
||||
var min = 1;
|
||||
var left = 1;
|
||||
var operand = 1;
|
||||
|
||||
Console.Write($"[{new String('■', length)}{new String('─', max - length)}]");
|
||||
|
||||
while (!progressAnimationToken.IsCancellationRequested)
|
||||
{
|
||||
Console.SetCursorPosition(left, Console.CursorTop);
|
||||
Console.Write(new String('─', length));
|
||||
|
||||
if (left + length > max)
|
||||
{
|
||||
operand = -1;
|
||||
}
|
||||
else if (left <= min)
|
||||
{
|
||||
operand = 1;
|
||||
}
|
||||
|
||||
left += operand;
|
||||
|
||||
Console.SetCursorPosition(left, Console.CursorTop);
|
||||
Console.Write(new String('■', length));
|
||||
|
||||
Thread.Sleep(20);
|
||||
}
|
||||
|
||||
Console.SetCursorPosition(0, Console.CursorTop);
|
||||
Console.WriteLine(new String(' ', Console.BufferWidth));
|
||||
Console.SetCursorPosition(0, Console.CursorTop - 2);
|
||||
}
|
||||
|
||||
private void SelectNextOption(ConsoleKey key, IList<MenuOption> options)
|
||||
{
|
||||
var current = options.First(o => o.IsSelected);
|
||||
var currentIndex = options.IndexOf(current);
|
||||
var nextIndex = default(int);
|
||||
|
||||
if (key == ConsoleKey.UpArrow)
|
||||
{
|
||||
nextIndex = --currentIndex < 0 ? options.Count - 1 : currentIndex;
|
||||
}
|
||||
|
||||
if (key == ConsoleKey.DownArrow)
|
||||
{
|
||||
nextIndex = ++currentIndex == options.Count ? 0 : currentIndex;
|
||||
}
|
||||
|
||||
var next = options.ElementAt(nextIndex);
|
||||
|
||||
current.IsSelected = false;
|
||||
next.IsSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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.ResetUtility.Procedure
|
||||
{
|
||||
internal enum ProcedureStepResult
|
||||
{
|
||||
Continue,
|
||||
Terminate
|
||||
}
|
||||
}
|
156
SafeExamBrowser.ResetUtility/Procedure/Reset.cs
Normal file
156
SafeExamBrowser.ResetUtility/Procedure/Reset.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SafeExamBrowser.Lockdown.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.ResetUtility.Procedure
|
||||
{
|
||||
internal class Reset : ProcedureStep
|
||||
{
|
||||
public Reset(ProcedureContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
internal override ProcedureStepResult Execute()
|
||||
{
|
||||
InitializeConsole();
|
||||
|
||||
var success = TryGetUserInfo(out var userName, out var sid);
|
||||
|
||||
if (success)
|
||||
{
|
||||
ResetAll(userName, sid);
|
||||
}
|
||||
|
||||
return ProcedureStepResult.Continue;
|
||||
}
|
||||
|
||||
internal override ProcedureStep GetNextStep()
|
||||
{
|
||||
return new MainMenu(Context);
|
||||
}
|
||||
|
||||
private bool TryGetUserInfo(out string userName, out string sid)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||
Console.WriteLine("IMPORTANT: Some configuration values are user specific. In order to reset these values, the user specified below needs to be logged in!");
|
||||
Console.ForegroundColor = ForegroundColor;
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Please enter the name of the user for which to reset all configuration values:");
|
||||
|
||||
userName = ReadLine();
|
||||
|
||||
StartProgressAnimation();
|
||||
var success = Context.UserInfo.TryGetSidForUser(userName, out sid);
|
||||
StopProgressAnimation();
|
||||
|
||||
while (!success)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine($"Could not find user '{userName}'!");
|
||||
Console.ForegroundColor = ForegroundColor;
|
||||
|
||||
var tryAgain = new MenuOption { IsSelected = true, Text = "Try again" };
|
||||
var mainMenu = new MenuOption { Text = "Return to main menu" };
|
||||
|
||||
ShowMenu(new List<MenuOption> { tryAgain, mainMenu });
|
||||
|
||||
if (mainMenu.IsSelected)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ClearLine(Console.CursorTop - 1);
|
||||
ClearLine(Console.CursorTop - 1);
|
||||
ClearLine(Console.CursorTop - 1);
|
||||
ClearLine(Console.CursorTop - 1);
|
||||
|
||||
userName = ReadLine();
|
||||
success = Context.UserInfo.TryGetSidForUser(userName, out sid);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private void ResetAll(string userName, string sid)
|
||||
{
|
||||
var configurations = Context.ConfigurationFactory.CreateAll(Guid.NewGuid(), sid, userName);
|
||||
var failed = new List<IFeatureConfiguration>();
|
||||
|
||||
Logger.Info($"Attempting to reset all configuration values for user '{userName}' with SID '{sid}'...");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Initiating reset procedure...");
|
||||
|
||||
foreach (var configuration in configurations)
|
||||
{
|
||||
var success = configuration.Reset();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
failed.Add(configuration);
|
||||
}
|
||||
|
||||
ShowProgress(configurations.IndexOf(configuration) + 1, configurations.Count);
|
||||
}
|
||||
|
||||
PerformUpdate();
|
||||
|
||||
if (failed.Any())
|
||||
{
|
||||
HandleFailure(failed);
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleSuccess();
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Press any key to return to the main menu.");
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
private void PerformUpdate()
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Performing system configuration update, please wait...");
|
||||
StartProgressAnimation();
|
||||
Context.Update.Execute();
|
||||
StopProgressAnimation();
|
||||
Console.WriteLine("Update completed.");
|
||||
}
|
||||
|
||||
private void HandleFailure(IList<IFeatureConfiguration> configurations)
|
||||
{
|
||||
Logger.Warn($"Failed to reset {configurations.Count} items!");
|
||||
Console.WriteLine();
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine($"Failed to reset {configurations.Count} items!");
|
||||
|
||||
foreach (var configuration in configurations)
|
||||
{
|
||||
Console.WriteLine($" - {configuration.GetType().Name}");
|
||||
}
|
||||
|
||||
Console.ForegroundColor = ForegroundColor;
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Please consult the application log for more information.");
|
||||
}
|
||||
|
||||
private void HandleSuccess()
|
||||
{
|
||||
Logger.Info("Successfully reset all changes!");
|
||||
Console.WriteLine();
|
||||
Console.ForegroundColor = ConsoleColor.DarkGreen;
|
||||
Console.WriteLine("Successfully reset all changes!");
|
||||
Console.ForegroundColor = ForegroundColor;
|
||||
}
|
||||
}
|
||||
}
|
163
SafeExamBrowser.ResetUtility/Procedure/Restore.cs
Normal file
163
SafeExamBrowser.ResetUtility/Procedure/Restore.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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 System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SafeExamBrowser.Configuration.Contracts;
|
||||
using SafeExamBrowser.Lockdown.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.ResetUtility.Procedure
|
||||
{
|
||||
internal class Restore : ProcedureStep
|
||||
{
|
||||
private ProcedureStep next;
|
||||
|
||||
public Restore(ProcedureContext context) : base(context)
|
||||
{
|
||||
next = new MainMenu(Context);
|
||||
}
|
||||
|
||||
internal override ProcedureStepResult Execute()
|
||||
{
|
||||
var filePath = $@"config\systemprofile\AppData\Local\{nameof(SafeExamBrowser)}\{AppConfig.BACKUP_FILE_NAME}";
|
||||
var x86FilePath = Environment.ExpandEnvironmentVariables($@"%WINDIR%\system32\{filePath}");
|
||||
var x64FilePath = Environment.ExpandEnvironmentVariables($@"%WINDIR%\SysWOW64\{filePath}");
|
||||
|
||||
InitializeConsole();
|
||||
|
||||
Logger.Info("Searching backup file...");
|
||||
Logger.Debug($"x86 path => {x86FilePath}");
|
||||
Logger.Debug($"x64 path => {x64FilePath}");
|
||||
Console.WriteLine("Searching backup file...");
|
||||
|
||||
if (File.Exists(x86FilePath))
|
||||
{
|
||||
RestoreBackup(x86FilePath);
|
||||
}
|
||||
else if (File.Exists(x64FilePath))
|
||||
{
|
||||
RestoreBackup(x64FilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleNoBackupFile();
|
||||
}
|
||||
|
||||
return ProcedureStepResult.Continue;
|
||||
}
|
||||
|
||||
internal override ProcedureStep GetNextStep()
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
private void RestoreBackup(string filePath)
|
||||
{
|
||||
var backup = Context.CreateBackup(filePath);
|
||||
var configurations = backup.GetAllConfigurations();
|
||||
var failed = new List<IFeatureConfiguration>();
|
||||
|
||||
Logger.Info($"Found backup file '{filePath}' with {configurations.Count} items. Initiating restore procedure...");
|
||||
Console.WriteLine($"Found backup file with {configurations.Count} items.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Initiating restore procedure...");
|
||||
|
||||
foreach (var configuration in configurations)
|
||||
{
|
||||
var success = configuration.Restore();
|
||||
|
||||
if (success)
|
||||
{
|
||||
backup.Delete(configuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
failed.Add(configuration);
|
||||
}
|
||||
|
||||
ShowProgress(configurations.IndexOf(configuration) + 1, configurations.Count);
|
||||
}
|
||||
|
||||
PerformUpdate();
|
||||
|
||||
if (failed.Any())
|
||||
{
|
||||
HandleFailure(failed);
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleSuccess();
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Press any key to return to the main menu.");
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
private void PerformUpdate()
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Performing system configuration update, please wait...");
|
||||
StartProgressAnimation();
|
||||
Context.Update.Execute();
|
||||
StopProgressAnimation();
|
||||
Console.WriteLine("Update completed.");
|
||||
}
|
||||
|
||||
private void HandleFailure(IList<IFeatureConfiguration> configurations)
|
||||
{
|
||||
Logger.Warn($"Failed to restore {configurations.Count} items!");
|
||||
Console.WriteLine();
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine($"Failed to restore {configurations.Count} items!");
|
||||
|
||||
foreach (var configuration in configurations)
|
||||
{
|
||||
Console.WriteLine($" - {configuration.GetType().Name}");
|
||||
}
|
||||
|
||||
Console.ForegroundColor = ForegroundColor;
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Some configuration values may be user specific. In order to restore these values, the user who used SEB needs to be logged in.");
|
||||
}
|
||||
|
||||
private void HandleSuccess()
|
||||
{
|
||||
Logger.Info("Successfully restored all changes!");
|
||||
Console.WriteLine();
|
||||
Console.ForegroundColor = ConsoleColor.DarkGreen;
|
||||
Console.WriteLine("Successfully restored all changes!");
|
||||
Console.ForegroundColor = ForegroundColor;
|
||||
}
|
||||
|
||||
private void HandleNoBackupFile()
|
||||
{
|
||||
var yes = new MenuOption { IsSelected = true, Text = "Yes" };
|
||||
var no = new MenuOption { Text = "No" };
|
||||
|
||||
Logger.Warn("Could not find any backup file!");
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||
Console.WriteLine("Could not find any backup file!");
|
||||
Console.ForegroundColor = ForegroundColor;
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Would you like to reset all configuration values possibly changed by SEB?");
|
||||
|
||||
ShowMenu(new List<MenuOption> { yes, no });
|
||||
|
||||
if (yes.IsSelected)
|
||||
{
|
||||
next = new Reset(Context);
|
||||
}
|
||||
|
||||
Logger.Info($"The user chose {(yes.IsSelected ? "" : "not ")}to perform a reset.");
|
||||
}
|
||||
}
|
||||
}
|
46
SafeExamBrowser.ResetUtility/Procedure/Version.cs
Normal file
46
SafeExamBrowser.ResetUtility/Procedure/Version.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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 System.Reflection;
|
||||
|
||||
namespace SafeExamBrowser.ResetUtility.Procedure
|
||||
{
|
||||
internal class Version : ProcedureStep
|
||||
{
|
||||
public Version(ProcedureContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
internal override ProcedureStepResult Execute()
|
||||
{
|
||||
var executable = Assembly.GetExecutingAssembly();
|
||||
var build = executable.GetCustomAttribute<AssemblyFileVersionAttribute>().Version;
|
||||
var copyright = executable.GetCustomAttribute<AssemblyCopyrightAttribute>().Copyright;
|
||||
var version = executable.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
|
||||
|
||||
InitializeConsole();
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.DarkBlue;
|
||||
Console.WriteLine($"Safe Exam Browser, Version {version}");
|
||||
Console.WriteLine($"Build {build}");
|
||||
Console.WriteLine(copyright.Replace("©", "(c)"));
|
||||
Console.WriteLine();
|
||||
Console.ForegroundColor = ForegroundColor;
|
||||
Console.WriteLine("Press any key to return to the main menu.");
|
||||
Console.ReadKey();
|
||||
|
||||
return ProcedureStepResult.Continue;
|
||||
}
|
||||
|
||||
internal override ProcedureStep GetNextStep()
|
||||
{
|
||||
return new MainMenu(Context);
|
||||
}
|
||||
}
|
||||
}
|
41
SafeExamBrowser.ResetUtility/Program.cs
Normal file
41
SafeExamBrowser.ResetUtility/Program.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* 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.ResetUtility.Procedure;
|
||||
|
||||
namespace SafeExamBrowser.ResetUtility
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
new Program().Run();
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
var instances = new CompositionRoot();
|
||||
|
||||
instances.BuildObjectGraph();
|
||||
instances.LogStartupInformation();
|
||||
instances.NativeMethods.TryDisableSystemMenu();
|
||||
|
||||
for (var step = instances.InitialStep; ; step = step.GetNextStep())
|
||||
{
|
||||
var result = step.Execute();
|
||||
|
||||
if (result == ProcedureStepResult.Terminate)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
instances.LogShutdownInformation();
|
||||
}
|
||||
}
|
||||
}
|
33
SafeExamBrowser.ResetUtility/Properties/AssemblyInfo.cs
Normal file
33
SafeExamBrowser.ResetUtility/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("SafeExamBrowser.ResetUtility")]
|
||||
[assembly: AssemblyDescription("Safe Exam Browser")]
|
||||
[assembly: AssemblyCompany("ETH Zürich")]
|
||||
[assembly: AssemblyProduct("SafeExamBrowser.ResetUtility")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2024 ETH Zürich, IT Services")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("bc229e80-ff93-424f-9930-d9c07d9b57b4")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: AssemblyInformationalVersion("1.0.0.0")]
|
BIN
SafeExamBrowser.ResetUtility/ResetUtility.ico
Normal file
BIN
SafeExamBrowser.ResetUtility/ResetUtility.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
126
SafeExamBrowser.ResetUtility/SafeExamBrowser.ResetUtility.csproj
Normal file
126
SafeExamBrowser.ResetUtility/SafeExamBrowser.ResetUtility.csproj
Normal file
@@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{BC229E80-FF93-424F-9930-D9C07D9B57B4}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>SafeExamBrowser.ResetUtility</RootNamespace>
|
||||
<AssemblyName>SafeExamBrowser.ResetUtility</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>ResetUtility.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Procedure\ProcedureContext.cs" />
|
||||
<Compile Include="CompositionRoot.cs" />
|
||||
<Compile Include="NativeMethods.cs" />
|
||||
<Compile Include="Procedure\Initialization.cs" />
|
||||
<Compile Include="Procedure\MainMenu.cs" />
|
||||
<Compile Include="Procedure\MainMenuOption.cs" />
|
||||
<Compile Include="Procedure\MenuOption.cs" />
|
||||
<Compile Include="Procedure\ProcedureStep.cs" />
|
||||
<Compile Include="Procedure\ProcedureStepResult.cs" />
|
||||
<Compile Include="Procedure\Reset.cs" />
|
||||
<Compile Include="Procedure\Restore.cs" />
|
||||
<Compile Include="Procedure\Log.cs" />
|
||||
<Compile Include="Procedure\Version.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="app.manifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Configuration.Contracts\SafeExamBrowser.Configuration.Contracts.csproj">
|
||||
<Project>{7d74555e-63e1-4c46-bd0a-8580552368c8}</Project>
|
||||
<Name>SafeExamBrowser.Configuration.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Lockdown.Contracts\SafeExamBrowser.Lockdown.Contracts.csproj">
|
||||
<Project>{3368b17d-6060-4482-9983-aa800d74041d}</Project>
|
||||
<Name>SafeExamBrowser.Lockdown.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Lockdown\SafeExamBrowser.Lockdown.csproj">
|
||||
<Project>{386b6042-3e12-4753-9fc6-c88ea4f97030}</Project>
|
||||
<Name>SafeExamBrowser.Lockdown</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Logging.Contracts\SafeExamBrowser.Logging.Contracts.csproj">
|
||||
<Project>{64ea30fb-11d4-436a-9c2b-88566285363e}</Project>
|
||||
<Name>SafeExamBrowser.Logging.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Logging\SafeExamBrowser.Logging.csproj">
|
||||
<Project>{e107026c-2011-4552-a7d8-3a0d37881df6}</Project>
|
||||
<Name>SafeExamBrowser.Logging</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Settings\SafeExamBrowser.Settings.csproj">
|
||||
<Project>{30b2d907-5861-4f39-abad-c4abf1b3470e}</Project>
|
||||
<Name>SafeExamBrowser.Settings</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.SystemComponents.Contracts\SafeExamBrowser.SystemComponents.Contracts.csproj">
|
||||
<Project>{903129c6-e236-493b-9ad6-c6a57f647a3a}</Project>
|
||||
<Name>SafeExamBrowser.SystemComponents.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.SystemComponents\SafeExamBrowser.SystemComponents.csproj">
|
||||
<Project>{acee2ef1-14d2-4b52-8994-5c053055bb51}</Project>
|
||||
<Name>SafeExamBrowser.SystemComponents</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="ResetUtility.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
11
SafeExamBrowser.ResetUtility/app.manifest
Normal file
11
SafeExamBrowser.ResetUtility/app.manifest
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
Reference in New Issue
Block a user