Last active
October 6, 2016 21:13
-
-
Save rdev5/fb5aacc9e5f5a89fe21f9bed9d7f3a29 to your computer and use it in GitHub Desktop.
Windows Service for disabling network adapters on screen lock, and re-enabling on screen unlock. Must be installed under Local System account to have write access to Event Log and managing network adapters (netsh).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Net.NetworkInformation; | |
namespace WorkstationLockdown | |
{ | |
public static class NetworkAdapterHelpers | |
{ | |
/// <summary> | |
/// Default list of adapters. | |
/// </summary> | |
public static readonly string[] Adapters = NetworkInterface.GetAllNetworkInterfaces().Select(a => a.Name).ToArray(); | |
private static void Log(EventLog logger, string msg, EventLogEntryType type = EventLogEntryType.Information) | |
{ | |
if (logger == null) | |
return; | |
if (string.IsNullOrEmpty(msg)) | |
return; | |
logger.WriteEntry(msg, type); | |
} | |
/// <summary> | |
/// Evaluates if adapter is currently installed. | |
/// </summary> | |
/// <param name="adapter"></param> | |
/// <param name="logger"></param> | |
/// <returns></returns> | |
public static bool ValidAdapter(string adapter, EventLog logger = null) | |
{ | |
Log(logger, string.Format("Looking for {0} in list of valid adapters ({1})", adapter, string.Join(", ", Adapters))); | |
return !string.IsNullOrEmpty(adapter) && Adapters.Contains(adapter); | |
} | |
/// <summary> | |
/// Enables network adapter. | |
/// </summary> | |
/// <remarks> | |
/// Command: netsh interface set interface {0} enable | |
/// | |
/// Must be run as administrator | |
/// </remarks> | |
/// <param name="adapter"></param> | |
/// <param name="logger"></param> | |
public static void EnableAdapter(string adapter, EventLog logger = null) | |
{ | |
if (!ValidAdapter(adapter, logger)) | |
throw new Exception("Invalid adapter: " + adapter); | |
var start = new ProcessStartInfo("netsh", string.Format("interface set interface \"{0}\" enable", adapter)); | |
Log(logger, ("Executing: netsh " + string.Format("interface set interface \"{0}\" enable", adapter))); | |
using (var process = new Process { StartInfo = start }) | |
{ | |
Log(logger, | |
process.Start() | |
? string.Format("Re-enabled network adapter ({0})", adapter) | |
: string.Format("Failed to re-enable network adapter ({0})", adapter)); | |
} | |
} | |
/// <summary> | |
/// Disables network adapter. | |
/// </summary> | |
/// <remarks> | |
/// Command: netsh interface set interface {0} disable | |
/// | |
/// Must be run as administrator | |
/// </remarks> | |
/// <param name="adapter"></param> | |
/// <param name="logger"></param> | |
public static void DisableAdapter(string adapter, EventLog logger = null) | |
{ | |
if (!ValidAdapter(adapter, logger)) | |
throw new Exception("Invalid adapter: " + adapter); | |
var start = new ProcessStartInfo("netsh", string.Format("interface set interface \"{0}\" disable", adapter)); | |
Log(logger, "Executing: netsh " + string.Format("interface set interface \"{0}\" disable", adapter)); | |
using (var process = new Process { StartInfo = start }) | |
{ | |
Log(logger, | |
process.Start() | |
? string.Format("Disabled network adapter ({0})", adapter) | |
: string.Format("Failed to disable network adapter ({0})", adapter)); | |
} | |
} | |
/// <summary> | |
/// Bulk enables list of network adapters. | |
/// </summary> | |
/// <param name="adapters">Specifies alternate list of adapters to enable.</param> | |
/// <param name="logger"></param> | |
public static void EnableAll(string[] adapters = null, EventLog logger = null) | |
{ | |
adapters = adapters ?? Adapters; | |
if (adapters == null || adapters.Length == 0) | |
throw new ArgumentNullException("adapters"); | |
foreach (var a in adapters) | |
EnableAdapter(a, logger); | |
} | |
/// <summary> | |
/// Bulk disables list of network adapters. | |
/// </summary> | |
/// <param name="adapters">Specifies alternate list of adapters to disable.</param> | |
/// <param name="logger"></param> | |
public static void DisableAll(string[] adapters = null, EventLog logger = null) | |
{ | |
adapters = adapters ?? Adapters; | |
if (adapters == null || adapters.Length == 0) | |
throw new ArgumentNullException("adapters"); | |
foreach (var a in adapters) | |
DisableAdapter(a, logger); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Runtime.InteropServices; | |
using System.ServiceProcess; | |
using System.Timers; | |
namespace WorkstationLockdown | |
{ | |
public enum ServiceState | |
{ | |
SERVICE_STOPPED = 0x00000001, | |
SERVICE_START_PENDING = 0x00000002, | |
SERVICE_STOP_PENDING = 0x00000003, | |
SERVICE_RUNNING = 0x00000004, | |
SERVICE_CONTINUE_PENDING = 0x00000005, | |
SERVICE_PAUSE_PENDING = 0x00000006, | |
SERVICE_PAUSED = 0x00000007, | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
public struct ServiceStatus | |
{ | |
public long dwServiceType; | |
public ServiceState dwCurrentState; | |
public long dwControlsAccepted; | |
public long dwWin32ExitCode; | |
public long dwServiceSpecificExitCode; | |
public long dwCheckPoint; | |
public long dwWaitHint; | |
}; | |
public partial class WorkstationLockdownService : ServiceBase | |
{ | |
private const string EventLogName = "WorkstationLockdown"; | |
private const string EventLogSource = "WorkstationLockdownService"; | |
private const double PollingInterval = 60000; | |
private const long StatusWaitHint = 10000; | |
/// <summary> | |
/// The Service Control Manager uses the dwWaitHint and dwCheckpoint members of the SERVICE_STATUS structure to determine how much time to wait for a Windows Service to start or shut down. | |
/// </summary> | |
/// <remarks> | |
/// If OnStart and OnStop methods run long, service can request more time by calling SetServiceStatus again with an incremented dwCheckPoint value. | |
/// </remarks> | |
/// <param name="handle"></param> | |
/// <param name="serviceStatus"></param> | |
/// <returns></returns> | |
[DllImport("advapi32.dll", SetLastError = true)] | |
private static extern bool SetServiceStatus(IntPtr handle, ref ServiceStatus serviceStatus); | |
/// <summary> | |
/// | |
/// </summary> | |
/// <remarks> | |
/// Constructor arguments allow specifying an alternate log name (else, default EventLogName is used) | |
/// </remarks> | |
/// <param name="args">Optional list of arguments passed to command line</param> | |
public WorkstationLockdownService(string[] args) | |
{ | |
InitializeComponent(); | |
CanHandleSessionChangeEvent = true; | |
var source = args.Any() && !string.IsNullOrEmpty(args[0]) ? args[0] : EventLogSource; | |
EventLog.DeleteEventSource(source); | |
// TODO: Do we need to also call CreateEventSource when alternate log names are specified on the command line? | |
if (!EventLog.SourceExists(source)) | |
EventLog.CreateEventSource(source, EventLogName); | |
eventLog.Source = source; | |
eventLog.Log = EventLogName; | |
} | |
protected override void OnStart(string[] args) | |
{ | |
var status = new ServiceStatus | |
{ | |
dwCurrentState = ServiceState.SERVICE_START_PENDING, | |
dwWaitHint = StatusWaitHint | |
}; | |
SetServiceStatus(ServiceHandle, ref status); | |
eventLog.WriteEntry("Service started."); | |
var timer = new Timer(PollingInterval); | |
timer.Elapsed += Poll; | |
status.dwCurrentState = ServiceState.SERVICE_RUNNING; | |
SetServiceStatus(ServiceHandle, ref status); | |
} | |
/// <summary> | |
/// Handle session change event (i.e. screen lock/unlock). | |
/// </summary> | |
/// <remarks> | |
/// Requires CanHandleSessionChangeEvent = true | |
/// </remarks> | |
/// <param name="e"></param> | |
protected override void OnSessionChange(SessionChangeDescription e) | |
{ | |
switch (e.Reason) | |
{ | |
case SessionChangeReason.SessionLock: | |
OnScreenLock(); | |
break; | |
case SessionChangeReason.SessionUnlock: | |
OnScreenUnlock(); | |
break; | |
} | |
} | |
/// <summary> | |
/// Disables network adapter on screen lock. | |
/// </summary> | |
private void OnScreenLock() | |
{ | |
// Disable network adapter | |
NetworkAdapterHelpers.DisableAll(); | |
} | |
/// <summary> | |
/// Re-enables network adapter on screen unlock. | |
/// </summary> | |
private void OnScreenUnlock() | |
{ | |
// Re-enable network adapter | |
NetworkAdapterHelpers.EnableAll(); | |
} | |
private void Poll(object sender, ElapsedEventArgs e) | |
{ | |
} | |
protected override void OnStop() | |
{ | |
eventLog.WriteEntry("Service stopped"); | |
} | |
protected override void OnContinue() | |
{ | |
eventLog.WriteEntry("Service resumed"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment