SEBWIN-633: Fixed ease of access exploit.

This commit is contained in:
Damian Büchel 2022-12-21 05:37:03 +01:00
parent 3bd786543d
commit f0aecb06d9
19 changed files with 417 additions and 22 deletions

View file

@ -33,6 +33,7 @@ using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Server.Contracts.Data; using SafeExamBrowser.Server.Contracts.Data;
using SafeExamBrowser.Settings; using SafeExamBrowser.Settings;
using SafeExamBrowser.Settings.Monitoring; using SafeExamBrowser.Settings.Monitoring;
using SafeExamBrowser.SystemComponents.Contracts.Registry;
using SafeExamBrowser.UserInterface.Contracts; using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog; using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog;
using SafeExamBrowser.UserInterface.Contracts.MessageBox; using SafeExamBrowser.UserInterface.Contracts.MessageBox;
@ -60,6 +61,7 @@ namespace SafeExamBrowser.Client.UnitTests
private Mock<ILogger> logger; private Mock<ILogger> logger;
private Mock<IMessageBox> messageBox; private Mock<IMessageBox> messageBox;
private Mock<IOperationSequence> operationSequence; private Mock<IOperationSequence> operationSequence;
private Mock<IRegistry> registry;
private Mock<IRuntimeProxy> runtimeProxy; private Mock<IRuntimeProxy> runtimeProxy;
private Mock<IServerProxy> server; private Mock<IServerProxy> server;
private Guid sessionId; private Guid sessionId;
@ -92,6 +94,7 @@ namespace SafeExamBrowser.Client.UnitTests
logger = new Mock<ILogger>(); logger = new Mock<ILogger>();
messageBox = new Mock<IMessageBox>(); messageBox = new Mock<IMessageBox>();
operationSequence = new Mock<IOperationSequence>(); operationSequence = new Mock<IOperationSequence>();
registry = new Mock<IRegistry>();
runtimeProxy = new Mock<IRuntimeProxy>(); runtimeProxy = new Mock<IRuntimeProxy>();
server = new Mock<IServerProxy>(); server = new Mock<IServerProxy>();
sessionId = Guid.NewGuid(); sessionId = Guid.NewGuid();
@ -119,6 +122,7 @@ namespace SafeExamBrowser.Client.UnitTests
logger.Object, logger.Object,
messageBox.Object, messageBox.Object,
operationSequence.Object, operationSequence.Object,
registry.Object,
runtimeProxy.Object, runtimeProxy.Object,
shutdown.Object, shutdown.Object,
splashScreen.Object, splashScreen.Object,

View file

@ -33,6 +33,7 @@ using SafeExamBrowser.Monitoring.Contracts.System;
using SafeExamBrowser.Server.Contracts; using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Server.Contracts.Data; using SafeExamBrowser.Server.Contracts.Data;
using SafeExamBrowser.Settings; using SafeExamBrowser.Settings;
using SafeExamBrowser.SystemComponents.Contracts.Registry;
using SafeExamBrowser.UserInterface.Contracts; using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog; using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog;
using SafeExamBrowser.UserInterface.Contracts.MessageBox; using SafeExamBrowser.UserInterface.Contracts.MessageBox;
@ -55,6 +56,7 @@ namespace SafeExamBrowser.Client
private readonly ILogger logger; private readonly ILogger logger;
private readonly IMessageBox messageBox; private readonly IMessageBox messageBox;
private readonly IOperationSequence operations; private readonly IOperationSequence operations;
private readonly IRegistry registry;
private readonly IRuntimeProxy runtime; private readonly IRuntimeProxy runtime;
private readonly Action shutdown; private readonly Action shutdown;
private readonly ISplashScreen splashScreen; private readonly ISplashScreen splashScreen;
@ -83,6 +85,7 @@ namespace SafeExamBrowser.Client
ILogger logger, ILogger logger,
IMessageBox messageBox, IMessageBox messageBox,
IOperationSequence operations, IOperationSequence operations,
IRegistry registry,
IRuntimeProxy runtime, IRuntimeProxy runtime,
Action shutdown, Action shutdown,
ISplashScreen splashScreen, ISplashScreen splashScreen,
@ -101,6 +104,7 @@ namespace SafeExamBrowser.Client
this.logger = logger; this.logger = logger;
this.messageBox = messageBox; this.messageBox = messageBox;
this.operations = operations; this.operations = operations;
this.registry = registry;
this.runtime = runtime; this.runtime = runtime;
this.shutdown = shutdown; this.shutdown = shutdown;
this.splashScreen = splashScreen; this.splashScreen = splashScreen;
@ -167,6 +171,7 @@ namespace SafeExamBrowser.Client
CloseShell(); CloseShell();
DeregisterEvents(); DeregisterEvents();
UpdateSessionIntegrity(); UpdateSessionIntegrity();
TerminateIntegrityVerification();
var success = operations.TryRevert() == OperationResult.Success; var success = operations.TryRevert() == OperationResult.Success;
@ -206,6 +211,7 @@ namespace SafeExamBrowser.Client
ClientHost.ServerFailureActionRequested += ClientHost_ServerFailureActionRequested; ClientHost.ServerFailureActionRequested += ClientHost_ServerFailureActionRequested;
ClientHost.Shutdown += ClientHost_Shutdown; ClientHost.Shutdown += ClientHost_Shutdown;
displayMonitor.DisplayChanged += DisplayMonitor_DisplaySettingsChanged; displayMonitor.DisplayChanged += DisplayMonitor_DisplaySettingsChanged;
registry.ValueChanged += Registry_ValueChanged;
runtime.ConnectionLost += Runtime_ConnectionLost; runtime.ConnectionLost += Runtime_ConnectionLost;
systemMonitor.SessionSwitched += SystemMonitor_SessionSwitched; systemMonitor.SessionSwitched += SystemMonitor_SessionSwitched;
taskbar.LoseFocusRequested += Taskbar_LoseFocusRequested; taskbar.LoseFocusRequested += Taskbar_LoseFocusRequested;
@ -240,6 +246,7 @@ namespace SafeExamBrowser.Client
applicationMonitor.ExplorerStarted -= ApplicationMonitor_ExplorerStarted; applicationMonitor.ExplorerStarted -= ApplicationMonitor_ExplorerStarted;
applicationMonitor.TerminationFailed -= ApplicationMonitor_TerminationFailed; applicationMonitor.TerminationFailed -= ApplicationMonitor_TerminationFailed;
displayMonitor.DisplayChanged -= DisplayMonitor_DisplaySettingsChanged; displayMonitor.DisplayChanged -= DisplayMonitor_DisplaySettingsChanged;
registry.ValueChanged -= Registry_ValueChanged;
runtime.ConnectionLost -= Runtime_ConnectionLost; runtime.ConnectionLost -= Runtime_ConnectionLost;
systemMonitor.SessionSwitched -= SystemMonitor_SessionSwitched; systemMonitor.SessionSwitched -= SystemMonitor_SessionSwitched;
taskbar.QuitButtonClicked -= Shell_QuitButtonClicked; taskbar.QuitButtonClicked -= Shell_QuitButtonClicked;
@ -351,6 +358,8 @@ namespace SafeExamBrowser.Client
}; };
timer.Interval = TEN_MINUTES + (new Random().NextDouble() * FIVE_MINUTES); timer.Interval = TEN_MINUTES + (new Random().NextDouble() * FIVE_MINUTES);
timer.Start(); timer.Start();
registry.StartMonitoring(RegistryKey.MachineHive.EaseOfAccess_Key, RegistryKey.MachineHive.EaseOfAccess_Name);
} }
private void VerifySessionIntegrity() private void VerifySessionIntegrity()
@ -394,6 +403,11 @@ namespace SafeExamBrowser.Client
} }
} }
private void TerminateIntegrityVerification()
{
registry.StopMonitoring();
}
private void ApplicationMonitor_ExplorerStarted() private void ApplicationMonitor_ExplorerStarted()
{ {
logger.Info("Trying to terminate Windows explorer..."); logger.Info("Trying to terminate Windows explorer...");
@ -681,6 +695,40 @@ namespace SafeExamBrowser.Client
splashScreen.UpdateStatus(status, true); splashScreen.UpdateStatus(status, true);
} }
private void Registry_ValueChanged(object oldValue, object newValue)
{
logger.Warn($"The ease of access registry value has changed from '{oldValue}' to '{newValue}'! Attempting to show lock screen...");
if (!sessionLocked)
{
var message = text.Get(TextKey.LockScreen_EaseOfAccessMessage);
var title = text.Get(TextKey.LockScreen_Title);
var continueOption = new LockScreenOption { Text = text.Get(TextKey.LockScreen_EaseOfAccessContinueOption) };
var terminateOption = new LockScreenOption { Text = text.Get(TextKey.LockScreen_EaseOfAccessTerminateOption) };
sessionLocked = true;
registry.StopMonitoring();
var result = ShowLockScreen(message, title, new[] { continueOption, terminateOption });
if (result.OptionId == continueOption.Id)
{
logger.Info("The session will be allowed to resume as requested by the user...");
}
else if (result.OptionId == terminateOption.Id)
{
logger.Info("Attempting to shutdown as requested by the user...");
TryRequestShutdown();
}
sessionLocked = false;
}
else
{
logger.Info("Lock screen is already active.");
}
}
private void Runtime_ConnectionLost() private void Runtime_ConnectionLost()
{ {
logger.Error("Lost connection to the runtime!"); logger.Error("Lost connection to the runtime!");

View file

@ -45,6 +45,7 @@ using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.SystemComponents.Keyboard; using SafeExamBrowser.SystemComponents.Keyboard;
using SafeExamBrowser.SystemComponents.Network; using SafeExamBrowser.SystemComponents.Network;
using SafeExamBrowser.SystemComponents.PowerSupply; using SafeExamBrowser.SystemComponents.PowerSupply;
using SafeExamBrowser.SystemComponents.Registry;
using SafeExamBrowser.UserInterface.Contracts; using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog; using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog;
using SafeExamBrowser.UserInterface.Contracts.MessageBox; using SafeExamBrowser.UserInterface.Contracts.MessageBox;
@ -113,6 +114,7 @@ namespace SafeExamBrowser.Client
var explorerShell = new ExplorerShell(ModuleLogger(nameof(ExplorerShell)), nativeMethods); var explorerShell = new ExplorerShell(ModuleLogger(nameof(ExplorerShell)), nativeMethods);
var fileSystemDialog = BuildFileSystemDialog(); var fileSystemDialog = BuildFileSystemDialog();
var hashAlgorithm = new HashAlgorithm(); var hashAlgorithm = new HashAlgorithm();
var registry = new Registry(ModuleLogger(nameof(Registry)));
var splashScreen = uiFactory.CreateSplashScreen(); var splashScreen = uiFactory.CreateSplashScreen();
var systemMonitor = new SystemMonitor(ModuleLogger(nameof(SystemMonitor))); var systemMonitor = new SystemMonitor(ModuleLogger(nameof(SystemMonitor)));
@ -149,6 +151,7 @@ namespace SafeExamBrowser.Client
logger, logger,
messageBox, messageBox,
sequence, sequence,
registry,
runtimeProxy, runtimeProxy,
shutdown, shutdown,
splashScreen, splashScreen,

View file

@ -65,8 +65,11 @@ namespace SafeExamBrowser.I18n.Contracts
LockScreen_ApplicationsMessage, LockScreen_ApplicationsMessage,
LockScreen_ApplicationsTerminateOption, LockScreen_ApplicationsTerminateOption,
LockScreen_DisplayConfigurationContinueOption, LockScreen_DisplayConfigurationContinueOption,
LockScreen_DisplayConfigurationTerminateOption,
LockScreen_DisplayConfigurationMessage, LockScreen_DisplayConfigurationMessage,
LockScreen_DisplayConfigurationTerminateOption,
LockScreen_EaseOfAccessContinueOption,
LockScreen_EaseOfAccessMessage,
LockScreen_EaseOfAccessTerminateOption,
LockScreen_SessionIntegrityMessage, LockScreen_SessionIntegrityMessage,
LockScreen_Title, LockScreen_Title,
LockScreen_UnlockButton, LockScreen_UnlockButton,
@ -197,6 +200,7 @@ namespace SafeExamBrowser.I18n.Contracts
OperationStatus_ValidateRemoteSessionPolicy, OperationStatus_ValidateRemoteSessionPolicy,
OperationStatus_ValidateVirtualMachinePolicy, OperationStatus_ValidateVirtualMachinePolicy,
OperationStatus_VerifyApplicationIntegrity, OperationStatus_VerifyApplicationIntegrity,
OperationStatus_VerifySessionIntegrity,
OperationStatus_WaitDisclaimerConfirmation, OperationStatus_WaitDisclaimerConfirmation,
OperationStatus_WaitExplorerStartup, OperationStatus_WaitExplorerStartup,
OperationStatus_WaitExplorerTermination, OperationStatus_WaitExplorerTermination,

View file

@ -153,11 +153,20 @@
<Entry key="LockScreen_DisplayConfigurationContinueOption"> <Entry key="LockScreen_DisplayConfigurationContinueOption">
Bildschirm-Konfiguration temporär erlauben. Dies gilt nur für die momentan laufende Sitzung! Bildschirm-Konfiguration temporär erlauben. Dies gilt nur für die momentan laufende Sitzung!
</Entry> </Entry>
<Entry key="LockScreen_DisplayConfigurationMessage">
Eine verbotene Bildschirm-Konfiguration wurde detektiert. Bitte wählen Sie eine der verfügbaren Optionen aus und geben Sie das korrekte Passwort ein, um SEB zu entsperren.
</Entry>
<Entry key="LockScreen_DisplayConfigurationTerminateOption"> <Entry key="LockScreen_DisplayConfigurationTerminateOption">
Safe Exam Browser beenden. WARNUNG: Sie werden keine Möglichkeit haben, Daten zu speichern oder weitere Aktionen auszuführen, SEB wird sofort beendet! Safe Exam Browser beenden. WARNUNG: Sie werden keine Möglichkeit haben, Daten zu speichern oder weitere Aktionen auszuführen, SEB wird sofort beendet!
</Entry> </Entry>
<Entry key="LockScreen_DisplayConfigurationMessage"> <Entry key="LockScreen_EaseOfAccessContinueOption">
Eine verbotene Bildschirm-Konfiguration wurde detektiert. Bitte wählen Sie eine der verfügbaren Optionen aus und geben Sie das korrekte Passwort ein, um SEB zu entsperren. Barrierefreiheit-Konfiguration temporär erlauben. Dies gilt nur für die momentan laufende Sitzung!
</Entry>
<Entry key="LockScreen_EaseOfAccessMessage">
Eine verbotene Barrierefreiheit-Konfiguration für den Windows Security Screen wurde detektiert. Bitte wählen Sie eine der verfügbaren Optionen aus und geben Sie das korrekte Passwort ein, um SEB zu entsperren.
</Entry>
<Entry key="LockScreen_EaseOfAccessTerminateOption">
Safe Exam Browser beenden. WARNUNG: Sie werden keine Möglichkeit haben, Daten zu speichern oder weitere Aktionen auszuführen, SEB wird sofort beendet!
</Entry> </Entry>
<Entry key="LockScreen_SessionIntegrityMessage"> <Entry key="LockScreen_SessionIntegrityMessage">
Die letzte Sitzung mit der momentan aktiven Konfiguration oder Start-URL wurde nicht ordnungsgemäss beendet! Geben Sie bitte das korrekte Passwort ein, um SEB zu entsperren. Die letzte Sitzung mit der momentan aktiven Konfiguration oder Start-URL wurde nicht ordnungsgemäss beendet! Geben Sie bitte das korrekte Passwort ein, um SEB zu entsperren.
@ -549,6 +558,9 @@
<Entry key="OperationStatus_VerifyApplicationIntegrity"> <Entry key="OperationStatus_VerifyApplicationIntegrity">
Überprüfe Integrität Überprüfe Integrität
</Entry> </Entry>
<Entry key="OperationStatus_VerifySessionIntegrity">
Überprüfe Integrität der Sitzung
</Entry>
<Entry key="OperationStatus_WaitDisclaimerConfirmation"> <Entry key="OperationStatus_WaitDisclaimerConfirmation">
Warte auf die Bestätigung des Hinweises zur Fernüberwachung Warte auf die Bestätigung des Hinweises zur Fernüberwachung
</Entry> </Entry>

View file

@ -153,11 +153,20 @@
<Entry key="LockScreen_DisplayConfigurationContinueOption"> <Entry key="LockScreen_DisplayConfigurationContinueOption">
Temporarily allow the display configuration. This applies only to the currently running session! Temporarily allow the display configuration. This applies only to the currently running session!
</Entry> </Entry>
<Entry key="LockScreen_DisplayConfigurationMessage">
A prohibited display configuration has been detected. In order to unlock SEB, please select one of the available options and enter the correct unlock password.
</Entry>
<Entry key="LockScreen_DisplayConfigurationTerminateOption"> <Entry key="LockScreen_DisplayConfigurationTerminateOption">
Terminate Safe Exam Browser. WARNING: There will be no possibility to save data or perform any further actions, the shutdown will be initiated immediately! Terminate Safe Exam Browser. WARNING: There will be no possibility to save data or perform any further actions, the shutdown will be initiated immediately!
</Entry> </Entry>
<Entry key="LockScreen_DisplayConfigurationMessage"> <Entry key="LockScreen_EaseOfAccessContinueOption">
A prohibited display configuration has been detected. In order to unlock SEB, please select one of the available options and enter the correct unlock password. Temporarily allow the ease of access configuration. This applies only to the currently running session!
</Entry>
<Entry key="LockScreen_EaseOfAccessMessage">
A prohibited ease of access configuration for the Windows Security Screen has been detected. In order to unlock SEB, please select one of the available options and enter the correct unlock password.
</Entry>
<Entry key="LockScreen_EaseOfAccessTerminateOption">
Terminate Safe Exam Browser. WARNING: There will be no possibility to save data or perform any further actions, the shutdown will be initiated immediately!
</Entry> </Entry>
<Entry key="LockScreen_SessionIntegrityMessage"> <Entry key="LockScreen_SessionIntegrityMessage">
The last session with the currently active configuration or start URL was not terminated properly! Please enter the correct password to unlock SEB. The last session with the currently active configuration or start URL was not terminated properly! Please enter the correct password to unlock SEB.
@ -549,6 +558,9 @@
<Entry key="OperationStatus_VerifyApplicationIntegrity"> <Entry key="OperationStatus_VerifyApplicationIntegrity">
Verifying integrity Verifying integrity
</Entry> </Entry>
<Entry key="OperationStatus_VerifySessionIntegrity">
Verifying session integrity
</Entry>
<Entry key="OperationStatus_WaitDisclaimerConfirmation"> <Entry key="OperationStatus_WaitDisclaimerConfirmation">
Waiting for confirmation of the disclaimer Waiting for confirmation of the disclaimer
</Entry> </Entry>

View file

@ -148,17 +148,26 @@
Les applications sur liste noire énumérées ci-dessous ont été lancées et nont pas pu être automatiquement supprimées! Afin de débloquer SEB, veuillez sélectionner l'une des options disponibles et entrer le mot de passe de déblocage. Les applications sur liste noire énumérées ci-dessous ont été lancées et nont pas pu être automatiquement supprimées! Afin de débloquer SEB, veuillez sélectionner l'une des options disponibles et entrer le mot de passe de déblocage.
</Entry> </Entry>
<Entry key="LockScreen_ApplicationsTerminateOption"> <Entry key="LockScreen_ApplicationsTerminateOption">
Terminer Safe Exam Browser. AVERTISSEMENT: Il n'y aura pas de possibilité de sauvegarder les données ou d'effectuer d'autres actions, l'arrêt sera déclenché immédiatement! Terminer Safe Exam Browser. AVERTISSEMENT: Il n'y aura aucune possibilité de sauvegarder les données ou d'effectuer d'autres actions, la fermeture sera initiée immédiatement!
</Entry> </Entry>
<Entry key="LockScreen_DisplayConfigurationContinueOption"> <Entry key="LockScreen_DisplayConfigurationContinueOption">
Autoriser temporairement la configuration de l'affichage. Ceci s'applique uniquement à la session en cours! Autoriser temporairement la configuration de l'affichage. Ceci s'applique uniquement à la session en cours!
</Entry> </Entry>
<Entry key="LockScreen_DisplayConfigurationTerminateOption">
Terminez le navigateur Safe Exam. AVERTISSEMENT: Il n'y aura aucune possibilité de sauvegarder des données ou d'effectuer d'autres actions, l'arrêt sera déclenché immédiatement!
</Entry>
<Entry key="LockScreen_DisplayConfigurationMessage"> <Entry key="LockScreen_DisplayConfigurationMessage">
Une configuration d'affichage interdite a été détectée. Pour déverrouiller SEB, veuillez sélectionner l'une des options disponibles et saisir le mot de passe de déverrouillage correct. Une configuration d'affichage interdite a été détectée. Pour déverrouiller SEB, veuillez sélectionner l'une des options disponibles et saisir le mot de passe de déverrouillage correct.
</Entry> </Entry>
<Entry key="LockScreen_DisplayConfigurationTerminateOption">
Terminer Safe Exam Browser. AVERTISSEMENT: Il n'y aura aucune possibilité de sauvegarder les données ou d'effectuer d'autres actions, la fermeture sera initiée immédiatement!
</Entry>
<Entry key="LockScreen_EaseOfAccessContinueOption">
Autoriser temporairement la configuration de la facilité d'accès. Ceci s'applique uniquement à la session en cours!
</Entry>
<Entry key="LockScreen_EaseOfAccessMessage">
Une configuration de facilité d'accès interdite pour l'écran de sécurité de Windows a été détectée. Afin de déverrouiller le SEB, veuillez sélectionner l'une des options disponibles et saisir le mot de passe de déverrouillage correct.
</Entry>
<Entry key="LockScreen_EaseOfAccessTerminateOption">
Terminer Safe Exam Browser. AVERTISSEMENT: Il n'y aura aucune possibilité de sauvegarder les données ou d'effectuer d'autres actions, la fermeture sera initiée immédiatement!
</Entry>
<Entry key="LockScreen_SessionIntegrityMessage"> <Entry key="LockScreen_SessionIntegrityMessage">
La dernière session avec la configuration ou l'URL de démarrage actuellement active n'a pas été terminée correctement! Afin de déverrouiller SEB, veuillez entrer le mot de passe de déverrouillage correct. La dernière session avec la configuration ou l'URL de démarrage actuellement active n'a pas été terminée correctement! Afin de déverrouiller SEB, veuillez entrer le mot de passe de déverrouillage correct.
</Entry> </Entry>
@ -175,7 +184,7 @@
L'utilisateur actif a changé ou l'ordinateur a été verrouillé! Afin de déverrouiller SEB, veuillez sélectionner une des options disponibles et entrer le mot de passe de déverrouillage. L'utilisateur actif a changé ou l'ordinateur a été verrouillé! Afin de déverrouiller SEB, veuillez sélectionner une des options disponibles et entrer le mot de passe de déverrouillage.
</Entry> </Entry>
<Entry key="LockScreen_UserSessionTerminateOption"> <Entry key="LockScreen_UserSessionTerminateOption">
Terminer Safe Exam Browser. AVERTISSEMENT: Il n'y aura pas de possibilité de sauvegarder les données ou d'effectuer d'autres actions, l'arrêt sera déclenché immédiatement! Terminer Safe Exam Browser. AVERTISSEMENT: Il n'y aura aucune possibilité de sauvegarder les données ou d'effectuer d'autres actions, la fermeture sera initiée immédiatement!
</Entry> </Entry>
<Entry key="LogWindow_AlwaysOnTop"> <Entry key="LogWindow_AlwaysOnTop">
Toujours au premier plan Toujours au premier plan
@ -549,6 +558,9 @@
<Entry key="OperationStatus_VerifyApplicationIntegrity"> <Entry key="OperationStatus_VerifyApplicationIntegrity">
Vérification de l'intégrité Vérification de l'intégrité
</Entry> </Entry>
<Entry key="OperationStatus_VerifySessionIntegrity">
Vérification de l'intégrité de la session
</Entry>
<Entry key="OperationStatus_WaitDisclaimerConfirmation"> <Entry key="OperationStatus_WaitDisclaimerConfirmation">
En attente de confirmation de la clause de non-responsabilité En attente de confirmation de la clause de non-responsabilité
</Entry> </Entry>

View file

@ -148,17 +148,26 @@
Le applicazioni nella lista nera elencate di seguito sono state avviate e non è stato possibile terminare automaticamente! Per sbloccare SEB, seleziona una delle opzioni disponibili e inserisci la password di sblocco corretta. Le applicazioni nella lista nera elencate di seguito sono state avviate e non è stato possibile terminare automaticamente! Per sbloccare SEB, seleziona una delle opzioni disponibili e inserisci la password di sblocco corretta.
</Entry> </Entry>
<Entry key="LockScreen_ApplicationsTerminateOption"> <Entry key="LockScreen_ApplicationsTerminateOption">
Chiudi Safe Exam Browser. ATTENZIONE: non ci sarà la possibilità di salvare dati o eseguire ulteriori azioni, lo spegnimento verrà avviato immediatamente! Terminare Safe Exam Browser. ATTENZIONE: Non sarà possibile salvare i dati o eseguire ulteriori azioni, la chiusura verrà avviata immediatamente!
</Entry> </Entry>
<Entry key="LockScreen_DisplayConfigurationContinueOption"> <Entry key="LockScreen_DisplayConfigurationContinueOption">
Consenti temporaneamente la configurazione del display. Questo vale solo per la sessione attualmente in esecuzione! Consenti temporaneamente la configurazione del display. Questo vale solo per la sessione attualmente in esecuzione!
</Entry> </Entry>
<Entry key="LockScreen_DisplayConfigurationTerminateOption">
Termina Browser esame sicuro. ATTENZIONE: non sarà possibile salvare i dati o eseguire ulteriori azioni, lo spegnimento verrà avviato immediatamente!
</Entry>
<Entry key="LockScreen_DisplayConfigurationMessage"> <Entry key="LockScreen_DisplayConfigurationMessage">
È stata rilevata una configurazione di visualizzazione vietata. Per sbloccare SEB, seleziona una delle opzioni disponibili e inserisci la password di sblocco corretta. È stata rilevata una configurazione di visualizzazione vietata. Per sbloccare SEB, seleziona una delle opzioni disponibili e inserisci la password di sblocco corretta.
</Entry> </Entry>
<Entry key="LockScreen_DisplayConfigurationTerminateOption">
Terminare Safe Exam Browser. ATTENZIONE: Non sarà possibile salvare i dati o eseguire ulteriori azioni, la chiusura verrà avviata immediatamente!
</Entry>
<Entry key="LockScreen_EaseOfAccessContinueOption">
Consente temporaneamente la configurazione della facilità di accesso. Questo vale solo per la sessione in corso!
</Entry>
<Entry key="LockScreen_EaseOfAccessMessage">
È stata rilevata una configurazione di facilità di accesso non consentita per la schermata di sicurezza di Windows. Per sbloccare SEB, seleziona una delle opzioni disponibili e inserisci la password di sblocco corretta.
</Entry>
<Entry key="LockScreen_EaseOfAccessTerminateOption">
Terminare Safe Exam Browser. ATTENZIONE: Non sarà possibile salvare i dati o eseguire ulteriori azioni, la chiusura verrà avviata immediatamente!
</Entry>
<Entry key="LockScreen_SessionIntegrityMessage"> <Entry key="LockScreen_SessionIntegrityMessage">
L'ultima sessione con la configurazione o l'URL di avvio attualmente attiva non è stata terminata correttamente! Per sbloccare SEB, inserisci la password di sblocco corretta. L'ultima sessione con la configurazione o l'URL di avvio attualmente attiva non è stata terminata correttamente! Per sbloccare SEB, inserisci la password di sblocco corretta.
</Entry> </Entry>
@ -175,7 +184,7 @@
L'utente attivo è cambiato o il computer è stato bloccato! Per sbloccare SEB, seleziona una delle opzioni disponibili e inserisci la password di sblocco corretta. L'utente attivo è cambiato o il computer è stato bloccato! Per sbloccare SEB, seleziona una delle opzioni disponibili e inserisci la password di sblocco corretta.
</Entry> </Entry>
<Entry key="LockScreen_UserSessionTerminateOption"> <Entry key="LockScreen_UserSessionTerminateOption">
Chiudi Safe Exam Browser. ATTENZIONE: non ci sarà la possibilità di salvare dati o eseguire ulteriori azioni, lo spegnimento verrà avviato immediatamente! Terminare Safe Exam Browser. ATTENZIONE: Non sarà possibile salvare i dati o eseguire ulteriori azioni, la chiusura verrà avviata immediatamente!
</Entry> </Entry>
<Entry key="LogWindow_AlwaysOnTop"> <Entry key="LogWindow_AlwaysOnTop">
Sempre in cima Sempre in cima
@ -549,6 +558,9 @@
<Entry key="OperationStatus_VerifyApplicationIntegrity"> <Entry key="OperationStatus_VerifyApplicationIntegrity">
Verifica dell'integrità Verifica dell'integrità
</Entry> </Entry>
<Entry key="OperationStatus_VerifySessionIntegrity">
Verifica dell'integrità della sessione
</Entry>
<Entry key="OperationStatus_WaitDisclaimerConfirmation"> <Entry key="OperationStatus_WaitDisclaimerConfirmation">
In attesa di conferma del disclaimer In attesa di conferma del disclaimer
</Entry> </Entry>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Text> <Text>
<Entry key="AboutWindow_LicenseInfo"> <Entry key="AboutWindow_LicenseInfo">
此应用程序受Mozilla Public License, 版本 2.0 的条款约束。汉化人272881521@qq.com。防作弊考试专用浏览器使用以下框架和第三方知识库: 此应用程序受Mozilla Public License, 版本 2.0 的条款约束。防作弊考试专用浏览器使用以下框架和第三方知识库:
</Entry> </Entry>
<Entry key="AboutWindow_Title"> <Entry key="AboutWindow_Title">
版本 &amp; 许可证信息 版本 &amp; 许可证信息
@ -138,11 +138,20 @@
<Entry key="LockScreen_DisplayConfigurationContinueOption"> <Entry key="LockScreen_DisplayConfigurationContinueOption">
暂时允许显示配置。 这仅适用于当前正在运行的会话! 暂时允许显示配置。 这仅适用于当前正在运行的会话!
</Entry> </Entry>
<Entry key="LockScreen_DisplayConfigurationMessage">
检测到禁止的显示配置。 要解锁 SEB请选择可用选项之一并输入正确的解锁密码。
</Entry>
<Entry key="LockScreen_DisplayConfigurationTerminateOption"> <Entry key="LockScreen_DisplayConfigurationTerminateOption">
终止安全考试浏览器。 警告:将无法保存数据或执行任何进一步操作,将立即启动关机! 终止安全考试浏览器。 警告:将无法保存数据或执行任何进一步操作,将立即启动关机!
</Entry> </Entry>
<Entry key="LockScreen_DisplayConfigurationMessage"> <Entry key="LockScreen_EaseOfAccessContinueOption">
检测到禁止的显示配置。 要解锁 SEB请选择可用选项之一并输入正确的解锁密码。 暂时允许轻松访问的配置。这只适用于当前运行的会话!
</Entry>
<Entry key="LockScreen_EaseOfAccessMessage">
检测到一个被禁止的Windows安全屏幕的访问方便配置。为了解锁SEB请选择一个可用的选项并输入正确的解锁密码。
</Entry>
<Entry key="LockScreen_EaseOfAccessTerminateOption">
终止安全考试浏览器。警告:将没有可能保存数据或执行任何进一步的行动,关闭将立即启动!
</Entry> </Entry>
<Entry key="LockScreen_SessionIntegrityMessage"> <Entry key="LockScreen_SessionIntegrityMessage">
当前激活的配置或启动URL的最后一个会话没有被正确终止! 请输入正确的密码以解锁SEB。 当前激活的配置或启动URL的最后一个会话没有被正确终止! 请输入正确的密码以解锁SEB。
@ -504,6 +513,9 @@
<Entry key="OperationStatus_VerifyApplicationIntegrity"> <Entry key="OperationStatus_VerifyApplicationIntegrity">
验证完整性 验证完整性
</Entry> </Entry>
<Entry key="OperationStatus_VerifySessionIntegrity">
验证会话的完整性
</Entry>
<Entry key="OperationStatus_WaitDisclaimerConfirmation"> <Entry key="OperationStatus_WaitDisclaimerConfirmation">
等待确认免责声明 等待确认免责声明
</Entry> </Entry>

View file

@ -32,6 +32,7 @@ using SafeExamBrowser.Server;
using SafeExamBrowser.Settings.Logging; using SafeExamBrowser.Settings.Logging;
using SafeExamBrowser.SystemComponents; using SafeExamBrowser.SystemComponents;
using SafeExamBrowser.SystemComponents.Contracts; using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.SystemComponents.Registry;
using SafeExamBrowser.UserInterface.Desktop; using SafeExamBrowser.UserInterface.Desktop;
using SafeExamBrowser.WindowsApi; using SafeExamBrowser.WindowsApi;
@ -73,6 +74,7 @@ namespace SafeExamBrowser.Runtime
var messageBox = new MessageBoxFactory(text); var messageBox = new MessageBoxFactory(text);
var processFactory = new ProcessFactory(ModuleLogger(nameof(ProcessFactory))); var processFactory = new ProcessFactory(ModuleLogger(nameof(ProcessFactory)));
var proxyFactory = new ProxyFactory(new ProxyObjectFactory(), ModuleLogger(nameof(ProxyFactory))); var proxyFactory = new ProxyFactory(new ProxyObjectFactory(), ModuleLogger(nameof(ProxyFactory)));
var registry = new Registry(ModuleLogger(nameof(Registry)));
var remoteSessionDetector = new RemoteSessionDetector(ModuleLogger(nameof(RemoteSessionDetector))); var remoteSessionDetector = new RemoteSessionDetector(ModuleLogger(nameof(RemoteSessionDetector)));
var runtimeHost = new RuntimeHost(appConfig.RuntimeAddress, new HostObjectFactory(), ModuleLogger(nameof(RuntimeHost)), FIVE_SECONDS); var runtimeHost = new RuntimeHost(appConfig.RuntimeAddress, new HostObjectFactory(), ModuleLogger(nameof(RuntimeHost)), FIVE_SECONDS);
var runtimeWindow = uiFactory.CreateRuntimeWindow(appConfig); var runtimeWindow = uiFactory.CreateRuntimeWindow(appConfig);
@ -87,13 +89,14 @@ namespace SafeExamBrowser.Runtime
bootstrapOperations.Enqueue(new I18nOperation(logger, text)); bootstrapOperations.Enqueue(new I18nOperation(logger, text));
bootstrapOperations.Enqueue(new CommunicationHostOperation(runtimeHost, logger)); bootstrapOperations.Enqueue(new CommunicationHostOperation(runtimeHost, logger));
bootstrapOperations.Enqueue(new IntegrityOperation(integrityModule, logger)); bootstrapOperations.Enqueue(new ApplicationIntegrityOperation(integrityModule, logger));
sessionOperations.Enqueue(new SessionInitializationOperation(configuration, fileSystem, logger, runtimeHost, sessionContext)); sessionOperations.Enqueue(new SessionInitializationOperation(configuration, fileSystem, logger, runtimeHost, sessionContext));
sessionOperations.Enqueue(new ConfigurationOperation(args, configuration, new FileSystem(), new HashAlgorithm(), logger, sessionContext)); sessionOperations.Enqueue(new ConfigurationOperation(args, configuration, new FileSystem(), new HashAlgorithm(), logger, sessionContext));
sessionOperations.Enqueue(new ServerOperation(args, configuration, fileSystem, logger, sessionContext, server)); sessionOperations.Enqueue(new ServerOperation(args, configuration, fileSystem, logger, sessionContext, server));
sessionOperations.Enqueue(new DisclaimerOperation(logger, sessionContext)); sessionOperations.Enqueue(new DisclaimerOperation(logger, sessionContext));
sessionOperations.Enqueue(new RemoteSessionOperation(remoteSessionDetector, logger, sessionContext)); sessionOperations.Enqueue(new RemoteSessionOperation(remoteSessionDetector, logger, sessionContext));
sessionOperations.Enqueue(new SessionIntegrityOperation(logger, registry, sessionContext));
sessionOperations.Enqueue(new VirtualMachineOperation(vmDetector, logger, sessionContext)); sessionOperations.Enqueue(new VirtualMachineOperation(vmDetector, logger, sessionContext));
sessionOperations.Enqueue(new DisplayMonitorOperation(displayMonitor, logger, sessionContext, text)); sessionOperations.Enqueue(new DisplayMonitorOperation(displayMonitor, logger, sessionContext, text));
sessionOperations.Enqueue(new ServiceOperation(logger, runtimeHost, serviceProxy, sessionContext, THIRTY_SECONDS, userInfo)); sessionOperations.Enqueue(new ServiceOperation(logger, runtimeHost, serviceProxy, sessionContext, THIRTY_SECONDS, userInfo));

View file

@ -14,7 +14,7 @@ using SafeExamBrowser.Logging.Contracts;
namespace SafeExamBrowser.Runtime.Operations namespace SafeExamBrowser.Runtime.Operations
{ {
internal class IntegrityOperation : IOperation internal class ApplicationIntegrityOperation : IOperation
{ {
private readonly IIntegrityModule module; private readonly IIntegrityModule module;
private readonly ILogger logger; private readonly ILogger logger;
@ -22,7 +22,7 @@ namespace SafeExamBrowser.Runtime.Operations
public event ActionRequiredEventHandler ActionRequired { add { } remove { } } public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
public event StatusChangedEventHandler StatusChanged; public event StatusChangedEventHandler StatusChanged;
public IntegrityOperation(IIntegrityModule module, ILogger logger) public ApplicationIntegrityOperation(IIntegrityModule module, ILogger logger)
{ {
this.module = module; this.module = module;
this.logger = logger; this.logger = logger;

View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 2022 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.Core.Contracts.OperationModel;
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Registry;
namespace SafeExamBrowser.Runtime.Operations
{
internal class SessionIntegrityOperation : SessionOperation
{
private readonly ILogger logger;
private readonly IRegistry registry;
public override event ActionRequiredEventHandler ActionRequired { add { } remove { } }
public override event StatusChangedEventHandler StatusChanged;
public SessionIntegrityOperation(ILogger logger, IRegistry registry, SessionContext context) : base(context)
{
this.logger = logger;
this.registry = registry;
}
public override OperationResult Perform()
{
StatusChanged?.Invoke(TextKey.OperationStatus_VerifySessionIntegrity);
return VerifyEaseOfAccessConfiguration();
}
public override OperationResult Repeat()
{
StatusChanged?.Invoke(TextKey.OperationStatus_VerifySessionIntegrity);
return VerifyEaseOfAccessConfiguration();
}
public override OperationResult Revert()
{
return OperationResult.Success;
}
private OperationResult VerifyEaseOfAccessConfiguration()
{
var result = OperationResult.Failed;
logger.Info($"Attempting to verify ease of access configuration...");
if (registry.TryRead(RegistryKey.MachineHive.EaseOfAccess_Key, RegistryKey.MachineHive.EaseOfAccess_Name, out var value))
{
if (value == default || (value is string s && string.IsNullOrWhiteSpace(s)))
{
result = OperationResult.Success;
logger.Info("Ease of access configuration successfully verified.");
}
else if (!Context.Next.Settings.Service.IgnoreService)
{
result = OperationResult.Success;
logger.Info($"Ease of access configuration is compromised ('{value}'), but service will be active in the next session.");
}
else
{
logger.Warn($"Ease of access configuration is compromised: '{value}'! Aborting session initialization...");
}
}
else
{
logger.Error("Failed to verify ease of access configuration!");
}
return result;
}
}
}

View file

@ -106,13 +106,14 @@
<Compile Include="Operations\Events\PasswordRequiredEventArgs.cs" /> <Compile Include="Operations\Events\PasswordRequiredEventArgs.cs" />
<Compile Include="Operations\Events\ServerFailureEventArgs.cs" /> <Compile Include="Operations\Events\ServerFailureEventArgs.cs" />
<Compile Include="Operations\Events\UnexpectedErrorMessageArgs.cs" /> <Compile Include="Operations\Events\UnexpectedErrorMessageArgs.cs" />
<Compile Include="Operations\IntegrityOperation.cs" /> <Compile Include="Operations\ApplicationIntegrityOperation.cs" />
<Compile Include="Operations\KioskModeOperation.cs" /> <Compile Include="Operations\KioskModeOperation.cs" />
<Compile Include="Operations\ProctoringWorkaroundOperation.cs" /> <Compile Include="Operations\ProctoringWorkaroundOperation.cs" />
<Compile Include="Operations\RemoteSessionOperation.cs" /> <Compile Include="Operations\RemoteSessionOperation.cs" />
<Compile Include="Operations\ServerOperation.cs" /> <Compile Include="Operations\ServerOperation.cs" />
<Compile Include="Operations\ServiceOperation.cs" /> <Compile Include="Operations\ServiceOperation.cs" />
<Compile Include="Operations\SessionActivationOperation.cs" /> <Compile Include="Operations\SessionActivationOperation.cs" />
<Compile Include="Operations\SessionIntegrityOperation.cs" />
<Compile Include="Operations\SessionOperation.cs" /> <Compile Include="Operations\SessionOperation.cs" />
<Compile Include="Operations\SessionInitializationOperation.cs" /> <Compile Include="Operations\SessionInitializationOperation.cs" />
<Compile Include="Communication\RuntimeHost.cs" /> <Compile Include="Communication\RuntimeHost.cs" />

View file

@ -0,0 +1,15 @@
/*
* Copyright (c) 2022 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.SystemComponents.Contracts.Registry.Events
{
/// <summary>
/// Indicates that a registry value has changed.
/// </summary>
public delegate void RegistryValueChangedEventHandler(object oldValue, object newValue);
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2022 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.SystemComponents.Contracts.Registry.Events;
namespace SafeExamBrowser.SystemComponents.Contracts.Registry
{
/// <summary>
/// Provides functionality related to the Windows registry.
/// </summary>
public interface IRegistry
{
/// <summary>
/// Fired when a registry value previously registred via <see cref="StartMonitoring(string, string)"/> has changed.
/// </summary>
event RegistryValueChangedEventHandler ValueChanged;
/// <summary>
/// Starts monitoring the specified registry value.
/// </summary>
void StartMonitoring(string key, string name);
/// <summary>
/// Stops the monitoring of all previously registered registry values.
/// </summary>
void StopMonitoring();
/// <summary>
/// Attempts to read the value of the given name under the specified registry key.
/// </summary>
bool TryRead(string key, string name, out object value);
}
}

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2022 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.SystemComponents.Contracts.Registry
{
/// <summary>
/// Defines registry keys and names used in conjunction with <see cref="IRegistry"/>. Use the pattern "LogicalGroup_Key" resp. "LogicalGroup_Name"
/// to allow for a better overview over all keys, names and their usage (where applicable).
/// </summary>
public static class RegistryKey
{
/// <summary>
/// All registry keys and names located in the machine hive.
/// </summary>
public static class MachineHive
{
public const string EaseOfAccess_Key = @"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\Utilman.exe";
public const string EaseOfAccess_Name = "Debugger";
}
}
}

View file

@ -57,6 +57,8 @@
<Compile Include="Audio\Events\VolumeChangedEventHandler.cs" /> <Compile Include="Audio\Events\VolumeChangedEventHandler.cs" />
<Compile Include="Audio\IAudio.cs" /> <Compile Include="Audio\IAudio.cs" />
<Compile Include="IFileSystem.cs" /> <Compile Include="IFileSystem.cs" />
<Compile Include="Registry\Events\RegistryValueChangedEventHandler.cs" />
<Compile Include="Registry\IRegistry.cs" />
<Compile Include="IRemoteSessionDetector.cs" /> <Compile Include="IRemoteSessionDetector.cs" />
<Compile Include="IVirtualMachineDetector.cs" /> <Compile Include="IVirtualMachineDetector.cs" />
<Compile Include="Network\ConnectionType.cs" /> <Compile Include="Network\ConnectionType.cs" />
@ -76,6 +78,7 @@
<Compile Include="PowerSupply\IPowerSupplyStatus.cs" /> <Compile Include="PowerSupply\IPowerSupplyStatus.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Network\ConnectionStatus.cs" /> <Compile Include="Network\ConnectionStatus.cs" />
<Compile Include="Registry\RegistryKey.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 2022 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 System;
using System.Collections.Concurrent;
using System.Timers;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Registry;
using SafeExamBrowser.SystemComponents.Contracts.Registry.Events;
namespace SafeExamBrowser.SystemComponents.Registry
{
public class Registry : IRegistry
{
private readonly ILogger logger;
private readonly ConcurrentBag<(string key, string name, object value)> values;
private Timer timer;
public event RegistryValueChangedEventHandler ValueChanged;
public Registry(ILogger logger)
{
this.logger = logger;
this.values = new ConcurrentBag<(string key, string name, object value)>();
}
public void StartMonitoring(string key, string name)
{
const int ONE_SECOND = 1000;
if (timer?.Enabled != true)
{
timer = new Timer(ONE_SECOND);
timer.AutoReset = true;
timer.Elapsed += Timer_Elapsed;
timer.Start();
}
if (TryRead(key, name, out var value))
{
values.Add((key, name, value));
logger.Debug($"Started monitoring value '{name}' from registry key '{key}'. Initial value: '{value}'.");
}
else
{
logger.Error($"Failed to start monitoring value '{name}' from registry key '{key}'!");
}
}
public void StopMonitoring()
{
while (!values.IsEmpty)
{
values.TryTake(out _);
}
if (timer != null)
{
timer.Stop();
logger.Debug("Stopped monitoring the registry.");
}
}
public bool TryRead(string key, string name, out object value)
{
var success = true;
value = default;
try
{
value = Microsoft.Win32.Registry.GetValue(key, name, default);
}
catch (Exception e)
{
success = false;
logger.Error($"Failed to read value '{name}' from registry key '{key}'!", e);
}
return success;
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
foreach (var item in values)
{
if (TryRead(item.key, item.name, out var value))
{
if (item.value != value)
{
logger.Debug($"Value '{item.name}' from registry key '{item.key}' has changed from '{item.value}' to '{value}'!");
ValueChanged?.Invoke(item.value, value);
}
}
else
{
logger.Error($"Failed to monitor value '{item.name}' from registry key '{item.key}'!");
}
}
}
}
}

View file

@ -97,6 +97,7 @@
<Compile Include="PowerSupply\PowerSupply.cs" /> <Compile Include="PowerSupply\PowerSupply.cs" />
<Compile Include="PowerSupply\PowerSupplyStatus.cs" /> <Compile Include="PowerSupply\PowerSupplyStatus.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Registry\Registry.cs" />
<Compile Include="RemoteSessionDetector.cs" /> <Compile Include="RemoteSessionDetector.cs" />
<Compile Include="SystemInfo.cs" /> <Compile Include="SystemInfo.cs" />
<Compile Include="UserInfo.cs" /> <Compile Include="UserInfo.cs" />