diff --git a/SafeExamBrowser.Configuration/Settings/SettingsRepository.cs b/SafeExamBrowser.Configuration/Settings/SettingsRepository.cs
index f613eccc..596a24e0 100644
--- a/SafeExamBrowser.Configuration/Settings/SettingsRepository.cs
+++ b/SafeExamBrowser.Configuration/Settings/SettingsRepository.cs
@@ -13,19 +13,22 @@ namespace SafeExamBrowser.Configuration.Settings
 {
 	public class SettingsRepository : ISettingsRepository
 	{
+		public ISettings Current { get; private set; }
+
 		public ISettings Load(Uri path)
 		{
 			// TODO
+
 			return LoadDefaults();
 		}
 
 		public ISettings LoadDefaults()
 		{
-			var settings = new Settings();
+			Current = new Settings();
 			
 			// TODO
 
-			return settings;
+			return Current;
 		}
 	}
 }
diff --git a/SafeExamBrowser.Contracts/Communication/ICommunicationHost.cs b/SafeExamBrowser.Contracts/Communication/ICommunicationHost.cs
new file mode 100644
index 00000000..386af226
--- /dev/null
+++ b/SafeExamBrowser.Contracts/Communication/ICommunicationHost.cs
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018 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.ServiceModel;
+using SafeExamBrowser.Contracts.Communication.Messages;
+using SafeExamBrowser.Contracts.Communication.Responses;
+
+namespace SafeExamBrowser.Contracts.Communication
+{
+	[ServiceContract(SessionMode = SessionMode.Required)]
+	public interface ICommunicationHost
+	{
+		/// 
+		/// Initiates a connection to the host and must thus be called before any other opertion. To authenticate itself to the host, the
+		/// client can specify a security token. If the connection request was successful, a new session will be created by the host and
+		/// the client will subsequently be allowed to start communicating with the host.
+		/// 
+		[OperationContract(IsInitiating = true)]
+		IConnectResponse Connect(Guid? token = null);
+
+		/// 
+		/// Closes the connection to the host and instructs it to terminate the communication session.
+		/// 
+		[OperationContract(IsInitiating = false, IsTerminating = true)]
+		void Disconnect(IMessage message);
+
+		/// 
+		/// Sends a message to the host, optionally returning a response. If no response is expected, null will be returned.
+		/// 
+		[OperationContract(IsInitiating = false)]
+		IResponse Send(IMessage message);
+	}
+}
diff --git a/SafeExamBrowser.Contracts/Communication/Messages/IMessage.cs b/SafeExamBrowser.Contracts/Communication/Messages/IMessage.cs
new file mode 100644
index 00000000..52d1a51e
--- /dev/null
+++ b/SafeExamBrowser.Contracts/Communication/Messages/IMessage.cs
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018 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.Runtime.Serialization;
+
+namespace SafeExamBrowser.Contracts.Communication.Messages
+{
+	public interface IMessage : ISerializable
+	{
+		/// 
+		/// The communication token needed for authentication with the host.
+		/// 
+		Guid CommunicationToken { get; }
+	}
+}
diff --git a/SafeExamBrowser.Contracts/Communication/Responses/IConnectResponse.cs b/SafeExamBrowser.Contracts/Communication/Responses/IConnectResponse.cs
new file mode 100644
index 00000000..664973a7
--- /dev/null
+++ b/SafeExamBrowser.Contracts/Communication/Responses/IConnectResponse.cs
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018 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;
+
+namespace SafeExamBrowser.Contracts.Communication.Responses
+{
+	public interface IConnectResponse : IResponse
+	{
+		/// 
+		/// The communication token needed for authentication with the host. Is null if a connection was refused.
+		/// 
+		Guid? CommunicationToken { get; }
+
+		/// 
+		/// Indicates whether the host has accepted the connection request.
+		/// 
+		bool ConnectionEstablished { get; }
+	}
+}
diff --git a/SafeExamBrowser.Contracts/Communication/Responses/IResponse.cs b/SafeExamBrowser.Contracts/Communication/Responses/IResponse.cs
new file mode 100644
index 00000000..51562212
--- /dev/null
+++ b/SafeExamBrowser.Contracts/Communication/Responses/IResponse.cs
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2018 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.Runtime.Serialization;
+
+namespace SafeExamBrowser.Contracts.Communication.Responses
+{
+	public interface IResponse : ISerializable
+	{
+	}
+}
diff --git a/SafeExamBrowser.Contracts/Configuration/Settings/ISettingsRepository.cs b/SafeExamBrowser.Contracts/Configuration/Settings/ISettingsRepository.cs
index 15fb434a..8c419131 100644
--- a/SafeExamBrowser.Contracts/Configuration/Settings/ISettingsRepository.cs
+++ b/SafeExamBrowser.Contracts/Configuration/Settings/ISettingsRepository.cs
@@ -12,6 +12,12 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
 {
 	public interface ISettingsRepository
 	{
+		/// 
+		/// Retrieves the current settings, i.e. the last ones which were loaded. If no settings have been loaded yet, this property will
+		/// be null.
+		/// 
+		ISettings Current { get; }
+
 		/// 
 		/// Attempts to load settings from the specified path.
 		/// 
diff --git a/SafeExamBrowser.Contracts/Logging/ILogger.cs b/SafeExamBrowser.Contracts/Logging/ILogger.cs
index 04cd8acc..c0351bae 100644
--- a/SafeExamBrowser.Contracts/Logging/ILogger.cs
+++ b/SafeExamBrowser.Contracts/Logging/ILogger.cs
@@ -13,6 +13,12 @@ namespace SafeExamBrowser.Contracts.Logging
 {
 	public interface ILogger
 	{
+		/// 
+		/// Logs the given message with severity DEBUG.
+		/// 
+		/// 
+		void Debug(string message);
+
 		/// 
 		/// Logs the given message with severity INFO.
 		/// 
diff --git a/SafeExamBrowser.Contracts/Logging/LogLevel.cs b/SafeExamBrowser.Contracts/Logging/LogLevel.cs
index 81a845cd..37836a99 100644
--- a/SafeExamBrowser.Contracts/Logging/LogLevel.cs
+++ b/SafeExamBrowser.Contracts/Logging/LogLevel.cs
@@ -13,8 +13,9 @@ namespace SafeExamBrowser.Contracts.Logging
 	/// 
 	public enum LogLevel
 	{
-		Info = 1,
-		Warning = 2,
-		Error = 3
+		Debug = 1,
+		Info = 2,
+		Warning = 3,
+		Error = 4
 	}
 }
diff --git a/SafeExamBrowser.Contracts/Runtime/IRuntimeController.cs b/SafeExamBrowser.Contracts/Runtime/IRuntimeController.cs
index 770fe573..c6452974 100644
--- a/SafeExamBrowser.Contracts/Runtime/IRuntimeController.cs
+++ b/SafeExamBrowser.Contracts/Runtime/IRuntimeController.cs
@@ -6,17 +6,10 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-using SafeExamBrowser.Contracts.Configuration.Settings;
-
 namespace SafeExamBrowser.Contracts.Runtime
 {
 	public interface IRuntimeController
 	{
-		/// 
-		/// Allows to specify the application settings to be used during runtime.
-		/// 
-		ISettings Settings { set; }
-
 		/// 
 		/// Wires up and starts the application event handling.
 		/// 
diff --git a/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj b/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj
index bfcd66da..3b391f27 100644
--- a/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj
+++ b/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj
@@ -50,9 +50,14 @@
   
     
     
+    
   
   
     
+    
+    
+    
+    
     
     
     
diff --git a/SafeExamBrowser.Core.UnitTests/Logging/LoggerTests.cs b/SafeExamBrowser.Core.UnitTests/Logging/LoggerTests.cs
index 36f90238..e0bc98d2 100644
--- a/SafeExamBrowser.Core.UnitTests/Logging/LoggerTests.cs
+++ b/SafeExamBrowser.Core.UnitTests/Logging/LoggerTests.cs
@@ -22,6 +22,7 @@ namespace SafeExamBrowser.Core.UnitTests.Logging
 		public void MustAddMessagesToLog()
 		{
 			var sut = new Logger();
+			var debug = "I'm a debug message";
 			var info = "I'm an info message";
 			var warn = "I'm a warning!";
 			var error = "I AM AN ERROR!!";
@@ -30,6 +31,7 @@ namespace SafeExamBrowser.Core.UnitTests.Logging
 			var message = "I'm a simple text message";
 			var content = new LogText("I'm some raw log text...");
 
+			sut.Debug(debug);
 			sut.Info(info);
 			sut.Warn(warn);
 			sut.Error(error);
@@ -39,34 +41,39 @@ namespace SafeExamBrowser.Core.UnitTests.Logging
 
 			var log = sut.GetLog();
 
-			Assert.IsTrue(log.Count == 7);
+			Assert.IsTrue(log.Count == 8);
 
-			Assert.IsTrue(info.Equals((log[0] as ILogMessage).Message));
-			Assert.IsTrue((log[0] as ILogMessage).Severity == LogLevel.Info);
+			Assert.IsTrue(debug.Equals((log[0] as ILogMessage).Message));
+			Assert.IsTrue((log[0] as ILogMessage).Severity == LogLevel.Debug);
 
-			Assert.IsTrue(warn.Equals((log[1] as ILogMessage).Message));
-			Assert.IsTrue((log[1] as ILogMessage).Severity == LogLevel.Warning);
+			Assert.IsTrue(info.Equals((log[1] as ILogMessage).Message));
+			Assert.IsTrue((log[1] as ILogMessage).Severity == LogLevel.Info);
 
-			Assert.IsTrue(error.Equals((log[2] as ILogMessage).Message));
-			Assert.IsTrue((log[2] as ILogMessage).Severity == LogLevel.Error);
+			Assert.IsTrue(warn.Equals((log[2] as ILogMessage).Message));
+			Assert.IsTrue((log[2] as ILogMessage).Severity == LogLevel.Warning);
 
 			Assert.IsTrue(error.Equals((log[3] as ILogMessage).Message));
 			Assert.IsTrue((log[3] as ILogMessage).Severity == LogLevel.Error);
-			Assert.IsTrue((log[4] as ILogText).Text.Contains(exceptionMessage));
 
-			Assert.IsTrue(message.Equals((log[5] as ILogText).Text));
+			Assert.IsTrue(error.Equals((log[4] as ILogMessage).Message));
+			Assert.IsTrue((log[4] as ILogMessage).Severity == LogLevel.Error);
+			Assert.IsTrue((log[5] as ILogText).Text.Contains(exceptionMessage));
 
-			Assert.IsTrue(content.Text.Equals((log[6] as ILogText).Text));
+			Assert.IsTrue(message.Equals((log[6] as ILogText).Text));
+
+			Assert.IsTrue(content.Text.Equals((log[7] as ILogText).Text));
 		}
 
 		[TestMethod]
 		public void MustReturnCopyOfLog()
 		{
 			var sut = new Logger();
+			var debug = "I'm a debug message";
 			var info = "I'm an info message";
 			var warn = "I'm a warning!";
 			var error = "I AM AN ERROR!!";
 
+			sut.Debug(debug);
 			sut.Info(info);
 			sut.Warn(warn);
 			sut.Error(error);
@@ -87,6 +94,7 @@ namespace SafeExamBrowser.Core.UnitTests.Logging
 		{
 			var sut = new Logger();
 
+			Assert.ThrowsException(() => sut.Debug(null));
 			Assert.ThrowsException(() => sut.Info(null));
 			Assert.ThrowsException(() => sut.Warn(null));
 			Assert.ThrowsException(() => sut.Error(null));
diff --git a/SafeExamBrowser.Core/Communication/CommunicationHostProxy.cs b/SafeExamBrowser.Core/Communication/CommunicationHostProxy.cs
new file mode 100644
index 00000000..c2739109
--- /dev/null
+++ b/SafeExamBrowser.Core/Communication/CommunicationHostProxy.cs
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2018 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.ServiceModel;
+using SafeExamBrowser.Contracts.Communication;
+using SafeExamBrowser.Contracts.Communication.Messages;
+using SafeExamBrowser.Contracts.Communication.Responses;
+using SafeExamBrowser.Contracts.Logging;
+
+namespace SafeExamBrowser.Core.Communication
+{
+	public class CommunicationHostProxy : ICommunicationHost
+	{
+		private string address;
+		private ILogger logger;
+		private ICommunicationHost channel;
+
+		public CommunicationHostProxy(ILogger logger, string address)
+		{
+			this.address = address;
+			this.logger = logger;
+		}
+
+		public IConnectResponse Connect(Guid? token = null)
+		{
+			var endpoint = new EndpointAddress(address);
+
+			channel = ChannelFactory.CreateChannel(new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport), endpoint);
+			(channel as ICommunicationObject).Closed += CommunicationHostProxy_Closed;
+			(channel as ICommunicationObject).Closing += CommunicationHostProxy_Closing;
+			(channel as ICommunicationObject).Faulted += CommunicationHostProxy_Faulted;
+
+			var response = channel.Connect(token);
+
+			logger.Debug($"Tried to connect to {address}, connection was {(response.ConnectionEstablished ? "established" : "refused")}.");
+
+			return response;
+		}
+
+		public void Disconnect(IMessage message)
+		{
+			if (ChannelIsReady())
+			{
+				channel.Disconnect(message);
+				logger.Debug($"Disconnected from {address}, transmitting {ToString(message)}.");
+			}
+
+			throw new CommunicationException($"Tried to disconnect from host, but channel was {GetChannelState()}!");
+		}
+
+		public IResponse Send(IMessage message)
+		{
+			if (ChannelIsReady())
+			{
+				var response = channel.Send(message);
+
+				logger.Debug($"Sent {ToString(message)}, got {ToString(response)}.");
+
+				return response;
+			}
+
+			throw new CommunicationException($"Tried to send {ToString(message)}, but channel was {GetChannelState()}!");
+		}
+
+		private bool ChannelIsReady()
+		{
+			return channel != null && (channel as ICommunicationObject).State == CommunicationState.Opened;
+		}
+
+		private void CommunicationHostProxy_Closed(object sender, EventArgs e)
+		{
+			logger.Debug("Communication channel has been closed.");
+		}
+
+		private void CommunicationHostProxy_Closing(object sender, EventArgs e)
+		{
+			logger.Debug("Communication channel is closing.");
+		}
+
+		private void CommunicationHostProxy_Faulted(object sender, EventArgs e)
+		{
+			logger.Error("Communication channel has faulted!");
+		}
+
+		private string GetChannelState()
+		{
+			return channel == null ? "null" : $"in state '{(channel as ICommunicationObject).State}'";
+		}
+
+		private string ToString(IMessage message)
+		{
+			return message != null ? $"message of type '{message.GetType()}'" : "no message";
+		}
+
+		private string ToString(IResponse response)
+		{
+			return response != null ? $"response of type '{response.GetType()}'" : "no response";
+		}
+	}
+}
diff --git a/SafeExamBrowser.Core/Logging/Logger.cs b/SafeExamBrowser.Core/Logging/Logger.cs
index e2a327f0..c5c4aaa6 100644
--- a/SafeExamBrowser.Core/Logging/Logger.cs
+++ b/SafeExamBrowser.Core/Logging/Logger.cs
@@ -21,6 +21,16 @@ namespace SafeExamBrowser.Core.Logging
 		private readonly IList log = new List();
 		private readonly IList observers = new List();
 
+		public void Debug(string message)
+		{
+			if (message == null)
+			{
+				throw new ArgumentNullException(nameof(message));
+			}
+
+			Add(LogLevel.Debug, message);
+		}
+
 		public void Info(string message)
 		{
 			if (message == null)
diff --git a/SafeExamBrowser.Core/Logging/ModuleLogger.cs b/SafeExamBrowser.Core/Logging/ModuleLogger.cs
index 040c9809..7370cf7c 100644
--- a/SafeExamBrowser.Core/Logging/ModuleLogger.cs
+++ b/SafeExamBrowser.Core/Logging/ModuleLogger.cs
@@ -27,6 +27,11 @@ namespace SafeExamBrowser.Core.Logging
 			this.module = module;
 		}
 
+		public void Debug(string message)
+		{
+			logger.Debug(AppendModuleInfo(message));
+		}
+
 		public void Error(string message)
 		{
 			logger.Error(AppendModuleInfo(message));
diff --git a/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj b/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj
index f0b0fcc2..b5f686b1 100644
--- a/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj
+++ b/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj
@@ -50,6 +50,7 @@
   
     
     
+    
     
     
   
@@ -57,6 +58,7 @@
     
     
     
+    
     
     
     
diff --git a/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ConfigurationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ConfigurationOperationTests.cs
index bdeab170..eb4b89ea 100644
--- a/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ConfigurationOperationTests.cs
+++ b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ConfigurationOperationTests.cs
@@ -14,7 +14,6 @@ using SafeExamBrowser.Contracts.Configuration;
 using SafeExamBrowser.Contracts.Configuration.Settings;
 using SafeExamBrowser.Contracts.I18n;
 using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.Runtime;
 using SafeExamBrowser.Contracts.UserInterface;
 using SafeExamBrowser.Runtime.Behaviour.Operations;
 
@@ -24,7 +23,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 	public class ConfigurationOperationTests
 	{
 		private Mock logger;
-		private Mock controller;
 		private Mock info;
 		private Mock repository;
 		private Mock settings;
@@ -37,7 +35,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 		public void Initialize()
 		{
 			logger = new Mock();
-			controller = new Mock();
 			info = new Mock();
 			repository = new Mock();
 			settings = new Mock();
@@ -55,23 +52,23 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 		[TestMethod]
 		public void MustNotFailWithoutCommandLineArgs()
 		{
-			controller.SetupSet(c => c.Settings = It.IsAny());
+			repository.Setup(r => r.LoadDefaults());
 
-			sut = new ConfigurationOperation(logger.Object, controller.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null)
+			sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null)
 			{
 				SplashScreen = splashScreen.Object
 			};
 
 			sut.Perform();
 
-			sut = new ConfigurationOperation(logger.Object, controller.Object, info.Object, repository.Object, text.Object, uiFactory.Object, new string[] { })
+			sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, new string[] { })
 			{
 				SplashScreen = splashScreen.Object
 			};
 
 			sut.Perform();
 
-			controller.VerifySet(c => c.Settings = It.IsAny(), Times.Exactly(2));
+			repository.Verify(r => r.LoadDefaults(), Times.Exactly(2));
 		}
 
 		[TestMethod]
@@ -79,7 +76,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 		{
 			var path = @"an/invalid\path.'*%yolo/()";
 
-			sut = new ConfigurationOperation(logger.Object, controller.Object, info.Object, repository.Object, text.Object, uiFactory.Object, new [] { "blubb.exe", path })
+			sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, new [] { "blubb.exe", path })
 			{
 				SplashScreen = splashScreen.Object
 			};
@@ -96,14 +93,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 			info.SetupGet(r => r.ProgramDataFolder).Returns(location);
 			info.SetupGet(r => r.AppDataFolder).Returns(location);
 
-			sut = new ConfigurationOperation(logger.Object, controller.Object, info.Object, repository.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", path })
+			sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, new[] { "blubb.exe", path })
 			{
 				SplashScreen = splashScreen.Object
 			};
 
 			sut.Perform();
 
-			controller.VerifySet(c => c.Settings = It.IsAny(), Times.Once);
 			repository.Verify(r => r.Load(It.Is(u => u.Equals(new Uri(path)))), Times.Once);
 		}
 
@@ -115,14 +111,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 			info.SetupGet(r => r.ProgramDataFolder).Returns(location);
 			info.SetupGet(r => r.AppDataFolder).Returns($@"{location}\WRONG");
 
-			sut = new ConfigurationOperation(logger.Object, controller.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null)
+			sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null)
 			{
 				SplashScreen = splashScreen.Object
 			};
 
 			sut.Perform();
 
-			controller.VerifySet(c => c.Settings = It.IsAny(), Times.Once);
 			repository.Verify(r => r.Load(It.Is(u => u.Equals(new Uri(Path.Combine(location, "SettingsDummy.txt"))))), Times.Once);
 		}
 
@@ -133,28 +128,26 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 
 			info.SetupGet(r => r.AppDataFolder).Returns(location);
 
-			sut = new ConfigurationOperation(logger.Object, controller.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null)
+			sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null)
 			{
 				SplashScreen = splashScreen.Object
 			};
 
 			sut.Perform();
 
-			controller.VerifySet(c => c.Settings = It.IsAny(), Times.Once);
 			repository.Verify(r => r.Load(It.Is(u => u.Equals(new Uri(Path.Combine(location, "SettingsDummy.txt"))))), Times.Once);
 		}
 
 		[TestMethod]
 		public void MustFallbackToDefaultsAsLastPrio()
 		{
-			sut = new ConfigurationOperation(logger.Object, controller.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null)
+			sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null)
 			{
 				SplashScreen = splashScreen.Object
 			};
 
 			sut.Perform();
 
-			controller.VerifySet(c => c.Settings = It.IsAny(), Times.Once);
 			repository.Verify(r => r.LoadDefaults(), Times.Once);
 		}
 
@@ -166,7 +159,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 			info.SetupGet(r => r.ProgramDataFolder).Returns(location);
 			uiFactory.Setup(u => u.Show(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(MessageBoxResult.Yes);
 
-			sut = new ConfigurationOperation(logger.Object, controller.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null)
+			sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null)
 			{
 				SplashScreen = splashScreen.Object
 			};
@@ -181,7 +174,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
 		{
 			uiFactory.Setup(u => u.Show(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(MessageBoxResult.No);
 
-			sut = new ConfigurationOperation(logger.Object, controller.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null)
+			sut = new ConfigurationOperation(logger.Object, info.Object, repository.Object, text.Object, uiFactory.Object, null)
 			{
 				SplashScreen = splashScreen.Object
 			};
diff --git a/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ServiceOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ServiceOperationTests.cs
new file mode 100644
index 00000000..10d4df4b
--- /dev/null
+++ b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ServiceOperationTests.cs
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018 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 Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
+{
+	[TestClass]
+	public class ServiceOperationTests
+	{
+		[TestMethod]
+		public void Test()
+		{
+			// TODO
+		}
+	}
+}
diff --git a/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj b/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj
index 881e3ab3..e3b1a600 100644
--- a/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj
+++ b/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj
@@ -82,6 +82,7 @@
   
     
     
+    
     
   
   
diff --git a/SafeExamBrowser.Runtime/App.cs b/SafeExamBrowser.Runtime/App.cs
index e1ff1797..f7118da0 100644
--- a/SafeExamBrowser.Runtime/App.cs
+++ b/SafeExamBrowser.Runtime/App.cs
@@ -60,7 +60,7 @@ namespace SafeExamBrowser.Runtime
 			base.OnStartup(e);
 
 			instances.BuildObjectGraph();
-			LogStartupInformation();
+			instances.LogStartupInformation();
 
 			var success = instances.StartupController.TryInitializeApplication(instances.StartupOperations);
 
@@ -79,27 +79,11 @@ namespace SafeExamBrowser.Runtime
 
 		protected override void OnExit(ExitEventArgs e)
 		{
-			instances.Logger?.Log($"{Environment.NewLine}# Application terminated at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
+			instances.LogShutdownInformation();
 
 			base.OnExit(e);
 		}
 
-		private void LogStartupInformation()
-		{
-			var runtimeInfo = instances.RuntimeInfo;
-			var logger = instances.Logger;
-			var titleLine = $"/* {runtimeInfo.ProgramTitle}, Version {runtimeInfo.ProgramVersion}{Environment.NewLine}";
-			var copyrightLine = $"/* {runtimeInfo.ProgramCopyright}{Environment.NewLine}";
-			var emptyLine = $"/* {Environment.NewLine}";
-			var githubLine = $"/* Please visit https://github.com/SafeExamBrowser for more information.";
-
-			logger.Log($"{titleLine}{copyrightLine}{emptyLine}{githubLine}");
-			logger.Log(string.Empty);
-			logger.Log($"# Application started at {runtimeInfo.ApplicationStartTime.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
-			logger.Log($"# Running on {instances.SystemInfo.OperatingSystemInfo}");
-			logger.Log(string.Empty);
-		}
-
 		private void MainWindow_Closing(object sender, CancelEventArgs e)
 		{
 			var operations = new Queue(instances.StartupOperations.Reverse());
diff --git a/SafeExamBrowser.Runtime/Behaviour/Operations/ConfigurationOperation.cs b/SafeExamBrowser.Runtime/Behaviour/Operations/ConfigurationOperation.cs
index 85a8401b..90c92195 100644
--- a/SafeExamBrowser.Runtime/Behaviour/Operations/ConfigurationOperation.cs
+++ b/SafeExamBrowser.Runtime/Behaviour/Operations/ConfigurationOperation.cs
@@ -13,7 +13,6 @@ using SafeExamBrowser.Contracts.Configuration;
 using SafeExamBrowser.Contracts.Configuration.Settings;
 using SafeExamBrowser.Contracts.I18n;
 using SafeExamBrowser.Contracts.Logging;
-using SafeExamBrowser.Contracts.Runtime;
 using SafeExamBrowser.Contracts.UserInterface;
 
 namespace SafeExamBrowser.Runtime.Behaviour.Operations
@@ -21,7 +20,6 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 	internal class ConfigurationOperation : IOperation
 	{
 		private ILogger logger;
-		private IRuntimeController controller;
 		private IRuntimeInfo runtimeInfo;
 		private ISettingsRepository repository;
 		private IText text;
@@ -33,7 +31,6 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 
 		public ConfigurationOperation(
 			ILogger logger,
-			IRuntimeController controller,
 			IRuntimeInfo runtimeInfo,
 			ISettingsRepository repository,
 			IText text,
@@ -41,7 +38,6 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 			string[] commandLineArgs)
 		{
 			this.logger = logger;
-			this.controller = controller;
 			this.commandLineArgs = commandLineArgs;
 			this.repository = repository;
 			this.runtimeInfo = runtimeInfo;
@@ -62,11 +58,10 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 				logger.Info($"Loading configuration from '{uri.AbsolutePath}'...");
 				settings = repository.Load(uri);
 
-				if (settings.ConfigurationMode == ConfigurationMode.ConfigureClient && Abort())
+				if (settings.ConfigurationMode == ConfigurationMode.ConfigureClient && UserWantsToAbortStartup())
 				{
 					AbortStartup = true;
-
-					return;
+					logger.Info($"The user chose to {(AbortStartup ? "abort" : "continue")} the application startup after successful client configuration.");
 				}
 			}
 			else
@@ -74,8 +69,6 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 				logger.Info("No valid settings file specified nor found in PROGRAMDATA or APPDATA - loading default settings...");
 				settings = repository.LoadDefaults();
 			}
-
-			controller.Settings = settings;
 		}
 
 		public void Revert()
@@ -116,23 +109,13 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
 			return isValidUri;
 		}
 
-		private bool Abort()
+		private bool UserWantsToAbortStartup()
 		{
 			var message = text.Get(TextKey.MessageBox_ConfigureClientSuccess);
 			var title = text.Get(TextKey.MessageBox_ConfigureClientSuccessTitle);
-			var quitDialogResult = uiFactory.Show(message, title, MessageBoxAction.YesNo, MessageBoxIcon.Question);
-			var abort = quitDialogResult == MessageBoxResult.Yes;
+			var abort = uiFactory.Show(message, title, MessageBoxAction.YesNo, MessageBoxIcon.Question);
 
-			if (abort)
-			{
-				logger.Info("The user chose to terminate the application after successful client configuration.");
-			}
-			else
-			{
-				logger.Info("The user chose to continue starting up the application after successful client configuration.");
-			}
-
-			return abort;
+			return abort == MessageBoxResult.Yes;
 		}
 	}
 }
diff --git a/SafeExamBrowser.Runtime/Behaviour/Operations/ServiceOperation.cs b/SafeExamBrowser.Runtime/Behaviour/Operations/ServiceOperation.cs
new file mode 100644
index 00000000..531cc21f
--- /dev/null
+++ b/SafeExamBrowser.Runtime/Behaviour/Operations/ServiceOperation.cs
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018 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.Contracts.Behaviour;
+using SafeExamBrowser.Contracts.Communication;
+using SafeExamBrowser.Contracts.Configuration.Settings;
+using SafeExamBrowser.Contracts.Logging;
+using SafeExamBrowser.Contracts.UserInterface;
+
+namespace SafeExamBrowser.Runtime.Behaviour.Operations
+{
+	internal class ServiceOperation : IOperation
+	{
+		private ICommunicationHost serviceHost;
+		private ILogger logger;
+		private ISettingsRepository settingsRepository;
+
+		public bool AbortStartup { get; private set; }
+		public ISplashScreen SplashScreen { private get; set; }
+
+		public ServiceOperation(ICommunicationHost serviceHost, ILogger logger, ISettingsRepository settingsRepository)
+		{
+			this.serviceHost = serviceHost;
+			this.logger = logger;
+			this.settingsRepository = settingsRepository;
+		}
+
+		public void Perform()
+		{
+			logger.Info("Initializing service connection...");
+			// SplashScreen.UpdateText(...)
+
+			// TODO
+		}
+
+		public void Revert()
+		{
+			// TODO
+		}
+	}
+}
diff --git a/SafeExamBrowser.Runtime/CompositionRoot.cs b/SafeExamBrowser.Runtime/CompositionRoot.cs
index 2535dab5..02ed3b77 100644
--- a/SafeExamBrowser.Runtime/CompositionRoot.cs
+++ b/SafeExamBrowser.Runtime/CompositionRoot.cs
@@ -17,6 +17,7 @@ using SafeExamBrowser.Contracts.Configuration;
 using SafeExamBrowser.Contracts.Logging;
 using SafeExamBrowser.Core.Behaviour;
 using SafeExamBrowser.Core.Behaviour.Operations;
+using SafeExamBrowser.Core.Communication;
 using SafeExamBrowser.Core.I18n;
 using SafeExamBrowser.Core.Logging;
 using SafeExamBrowser.Runtime.Behaviour;
@@ -28,11 +29,12 @@ namespace SafeExamBrowser.Runtime
 {
 	internal class CompositionRoot
 	{
-		internal ILogger Logger { get; private set; }
-		internal RuntimeInfo RuntimeInfo { get; private set; }
+		private ILogger logger;
+		private RuntimeInfo runtimeInfo;
+		private ISystemInfo systemInfo;
+
 		internal IShutdownController ShutdownController { get; private set; }
 		internal IStartupController StartupController { get; private set; }
-		internal ISystemInfo SystemInfo { get; private set; }
 		internal Queue StartupOperations { get; private set; }
 
 		internal void BuildObjectGraph()
@@ -42,24 +44,45 @@ namespace SafeExamBrowser.Runtime
 			var settingsRepository = new SettingsRepository();
 			var uiFactory = new UserInterfaceFactory();
 
-			Logger = new Logger();
-			RuntimeInfo = new RuntimeInfo();
-			SystemInfo = new SystemInfo();
+			logger = new Logger();
+			runtimeInfo = new RuntimeInfo();
+			systemInfo = new SystemInfo();
 
 			InitializeRuntimeInfo();
 			InitializeLogging();
 
-			var text = new Text(Logger);
-			var runtimeController = new RuntimeController(new ModuleLogger(Logger, typeof(RuntimeController)));
+			var text = new Text(logger);
+			var runtimeController = new RuntimeController(new ModuleLogger(logger, typeof(RuntimeController)));
+			var serviceProxy = new CommunicationHostProxy(new ModuleLogger(logger, typeof(CommunicationHostProxy)), "net.pipe://localhost/safeexambrowser/service");
 
-			ShutdownController = new ShutdownController(Logger, RuntimeInfo, text, uiFactory);
-			StartupController = new StartupController(Logger, RuntimeInfo, SystemInfo, text, uiFactory);
+			ShutdownController = new ShutdownController(logger, runtimeInfo, text, uiFactory);
+			StartupController = new StartupController(logger, runtimeInfo, systemInfo, text, uiFactory);
 
 			StartupOperations = new Queue();
-			StartupOperations.Enqueue(new I18nOperation(Logger, text));
-			StartupOperations.Enqueue(new ConfigurationOperation(Logger, runtimeController, RuntimeInfo, settingsRepository, text, uiFactory, args));
+			StartupOperations.Enqueue(new I18nOperation(logger, text));
+			StartupOperations.Enqueue(new ConfigurationOperation(logger, runtimeInfo, settingsRepository, text, uiFactory, args));
+			StartupOperations.Enqueue(new ServiceOperation(serviceProxy, logger, settingsRepository));
 			//StartupOperations.Enqueue(new KioskModeOperation());
-			StartupOperations.Enqueue(new RuntimeControllerOperation(runtimeController, Logger));
+			StartupOperations.Enqueue(new RuntimeControllerOperation(runtimeController, logger));
+		}
+
+		internal void LogStartupInformation()
+		{
+			var titleLine = $"/* {runtimeInfo.ProgramTitle}, Version {runtimeInfo.ProgramVersion}{Environment.NewLine}";
+			var copyrightLine = $"/* {runtimeInfo.ProgramCopyright}{Environment.NewLine}";
+			var emptyLine = $"/* {Environment.NewLine}";
+			var githubLine = $"/* Please visit https://www.github.com/SafeExamBrowser for more information.";
+
+			logger.Log($"{titleLine}{copyrightLine}{emptyLine}{githubLine}");
+			logger.Log(string.Empty);
+			logger.Log($"# Application started at {runtimeInfo.ApplicationStartTime.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
+			logger.Log($"# Running on {systemInfo.OperatingSystemInfo}");
+			logger.Log(string.Empty);
+		}
+
+		internal void LogShutdownInformation()
+		{
+			logger?.Log($"{Environment.NewLine}# Application terminated at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
 		}
 
 		private void InitializeRuntimeInfo()
@@ -70,25 +93,25 @@ namespace SafeExamBrowser.Runtime
 			var logFolder = Path.Combine(appDataFolder, "Logs");
 			var logFilePrefix = startTime.ToString("yyyy-MM-dd\\_HH\\hmm\\mss\\s");
 
-			RuntimeInfo.ApplicationStartTime = startTime;
-			RuntimeInfo.AppDataFolder = appDataFolder;
-			RuntimeInfo.BrowserCachePath = Path.Combine(appDataFolder, "Cache");
-			RuntimeInfo.BrowserLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Browser.txt");
-			RuntimeInfo.ClientLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Client.txt");
-			RuntimeInfo.DefaultSettingsFileName = "SebClientSettings.seb";
-			RuntimeInfo.ProgramCopyright = executable.GetCustomAttribute().Copyright;
-			RuntimeInfo.ProgramDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), nameof(SafeExamBrowser));
-			RuntimeInfo.ProgramTitle = executable.GetCustomAttribute().Title;
-			RuntimeInfo.ProgramVersion = executable.GetCustomAttribute().InformationalVersion;
-			RuntimeInfo.RuntimeLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Runtime.txt");
+			runtimeInfo.ApplicationStartTime = startTime;
+			runtimeInfo.AppDataFolder = appDataFolder;
+			runtimeInfo.BrowserCachePath = Path.Combine(appDataFolder, "Cache");
+			runtimeInfo.BrowserLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Browser.txt");
+			runtimeInfo.ClientLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Client.txt");
+			runtimeInfo.DefaultSettingsFileName = "SebClientSettings.seb";
+			runtimeInfo.ProgramCopyright = executable.GetCustomAttribute().Copyright;
+			runtimeInfo.ProgramDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), nameof(SafeExamBrowser));
+			runtimeInfo.ProgramTitle = executable.GetCustomAttribute().Title;
+			runtimeInfo.ProgramVersion = executable.GetCustomAttribute().InformationalVersion;
+			runtimeInfo.RuntimeLogFile = Path.Combine(logFolder, $"{logFilePrefix}_Runtime.txt");
 		}
 
 		private void InitializeLogging()
 		{
-			var logFileWriter = new LogFileWriter(new DefaultLogFormatter(), RuntimeInfo.RuntimeLogFile);
+			var logFileWriter = new LogFileWriter(new DefaultLogFormatter(), runtimeInfo.RuntimeLogFile);
 
 			logFileWriter.Initialize();
-			Logger.Subscribe(logFileWriter);
+			logger.Subscribe(logFileWriter);
 		}
 	}
 }
diff --git a/SafeExamBrowser.Runtime/SafeExamBrowser.Runtime.csproj b/SafeExamBrowser.Runtime/SafeExamBrowser.Runtime.csproj
index 2f587880..2b04d1f4 100644
--- a/SafeExamBrowser.Runtime/SafeExamBrowser.Runtime.csproj
+++ b/SafeExamBrowser.Runtime/SafeExamBrowser.Runtime.csproj
@@ -89,6 +89,7 @@
     
     
     
+    
     
     
       Code