diff --git a/ATXCommon/ATXCommon.csproj b/ATXCommon/ATXCommon.csproj
index 4f96cd3cd8f4dc269029eedd132946ce4b0fbf29..dcc7ac57b7371704ab4d65f89b2b29e8dc05b90e 100644
--- a/ATXCommon/ATXCommon.csproj
+++ b/ATXCommon/ATXCommon.csproj
@@ -53,6 +53,7 @@
     <Compile Include="Serializables\ServiceConfig.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Serializables\ServiceStatus.cs" />
+    <Compile Include="SystemChecks.cs" />
     <Compile Include="TimeUtils.cs" />
   </ItemGroup>
   <ItemGroup>
diff --git a/ATXCommon/ActiveDirectory.cs b/ATXCommon/ActiveDirectory.cs
index 98b99bf45195b0ec18c3701c805dd65902804787..6fd6335713ca0d8fb04d3a5eae6bdf6a4def17fc 100644
--- a/ATXCommon/ActiveDirectory.cs
+++ b/ATXCommon/ActiveDirectory.cs
@@ -1,7 +1,5 @@
 using System;
 using System.DirectoryServices.AccountManagement;
-using System.Linq;
-using System.Management;
 using NLog;
 
 namespace ATXCommon
@@ -10,30 +8,6 @@ namespace ATXCommon
     {
         private static readonly Logger Log = LogManager.GetCurrentClassLogger();
 
-        /// <summary>
-        /// Check if a user is currently logged into Windows.
-        /// 
-        /// WARNING: this DOES NOT ACCOUNT for users logged in via RDP!!
-        /// </summary>
-        /// See https://stackoverflow.com/questions/5218778/ for the RDP problem.
-        public static bool NoUserIsLoggedOn() {
-            var username = "";
-            try {
-                var searcher = new ManagementObjectSearcher("SELECT UserName " +
-                                                            "FROM Win32_ComputerSystem");
-                var collection = searcher.Get();
-                username = (string)collection.Cast<ManagementBaseObject>().First()["UserName"];
-            }
-            catch (Exception ex) {
-                // TODO / FIXME: combine log and admin-email!
-                var msg = string.Format("Error in getCurrentUsername(): {0}", ex.Message);
-                Log.Error(msg);
-                // TODO: FIXME!
-                // SendAdminEmail(msg);
-            }
-            return username == "";
-        }
-
         /// <summary>
         /// Get the user email address from ActiveDirectory.
         /// </summary>
diff --git a/ATXCommon/SystemChecks.cs b/ATXCommon/SystemChecks.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f7f42358977753af5f361fb0c185654433c33d1f
--- /dev/null
+++ b/ATXCommon/SystemChecks.cs
@@ -0,0 +1,93 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Management;
+using NLog;
+
+namespace ATXCommon
+{
+    public static class SystemChecks
+    {
+        private static readonly Logger Log = LogManager.GetCurrentClassLogger();
+
+        /// <summary>
+        /// Get the available physical memory in MB.
+        /// </summary>
+        /// <returns>The available physical memory in MB or -1 in case of an error.</returns>
+        public static long GetFreeMemory() {
+            try {
+                var searcher =
+                    new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem");
+                foreach (var mo in searcher.Get()) {
+                    var queryObj = (ManagementObject)mo;
+                    return Convert.ToInt64(queryObj["FreePhysicalMemory"]) / 1024;
+                }
+            }
+            catch (Exception ex) {
+                Log.Warn("Error in GetFreeMemory: {0}", ex.Message);
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// Get the CPU usage in percent over all cores.
+        /// </summary>
+        /// <returns>CPU usage in percent or -1 if an error occured.</returns>
+        public static int GetCpuUsage() {
+            try {
+                var searcher = new ManagementObjectSearcher("select * from Win32_PerfFormattedData_PerfOS_Processor");
+                foreach (var mo in searcher.Get()) {
+                    var obj = (ManagementObject)mo;
+                    var usage = obj["PercentProcessorTime"];
+                    var name = obj["Name"];
+                    if (name.ToString().Equals("_Total"))
+                        return Convert.ToInt32(usage);
+                }
+            }
+            catch (Exception ex) {
+                Log.Warn("Error in GetCpuUsage: {0}", ex.Message);
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// Get the free space of a drive in megabytes.
+        /// </summary>
+        /// /// <param name="drive">The drive name, e.g. "c:".</param>
+        /// <returns>Free space of a drive in megabytes, zero if an error occured.</returns>
+        public static long GetFreeDriveSpace(string drive) {
+            try {
+                var dInfo = new DriveInfo(drive);
+                return dInfo.TotalFreeSpace / Conv.MegaBytes;
+            }
+            catch (Exception ex) {
+                Log.Warn("Error in GetFreeDriveSpace({0}): {1}", drive, ex.Message);
+            }
+            return 0;
+        }
+
+        /// <summary>
+        /// Check if a user is currently logged into Windows.
+        /// 
+        /// WARNING: this DOES NOT ACCOUNT for users logged in via RDP!!
+        /// </summary>
+        /// See https://stackoverflow.com/questions/5218778/ for the RDP problem.
+        public static bool NoUserIsLoggedOn() {
+            var username = "";
+            try {
+                var searcher = new ManagementObjectSearcher("SELECT UserName " +
+                                                            "FROM Win32_ComputerSystem");
+                var collection = searcher.Get();
+                username = (string)collection.Cast<ManagementBaseObject>().First()["UserName"];
+            }
+            catch (Exception ex) {
+                // TODO / FIXME: combine log and admin-email!
+                var msg = string.Format("Error in getCurrentUsername(): {0}", ex.Message);
+                Log.Error(msg);
+                // TODO: FIXME!
+                // SendAdminEmail(msg);
+            }
+            return username == "";
+        }
+    }
+}
diff --git a/AutoTx/AutoTx.cs b/AutoTx/AutoTx.cs
index ae708e59c3f37be9cfb9e2b3b6c293b917f6c38e..2c87db6dc5be5727d4d9cf8be161aa4c7954e7c4 100644
--- a/AutoTx/AutoTx.cs
+++ b/AutoTx/AutoTx.cs
@@ -284,10 +284,10 @@ namespace AutoTx
 
             msg += "\n------ Current system parameters ------\n" +
                    "Hostname: " + Environment.MachineName + "\n" +
-                   "Free system memory: " + GetFreeMemory() + " MB" + "\n";
+                   "Free system memory: " + SystemChecks.GetFreeMemory() + " MB" + "\n";
             foreach (var driveToCheck in _config.SpaceMonitoring) {
                 msg += "Free space on drive '" + driveToCheck.DriveName + "': " +
-                       GetFreeDriveSpace(driveToCheck.DriveName) + "\n";
+                       SystemChecks.GetFreeDriveSpace(driveToCheck.DriveName) + "\n";
             }
 
 
@@ -441,9 +441,9 @@ namespace AutoTx
 
             // check all system parameters for valid ranges and remember the reason in a string
             // if one of them is failing (to report in the log why we're suspended)
-            if (GetCpuUsage() >= _config.MaxCpuUsage)
+            if (SystemChecks.GetCpuUsage() >= _config.MaxCpuUsage)
                 limitReason = "CPU usage";
-            else if (GetFreeMemory() < _config.MinAvailableMemory)
+            else if (SystemChecks.GetFreeMemory() < _config.MinAvailableMemory)
                 limitReason = "RAM usage";
             else {
                 var blacklistedProcess = CheckForBlacklistedProcesses();
@@ -463,7 +463,7 @@ namespace AutoTx
             }
             
             // set state to "Running" if no-one is logged on:
-            if (ActiveDirectory.NoUserIsLoggedOn()) {
+            if (SystemChecks.NoUserIsLoggedOn()) {
                 _status.ServiceSuspended = false;
                 if (!string.IsNullOrEmpty(_status.LimitReason)) {
                     _status.LimitReason = ""; // reset to force a message on next service suspend
diff --git a/AutoTx/SystemChecks.cs b/AutoTx/SystemChecks.cs
index cbda3a29b96fc37b58ddce566419897570d63c83..2364680f51d72df3d93d4a9a14c417fb6139646a 100644
--- a/AutoTx/SystemChecks.cs
+++ b/AutoTx/SystemChecks.cs
@@ -1,69 +1,11 @@
 using System;
 using System.Diagnostics;
-using System.IO;
-using System.Management;
 using ATXCommon;
 
 namespace AutoTx
 {
     public partial class AutoTx
     {
-
-        /// <summary>
-        /// Get the available physical memory in MB.
-        /// </summary>
-        /// <returns>The available physical memory in MB or -1 in case of an error.</returns>
-        private long GetFreeMemory() {
-            try {
-                var searcher =
-                    new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem");
-                foreach (var mo in searcher.Get()) {
-                    var queryObj = (ManagementObject) mo;
-                    return Convert.ToInt64(queryObj["FreePhysicalMemory"]) / 1024;
-                }
-            }
-            catch (Exception ex) {
-                Log.Warn("Error in GetFreeMemory: {0}", ex.Message);
-            }
-            return -1;
-        }
-
-        /// <summary>
-        /// Get the CPU usage in percent over all cores.
-        /// </summary>
-        /// <returns>CPU usage in percent or -1 if an error occured.</returns>
-        private int GetCpuUsage() {
-            try {
-                var searcher = new ManagementObjectSearcher("select * from Win32_PerfFormattedData_PerfOS_Processor");
-                foreach (var mo in searcher.Get()) {
-                    var obj = (ManagementObject) mo;
-                    var usage = obj["PercentProcessorTime"];
-                    var name = obj["Name"];
-                    if (name.ToString().Equals("_Total")) return Convert.ToInt32(usage);
-                }
-            }
-            catch (Exception ex) {
-                Log.Warn("Error in GetCpuUsage: {0}", ex.Message);
-            }
-            return -1;
-        }
-
-        /// <summary>
-        /// Get the free space of a drive in megabytes.
-        /// </summary>
-        /// /// <param name="drive">The drive name, e.g. "c:".</param>
-        /// <returns>Free space of a drive in megabytes, zero if an error occured.</returns>
-        private long GetFreeDriveSpace(string drive) {
-            try {
-                var dInfo = new DriveInfo(drive);
-                return dInfo.TotalFreeSpace / Conv.MegaBytes;
-            }
-            catch (Exception ex) {
-                Log.Warn("Error in GetFreeDriveSpace({0}): {1}", drive, ex.Message);
-            }
-            return 0;
-        }
-
         /// <summary>
         /// Check all configured disks for their free space and send a notification
         /// if necessary (depending on the configured delta time).
@@ -71,7 +13,7 @@ namespace AutoTx
         public void CheckFreeDiskSpace() {
             var msg = "";
             foreach (var driveToCheck in _config.SpaceMonitoring) {
-                var freeSpace = GetFreeDriveSpace(driveToCheck.DriveName);
+                var freeSpace = SystemChecks.GetFreeDriveSpace(driveToCheck.DriveName);
                 if (freeSpace >= driveToCheck.SpaceThreshold) continue;
 
                 msg += "Drive '" + driveToCheck.DriveName +