Skip to content

Instantly share code, notes, and snippets.

@darinkes
Created December 4, 2012 14:41
Show Gist options
  • Save darinkes/4204627 to your computer and use it in GitHub Desktop.
Save darinkes/4204627 to your computer and use it in GitHub Desktop.
ServiceBase Session Events for Topshelf
diff -NurP Topshelf/src/Topshelf/Configuration/Builders/ControlServiceBuilder.cs Topshelf/Configuration/Builders/ControlServiceBuilder.cs
--- Topshelf/src/Topshelf/Configuration/Builders/ControlServiceBuilder.cs Wed Nov 28 13:21:02 2012
+++ Topshelf/Configuration/Builders/ControlServiceBuilder.cs Thu Nov 29 08:32:37 2012
@@ -14,6 +14,7 @@
{
using System;
using Runtime;
+ using System.ServiceProcess;
public class ControlServiceBuilder<T> :
ServiceBuilder
@@ -100,6 +101,11 @@
{
serviceShutdown.Shutdown(hostControl);
}
+ }
+
+ public void SessionEvent(HostControl hostControl, SessionChangeReason reason, int id)
+ {
+ // nothing to control
}
}
}
diff -NurP Topshelf/src/Topshelf/Configuration/Builders/DelegateServiceBuilder.cs Topshelf/Configuration/Builders/DelegateServiceBuilder.cs
--- Topshelf/src/Topshelf/Configuration/Builders/DelegateServiceBuilder.cs Wed Nov 28 13:21:02 2012
+++ Topshelf/Configuration/Builders/DelegateServiceBuilder.cs Thu Nov 29 08:32:37 2012
@@ -14,6 +14,7 @@
{
using System;
using Runtime;
+ using System.ServiceProcess;
public class DelegateServiceBuilder<T> :
ServiceBuilder
@@ -26,10 +27,11 @@
readonly Action<T, HostControl> _shutdown;
readonly Func<T, HostControl, bool> _start;
readonly Func<T, HostControl, bool> _stop;
+ readonly Action<T, HostControl, SessionChangeReason, int> _sessionevent;
public DelegateServiceBuilder(ServiceFactory<T> serviceFactory, Func<T, HostControl, bool> start,
Func<T, HostControl, bool> stop, Func<T, HostControl, bool> pause, Func<T, HostControl, bool> @continue,
- Action<T, HostControl> shutdown, ServiceEvents serviceEvents)
+ Action<T, HostControl> shutdown, Action<T, HostControl, SessionChangeReason, int> sessionevent, ServiceEvents serviceEvents)
{
_serviceFactory = serviceFactory;
_start = start;
@@ -37,6 +39,7 @@
_pause = pause;
_continue = @continue;
_shutdown = shutdown;
+ _sessionevent = sessionevent;
_serviceEvents = serviceEvents;
}
@@ -46,7 +49,7 @@
{
T service = _serviceFactory(settings);
- return new DelegateServiceHandle(service, _start, _stop, _pause, _continue, _shutdown, _serviceEvents);
+ return new DelegateServiceHandle(service, _start, _stop, _pause, _continue, _shutdown, _sessionevent, _serviceEvents);
}
catch (Exception ex)
{
@@ -64,10 +67,11 @@
readonly Action<T, HostControl> _shutdown;
readonly Func<T, HostControl, bool> _start;
readonly Func<T, HostControl, bool> _stop;
+ readonly Action<T, HostControl, SessionChangeReason, int> _sessionevent;
public DelegateServiceHandle(T service, Func<T, HostControl, bool> start, Func<T, HostControl, bool> stop,
Func<T, HostControl, bool> pause, Func<T, HostControl, bool> @continue, Action<T, HostControl> shutdown,
- ServiceEvents serviceEvents)
+ Action<T, HostControl, SessionChangeReason, int> sessionevent, ServiceEvents serviceEvents)
{
_service = service;
_start = start;
@@ -75,6 +79,7 @@
_pause = pause;
_continue = @continue;
_shutdown = shutdown;
+ _sessionevent = sessionevent;
_serviceEvents = serviceEvents;
}
@@ -95,6 +100,12 @@
_serviceEvents.AfterStart(hostControl);
}
return started;
+ }
+
+ public void SessionEvent(HostControl hostControl, SessionChangeReason reason, int id)
+ {
+ if (_sessionevent != null)
+ _sessionevent(_service, hostControl, reason, id);
}
public bool Pause(HostControl hostControl)
diff -NurP Topshelf/src/Topshelf/Configuration/HostConfigurators/HostConfigurator.cs Topshelf/Configuration/HostConfigurators/HostConfigurator.cs
--- Topshelf/src/Topshelf/Configuration/HostConfigurators/HostConfigurator.cs Wed Nov 28 13:21:02 2012
+++ Topshelf/Configuration/HostConfigurators/HostConfigurator.cs Tue Dec 4 13:39:44 2012
@@ -46,6 +46,11 @@
void EnablePauseAndContinue();
/// <summary>
+ /// Enable support for session change events.
+ /// </summary>
+ void EnableHandleSessionChangeEvent();
+
+ /// <summary>
/// Enable support for service shutdown (signaled by the host OS)
/// </summary>
void EnableShutdown();
diff -NurP Topshelf/src/Topshelf/Configuration/HostConfigurators/HostConfiguratorImpl.cs Topshelf/Configuration/HostConfigurators/HostConfiguratorImpl.cs
--- Topshelf/src/Topshelf/Configuration/HostConfigurators/HostConfiguratorImpl.cs Wed Nov 28 13:21:02 2012
+++ Topshelf/Configuration/HostConfigurators/HostConfiguratorImpl.cs Thu Nov 29 08:32:37 2012
@@ -113,6 +113,11 @@
_settings.CanPauseAndContinue = true;
}
+ public void EnableHandleSessionChangeEvent()
+ {
+ _settings.CanHandleSessionChangeEvent = true;
+ }
+
public void EnableShutdown()
{
_settings.CanShutdown = true;
diff -NurP Topshelf/src/Topshelf/Configuration/ServiceConfiguratorExtensions.cs Topshelf/Configuration/ServiceConfiguratorExtensions.cs
--- Topshelf/src/Topshelf/Configuration/ServiceConfiguratorExtensions.cs Wed Nov 28 13:21:02 2012
+++ Topshelf/Configuration/ServiceConfiguratorExtensions.cs Thu Nov 29 08:32:37 2012
@@ -14,6 +14,7 @@
{
using System;
using ServiceConfigurators;
+ using System.ServiceProcess;
public static class ServiceConfiguratorExtensions
{
@@ -101,6 +102,21 @@
return true;
});
+
+ return configurator;
+ }
+
+ public static ServiceConfigurator<T> WhenSessionEvent<T>(this ServiceConfigurator<T> configurator,
+ Action<T, SessionChangeReason, int> callback)
+ where T : class
+ {
+ if (configurator == null)
+ throw new ArgumentNullException("configurator");
+
+ configurator.WhenSessionEvent((service, control, reason, id) =>
+ {
+ callback(service, reason, id);
+ });
return configurator;
}
diff -NurP Topshelf/src/Topshelf/Configuration/ServiceConfigurators/DelegateServiceConfigurator.cs Topshelf/Configuration/ServiceConfigurators/DelegateServiceConfigurator.cs
--- Topshelf/src/Topshelf/Configuration/ServiceConfigurators/DelegateServiceConfigurator.cs Wed Nov 28 13:21:02 2012
+++ Topshelf/Configuration/ServiceConfigurators/DelegateServiceConfigurator.cs Thu Nov 29 08:32:37 2012
@@ -17,6 +17,7 @@
using Builders;
using Configurators;
using Runtime;
+ using System.ServiceProcess;
public class DelegateServiceConfigurator<T> :
ServiceConfiguratorBase,
@@ -35,6 +36,9 @@
Func<T, HostControl, bool> _start;
Func<T, HostControl, bool> _stop;
+ Action<T, HostControl, SessionChangeReason, int> _sessionevent;
+ bool _sessioneventConfigured;
+
public IEnumerable<ValidateResult> Validate()
{
if (_factory == null)
@@ -50,6 +54,8 @@
yield return this.Failure("Pause", "must not be null if continue is specified");
if (_shutdownConfigured && _shutdown == null)
yield return this.Failure("Shutdown", "must not be null if shutdown is allowed");
+ if (_sessioneventConfigured && _sessionevent == null)
+ yield return this.Failure("SessionEvent", "must not be null if SessionEvent is allowed");
}
public void ConstructUsing(ServiceFactory<T> serviceFactory)
@@ -85,9 +91,15 @@
_shutdown = shutdown;
}
+ public void WhenSessionEvent(Action<T, HostControl, SessionChangeReason, int> sessionevent)
+ {
+ _sessioneventConfigured = true;
+ _sessionevent = sessionevent;
+ }
+
public ServiceBuilder Build()
{
- var serviceBuilder = new DelegateServiceBuilder<T>(_factory, _start, _stop, _pause, _continue, _shutdown,
+ var serviceBuilder = new DelegateServiceBuilder<T>(_factory, _start, _stop, _pause, _continue, _shutdown, _sessionevent,
ServiceEvents);
return serviceBuilder;
}
diff -NurP Topshelf/src/Topshelf/Configuration/ServiceConfigurators/ServiceConfigurator.cs Topshelf/Configuration/ServiceConfigurators/ServiceConfigurator.cs
--- Topshelf/src/Topshelf/Configuration/ServiceConfigurators/ServiceConfigurator.cs Wed Nov 28 13:21:02 2012
+++ Topshelf/Configuration/ServiceConfigurators/ServiceConfigurator.cs Thu Nov 29 08:32:37 2012
@@ -14,6 +14,7 @@
{
using System;
using Runtime;
+ using System.ServiceProcess;
public interface ServiceConfigurator
{
@@ -48,5 +49,6 @@
void WhenPaused(Func<T, HostControl, bool> pause);
void WhenContinued(Func<T, HostControl, bool> @continue);
void WhenShutdown(Action<T, HostControl> shutdown);
+ void WhenSessionEvent(Action<T, HostControl, SessionChangeReason, int> sessionevent);
}
}
diff -NurP Topshelf/src/Topshelf/Hosts/ConsoleRunHost.cs Topshelf/Hosts/ConsoleRunHost.cs
--- Topshelf/src/Topshelf/Hosts/ConsoleRunHost.cs Wed Nov 28 13:21:02 2012
+++ Topshelf/Hosts/ConsoleRunHost.cs Tue Dec 4 13:40:26 2012
@@ -20,6 +20,9 @@
#endif
using Logging;
using Runtime;
+ using System.ServiceProcess;
+ using Microsoft.Win32;
+ using System.Diagnostics;
public class ConsoleRunHost :
Host,
@@ -44,6 +47,19 @@
_settings = settings;
_environment = environment;
_serviceHandle = serviceHandle;
+
+ if (_settings.CanHandleSessionChangeEvent)
+ {
+ SystemEvents.SessionSwitch += new SessionSwitchEventHandler(OnSessionChange);
+ }
+ }
+
+ void OnSessionChange(object sender, SessionSwitchEventArgs e)
+ {
+ int sessionid = Process.GetCurrentProcess().SessionId;
+
+ // We can cast the reason directly, the enums are identical
+ _serviceHandle.SessionEvent(this, (SessionChangeReason)e.Reason, sessionid);
}
public TopshelfExitCode Run()
diff -NurP Topshelf/src/Topshelf/Hosts/InstallHost.cs Topshelf/Hosts/InstallHost.cs
--- Topshelf/src/Topshelf/Hosts/InstallHost.cs Wed Nov 28 13:21:02 2012
+++ Topshelf/Hosts/InstallHost.cs Thu Nov 29 08:32:37 2012
@@ -146,6 +146,11 @@
get { return _settings.CanPauseAndContinue; }
}
+ public bool CanHandleSessionChangeEvent
+ {
+ get { return _settings.CanHandleSessionChangeEvent; }
+ }
+
public bool CanShutdown
{
get { return _settings.CanShutdown; }
diff -NurP Topshelf/src/Topshelf/Runtime/HostSettings.cs Topshelf/Runtime/HostSettings.cs
--- Topshelf/src/Topshelf/Runtime/HostSettings.cs Wed Nov 28 13:21:02 2012
+++ Topshelf/Runtime/HostSettings.cs Tue Dec 4 13:39:44 2012
@@ -49,6 +49,11 @@
bool CanPauseAndContinue { get; }
/// <summary>
+ /// True if the service can handle the session change event
+ /// </summary>
+ bool CanHandleSessionChangeEvent { get; }
+
+ /// <summary>
/// True if the service can handle the shutdown event
/// </summary>
bool CanShutdown { get; }
diff -NurP Topshelf/src/Topshelf/Runtime/ServiceHandle.cs Topshelf/Runtime/ServiceHandle.cs
--- Topshelf/src/Topshelf/Runtime/ServiceHandle.cs Wed Nov 28 13:21:02 2012
+++ Topshelf/Runtime/ServiceHandle.cs Tue Dec 4 13:39:44 2012
@@ -13,6 +13,7 @@
namespace Topshelf.Runtime
{
using System;
+ using System.ServiceProcess;
/// <summary>
/// A handle to a service being hosted by the Host
@@ -53,5 +54,11 @@
/// </summary>
/// <param name="hostControl"></param>
void Shutdown(HostControl hostControl);
+
+ /// <summary>Handles the session change event</summary>
+ /// <param name="hostControl"></param>
+ /// <param name="reason">The change reason.</param>
+ /// <param name="id">The session id.</param>
+ void SessionEvent(HostControl hostControl, SessionChangeReason reason, int id);
}
}
diff -NurP Topshelf/src/Topshelf/Runtime/Windows/WindowsHostSettings.cs Topshelf/Runtime/Windows/WindowsHostSettings.cs
--- Topshelf/src/Topshelf/Runtime/Windows/WindowsHostSettings.cs Wed Nov 28 13:21:02 2012
+++ Topshelf/Runtime/Windows/WindowsHostSettings.cs Thu Nov 29 08:32:37 2012
@@ -96,5 +96,7 @@
public bool CanPauseAndContinue { get; set; }
public bool CanShutdown { get; set; }
+
+ public bool CanHandleSessionChangeEvent { get; set; }
}
}
diff -NurP Topshelf/src/Topshelf/Runtime/Windows/WindowsServiceHost.cs Topshelf/Runtime/Windows/WindowsServiceHost.cs
--- Topshelf/src/Topshelf/Runtime/Windows/WindowsServiceHost.cs Tue Dec 4 14:34:51 2012
+++ Topshelf/Runtime/Windows/WindowsServiceHost.cs Tue Dec 4 13:39:44 2012
@@ -46,6 +46,14 @@
CanPauseAndContinue = settings.CanPauseAndContinue;
CanShutdown = settings.CanShutdown;
+ CanHandleSessionChangeEvent = settings.CanHandleSessionChangeEvent;
+ }
+
+ protected override void OnSessionChange(SessionChangeDescription changeDescription)
+ {
+ _serviceHandle.SessionEvent(this, changeDescription.Reason, changeDescription.SessionId);
+
+ base.OnSessionChange(changeDescription);
}
public TopshelfExitCode Run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment