SEBWIN-301: Implemented service log file persistence in user directory.
This commit is contained in:
		
							parent
							
								
									6b24554abc
								
							
						
					
					
						commit
						3589b92b9d
					
				
					 8 changed files with 61 additions and 22 deletions
				
			
		|  | @ -68,6 +68,8 @@ namespace SafeExamBrowser.Configuration.ConfigurationData | ||||||
| 			appConfig.SebUriScheme = "seb"; | 			appConfig.SebUriScheme = "seb"; | ||||||
| 			appConfig.SebUriSchemeSecure = "sebs"; | 			appConfig.SebUriSchemeSecure = "sebs"; | ||||||
| 			appConfig.ServiceAddress = $"{BASE_ADDRESS}/service"; | 			appConfig.ServiceAddress = $"{BASE_ADDRESS}/service"; | ||||||
|  | 			appConfig.ServiceEventName = $@"Global\{nameof(SafeExamBrowser)}-{Guid.NewGuid()}"; | ||||||
|  | 			appConfig.ServiceLogFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Service.log"); | ||||||
| 
 | 
 | ||||||
| 			return appConfig; | 			return appConfig; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -121,6 +121,11 @@ namespace SafeExamBrowser.Contracts.Configuration | ||||||
| 		/// </summary> | 		/// </summary> | ||||||
| 		public string ServiceEventName { get; set; } | 		public string ServiceEventName { get; set; } | ||||||
| 
 | 
 | ||||||
|  | 		/// <summary> | ||||||
|  | 		/// The file path under which the log for the current session of the service component is to be stored. | ||||||
|  | 		/// </summary> | ||||||
|  | 		public string ServiceLogFilePath { get; set; } | ||||||
|  | 
 | ||||||
| 		/// <summary> | 		/// <summary> | ||||||
| 		/// Creates a shallow clone. | 		/// Creates a shallow clone. | ||||||
| 		/// </summary> | 		/// </summary> | ||||||
|  |  | ||||||
|  | @ -29,11 +29,11 @@ namespace SafeExamBrowser.Logging | ||||||
| 
 | 
 | ||||||
| 		public void Initialize() | 		public void Initialize() | ||||||
| 		{ | 		{ | ||||||
| 			var logFolder = Path.GetDirectoryName(filePath); | 			var directory = Path.GetDirectoryName(filePath); | ||||||
| 
 | 
 | ||||||
| 			if (!Directory.Exists(logFolder)) | 			if (!Directory.Exists(directory)) | ||||||
| 			{ | 			{ | ||||||
| 				Directory.CreateDirectory(logFolder); | 				Directory.CreateDirectory(directory); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -46,7 +46,7 @@ namespace SafeExamBrowser.Service | ||||||
| 			bootstrapOperations.Enqueue(new CommunicationHostOperation(serviceHost, logger)); | 			bootstrapOperations.Enqueue(new CommunicationHostOperation(serviceHost, logger)); | ||||||
| 			bootstrapOperations.Enqueue(new ServiceEventCleanupOperation(logger, sessionContext)); | 			bootstrapOperations.Enqueue(new ServiceEventCleanupOperation(logger, sessionContext)); | ||||||
| 
 | 
 | ||||||
| 			sessionOperations.Enqueue(new SessionInitializationOperation(logger, serviceHost, sessionContext)); | 			sessionOperations.Enqueue(new SessionInitializationOperation(logger, CreateLogWriter, serviceHost, sessionContext)); | ||||||
| 			// TODO: sessionOperations.Enqueue(new RegistryOperation()); | 			// TODO: sessionOperations.Enqueue(new RegistryOperation()); | ||||||
| 			//       sessionOperations.Enqueue(new WindowsUpdateOperation()); | 			//       sessionOperations.Enqueue(new WindowsUpdateOperation()); | ||||||
| 			sessionOperations.Enqueue(new SessionActivationOperation(logger, sessionContext)); | 			sessionOperations.Enqueue(new SessionActivationOperation(logger, sessionContext)); | ||||||
|  | @ -81,5 +81,14 @@ namespace SafeExamBrowser.Service | ||||||
| 			logger.Subscribe(logFileWriter); | 			logger.Subscribe(logFileWriter); | ||||||
| 			logFileWriter.Initialize(); | 			logFileWriter.Initialize(); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		private ILogObserver CreateLogWriter(string filePath) | ||||||
|  | 		{ | ||||||
|  | 			var writer = new LogFileWriter(new DefaultLogFormatter(), filePath); | ||||||
|  | 
 | ||||||
|  | 			writer.Initialize(); | ||||||
|  | 
 | ||||||
|  | 			return writer; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -33,10 +33,10 @@ namespace SafeExamBrowser.Service.Operations | ||||||
| 
 | 
 | ||||||
| 		public OperationResult Revert() | 		public OperationResult Revert() | ||||||
| 		{ | 		{ | ||||||
| 			if (sessionContext.EventWaitHandle != null) | 			if (sessionContext.ServiceEvent != null) | ||||||
| 			{ | 			{ | ||||||
| 				logger.Info("Closing service event..."); | 				logger.Info("Closing service event..."); | ||||||
| 				sessionContext.EventWaitHandle.Close(); | 				sessionContext.ServiceEvent.Close(); | ||||||
| 				logger.Info("Service event successfully closed."); | 				logger.Info("Service event successfully closed."); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ namespace SafeExamBrowser.Service.Operations | ||||||
| 
 | 
 | ||||||
| 		public override OperationResult Perform() | 		public override OperationResult Perform() | ||||||
| 		{ | 		{ | ||||||
| 			var success = Context.EventWaitHandle.Set(); | 			var success = Context.ServiceEvent.Set(); | ||||||
| 
 | 
 | ||||||
| 			if (success) | 			if (success) | ||||||
| 			{ | 			{ | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. |  * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | using System; | ||||||
| using System.Security.AccessControl; | using System.Security.AccessControl; | ||||||
| using System.Security.Principal; | using System.Security.Principal; | ||||||
| using System.Threading; | using System.Threading; | ||||||
|  | @ -18,16 +19,25 @@ namespace SafeExamBrowser.Service.Operations | ||||||
| 	internal class SessionInitializationOperation : SessionOperation | 	internal class SessionInitializationOperation : SessionOperation | ||||||
| 	{ | 	{ | ||||||
| 		private ILogger logger; | 		private ILogger logger; | ||||||
|  | 		private Func<string, ILogObserver> createLogWriter; | ||||||
| 		private IServiceHost serviceHost; | 		private IServiceHost serviceHost; | ||||||
|  | 		private ILogObserver sessionWriter; | ||||||
| 
 | 
 | ||||||
| 		public SessionInitializationOperation(ILogger logger, IServiceHost serviceHost, SessionContext sessionContext) : base(sessionContext) | 		public SessionInitializationOperation( | ||||||
|  | 			ILogger logger, | ||||||
|  | 			Func<string, ILogObserver> createLogWriter, | ||||||
|  | 			IServiceHost serviceHost, | ||||||
|  | 			SessionContext sessionContext) : base(sessionContext) | ||||||
| 		{ | 		{ | ||||||
| 			this.logger = logger; | 			this.logger = logger; | ||||||
|  | 			this.createLogWriter = createLogWriter; | ||||||
| 			this.serviceHost = serviceHost; | 			this.serviceHost = serviceHost; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public override OperationResult Perform() | 		public override OperationResult Perform() | ||||||
| 		{ | 		{ | ||||||
|  | 			InitializeSessionWriter(); | ||||||
|  | 
 | ||||||
| 			logger.Info("Initializing new session..."); | 			logger.Info("Initializing new session..."); | ||||||
| 
 | 
 | ||||||
| 			serviceHost.AllowConnection = false; | 			serviceHost.AllowConnection = false; | ||||||
|  | @ -35,16 +45,20 @@ namespace SafeExamBrowser.Service.Operations | ||||||
| 			logger.Info($" -> Runtime-ID: {Context.Configuration.AppConfig.RuntimeId}"); | 			logger.Info($" -> Runtime-ID: {Context.Configuration.AppConfig.RuntimeId}"); | ||||||
| 			logger.Info($" -> Session-ID: {Context.Configuration.SessionId}"); | 			logger.Info($" -> Session-ID: {Context.Configuration.SessionId}"); | ||||||
| 
 | 
 | ||||||
| 			InitializeEventWaitHandle(); | 			InitializeServiceEvent(); | ||||||
| 
 | 
 | ||||||
| 			return OperationResult.Success; | 			return OperationResult.Success; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public override OperationResult Revert() | 		public override OperationResult Revert() | ||||||
| 		{ | 		{ | ||||||
|  | 			var success = true; | ||||||
|  | 
 | ||||||
| 			logger.Info("Finalizing current session..."); | 			logger.Info("Finalizing current session..."); | ||||||
| 
 | 
 | ||||||
| 			var success = Context.EventWaitHandle?.Set() == true; | 			if (Context.ServiceEvent != null) | ||||||
|  | 			{ | ||||||
|  | 				success = Context.ServiceEvent.Set(); | ||||||
| 
 | 
 | ||||||
| 				if (success) | 				if (success) | ||||||
| 				{ | 				{ | ||||||
|  | @ -54,14 +68,17 @@ namespace SafeExamBrowser.Service.Operations | ||||||
| 				{ | 				{ | ||||||
| 					logger.Error("Failed to inform runtime about session termination!"); | 					logger.Error("Failed to inform runtime about session termination!"); | ||||||
| 				} | 				} | ||||||
|  | 			} | ||||||
| 
 | 
 | ||||||
| 			Context.Configuration = null; | 			Context.Configuration = null; | ||||||
|  | 			logger.Unsubscribe(sessionWriter); | ||||||
|  | 			sessionWriter = null; | ||||||
| 			serviceHost.AllowConnection = true; | 			serviceHost.AllowConnection = true; | ||||||
| 
 | 
 | ||||||
| 			return success ? OperationResult.Success : OperationResult.Failed; | 			return success ? OperationResult.Success : OperationResult.Failed; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		private void InitializeEventWaitHandle() | 		private void InitializeServiceEvent() | ||||||
| 		{ | 		{ | ||||||
| 			var securityIdentifier = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null); | 			var securityIdentifier = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null); | ||||||
| 			var accessRule = new EventWaitHandleAccessRule(securityIdentifier, EventWaitHandleRights.Synchronize, AccessControlType.Allow); | 			var accessRule = new EventWaitHandleAccessRule(securityIdentifier, EventWaitHandleRights.Synchronize, AccessControlType.Allow); | ||||||
|  | @ -69,16 +86,22 @@ namespace SafeExamBrowser.Service.Operations | ||||||
| 
 | 
 | ||||||
| 			security.AddAccessRule(accessRule); | 			security.AddAccessRule(accessRule); | ||||||
| 
 | 
 | ||||||
| 			if (Context.EventWaitHandle != null) | 			if (Context.ServiceEvent != null) | ||||||
| 			{ | 			{ | ||||||
| 				logger.Info("Closing service event from previous session..."); | 				logger.Info("Closing service event from previous session..."); | ||||||
| 				Context.EventWaitHandle.Close(); | 				Context.ServiceEvent.Close(); | ||||||
| 				logger.Info("Service event successfully closed."); | 				logger.Info("Service event successfully closed."); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			logger.Info("Attempting to create new service event..."); | 			logger.Info("Attempting to create new service event..."); | ||||||
| 			Context.EventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Context.Configuration.AppConfig.ServiceEventName, out _, security); | 			Context.ServiceEvent = new EventWaitHandle(false, EventResetMode.AutoReset, Context.Configuration.AppConfig.ServiceEventName, out _, security); | ||||||
| 			logger.Info("Service event successfully created."); | 			logger.Info("Service event successfully created."); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		private void InitializeSessionWriter() | ||||||
|  | 		{ | ||||||
|  | 			sessionWriter = createLogWriter.Invoke(Context.Configuration.AppConfig.ServiceLogFilePath); | ||||||
|  | 			logger.Subscribe(sessionWriter); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,6 +24,6 @@ namespace SafeExamBrowser.Service | ||||||
| 		/// <summary> | 		/// <summary> | ||||||
| 		/// The global inter-process event used for status synchronization with the runtime component. | 		/// The global inter-process event used for status synchronization with the runtime component. | ||||||
| 		/// </summary> | 		/// </summary> | ||||||
| 		internal EventWaitHandle EventWaitHandle { get; set; } | 		internal EventWaitHandle ServiceEvent { get; set; } | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 dbuechel
						dbuechel