Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/origin/BUG-4264-TVService_ignor…
Browse files Browse the repository at this point in the history
…es_shutdown'
  • Loading branch information
Sebastiii committed Apr 1, 2013
2 parents 5029157 + 3ccc969 commit 62dda43
Showing 1 changed file with 79 additions and 15 deletions.
94 changes: 79 additions & 15 deletions TvEngine3/TVLibrary/TvService/Service1.cs
Expand Up @@ -25,6 +25,7 @@
using System.Configuration; using System.Configuration;
using System.Configuration.Install; using System.Configuration.Install;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection;
using System.Security.Principal; using System.Security.Principal;
using System.ServiceProcess; using System.ServiceProcess;
using System.Threading; using System.Threading;
Expand All @@ -49,11 +50,25 @@ public partial class Service1 : ServiceBase
private Thread _tvServiceThread = null; private Thread _tvServiceThread = null;
private static Thread _unhandledExceptionInThread = null; private static Thread _unhandledExceptionInThread = null;


const int SERVICE_ACCEPT_PRESHUTDOWN = 0x100; // not supported on Windows XP
const int SERVICE_CONTROL_PRESHUTDOWN = 0xf; // not supported on Windows XP

/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Service1"/> class. /// Initializes a new instance of the <see cref="Service1"/> class.
/// </summary> /// </summary>
public Service1() public Service1()
{ {
if (Environment.OSVersion.Version.Major >= 6)
{
// Enable pre-shutdown notification by accessing the ServiceBase class's internals through .NET reflection (code by Siva Chandran P)
FieldInfo acceptedCommandsFieldInfo = typeof(ServiceBase).GetField("acceptedCommands", BindingFlags.Instance | BindingFlags.NonPublic);
if (acceptedCommandsFieldInfo != null)
{
int value = (int)acceptedCommandsFieldInfo.GetValue(this);
acceptedCommandsFieldInfo.SetValue(this, value | SERVICE_ACCEPT_PRESHUTDOWN);
}
}

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
InitializeComponent(); InitializeComponent();
} }
Expand Down Expand Up @@ -107,7 +122,7 @@ private static void Main(string[] args)
ti.Installers.Add(mi); ti.Installers.Add(mi);
String path = String.Format("/assemblypath={0}", String path = String.Format("/assemblypath={0}",
System.Reflection.Assembly.GetExecutingAssembly().Location); System.Reflection.Assembly.GetExecutingAssembly().Location);
String[] cmdline = {path}; String[] cmdline = { path };
InstallContext ctx = new InstallContext("", cmdline); InstallContext ctx = new InstallContext("", cmdline);
ti.Context = ctx; ti.Context = ctx;
ti.Install(new Hashtable()); ti.Install(new Hashtable());
Expand All @@ -120,7 +135,7 @@ private static void Main(string[] args)
ti.Installers.Add(mi); ti.Installers.Add(mi);
String path = String.Format("/assemblypath={0}", String path = String.Format("/assemblypath={0}",
System.Reflection.Assembly.GetExecutingAssembly().Location); System.Reflection.Assembly.GetExecutingAssembly().Location);
String[] cmdline = {path}; String[] cmdline = { path };
InstallContext ctx = new InstallContext("", cmdline); InstallContext ctx = new InstallContext("", cmdline);
ti.Context = ctx; ti.Context = ctx;
ti.Uninstall(null); ti.Uninstall(null);
Expand All @@ -131,7 +146,7 @@ private static void Main(string[] args)
if (opt != null && opt.ToUpperInvariant() == "/DEBUG") if (opt != null && opt.ToUpperInvariant() == "/DEBUG")
{ {
Service1 s = new Service1(); Service1 s = new Service1();
s.DoStart(new string[] {"/DEBUG"}); s.DoStart(new string[] { "/DEBUG" });
do do
{ {
Thread.Sleep(100); Thread.Sleep(100);
Expand All @@ -144,7 +159,8 @@ private static void Main(string[] args)
// //
// ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()}; // ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()};
// //
ServiceBase[] ServicesToRun = new ServiceBase[] {new Service1()}; ServiceBase[] ServicesToRun = new ServiceBase[] { new Service1() };
ServicesToRun[0].CanShutdown = true; // Allow OnShutdown()
ServiceBase.Run(ServicesToRun); ServiceBase.Run(ServicesToRun);
} }


Expand Down Expand Up @@ -282,11 +298,34 @@ protected override void OnStop()
_tvServiceThread = null; _tvServiceThread = null;
} }
} }

/// <summary>
/// When implemented in a derived class, executes when the system is shutting down. Specifies what should occur immediately prior to the system shutting down.
/// </summary>
protected override void OnShutdown()
{
OnStop();
}

/// <summary>
/// When implemented in a derived class, executes when the Service Control Manager (SCM) passes a custom command to the service. Specifies actions to take when a command with the specified parameter value occurs.
/// </summary>
/// <param name="command"></param>
protected override void OnCustomCommand(int command)
{
// Check for pre-shutdown notification (code by Siva Chandran P)
if (command == SERVICE_CONTROL_PRESHUTDOWN)
{
OnStop();
}
else
base.OnCustomCommand(command);
}
} }


public class TvServiceThread : IPowerEventHandler public class TvServiceThread : IPowerEventHandler
{ {
#region variables #region variables


private EventWaitHandle _InitializedEvent; private EventWaitHandle _InitializedEvent;
private static bool _started; private static bool _started;
Expand Down Expand Up @@ -661,7 +700,7 @@ private void StartRemoting()
try try
{ {
// create the object reference and make the singleton instance available // create the object reference and make the singleton instance available
RemotingServices.Marshal(_controller, "TvControl", typeof (IController)); RemotingServices.Marshal(_controller, "TvControl", typeof(IController));
RemoteControl.Clear(); RemoteControl.Clear();
} }
catch (Exception ex) catch (Exception ex)
Expand Down Expand Up @@ -773,14 +812,21 @@ private void StopPlugins()


public void OnStop() public void OnStop()
{ {
if (!Started) if (!_started)
return; return;

Log.WriteFile("TV Service: stopping"); Log.WriteFile("TV Service: stopping");


// Reset "Global\MPTVServiceInitializedEvent"
if (_InitializedEvent != null) if (_InitializedEvent != null)
{ {
_InitializedEvent.Reset(); _InitializedEvent.Reset();
} }

// Stop the plugins
StopPlugins();

// Stop remoting and deinit the TvController
StopRemoting(); StopRemoting();
RemoteControl.Clear(); RemoteControl.Clear();
if (_controller != null) if (_controller != null)
Expand All @@ -789,7 +835,7 @@ public void OnStop()
_controller = null; _controller = null;
} }


StopPlugins(); // Terminate the power event thread
if (_powerEventThreadId != 0) if (_powerEventThreadId != 0)
{ {
Log.Debug("TV Service: OnStop asking PowerEventThread to exit"); Log.Debug("TV Service: OnStop asking PowerEventThread to exit");
Expand All @@ -798,6 +844,7 @@ public void OnStop()
} }
_powerEventThreadId = 0; _powerEventThreadId = 0;
_powerEventThread = null; _powerEventThread = null;

_started = false; _started = false;
Log.WriteFile("TV Service: stopped"); Log.WriteFile("TV Service: stopped");
} }
Expand All @@ -813,39 +860,56 @@ public void OnStart()


Thread.CurrentThread.Name = "TVService"; Thread.CurrentThread.Name = "TVService";


// Log TvService start and versions
FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(Application.ExecutablePath); FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(Application.ExecutablePath);

Log.WriteFile("TVService v" + versionInfo.FileVersion + " is starting up on " + Log.WriteFile("TVService v" + versionInfo.FileVersion + " is starting up on " +
OSInfo.OSInfo.GetOSDisplayVersion()); OSInfo.OSInfo.GetOSDisplayVersion());


//Check for unsupported operating systems // Warn about unsupported operating systems
OSPrerequisites.OSPrerequisites.OsCheck(false); OSPrerequisites.OSPrerequisites.OsCheck(false);


// Start the power event thread
_powerEventThread = new Thread(PowerEventThread); _powerEventThread = new Thread(PowerEventThread);
_powerEventThread.Name = "PowerEventThread"; _powerEventThread.Name = "PowerEventThread";
_powerEventThread.IsBackground = true; _powerEventThread.IsBackground = true;
_powerEventThread.Start(); _powerEventThread.Start();

// Init the TvController and start remoting
_controller = new TVController(); _controller = new TVController();
_controller.Init(); _controller.Init();
StartRemoting();

// Start the plugins
StartPlugins(); StartPlugins();


StartRemoting(); // Set "Global\MPTVServiceInitializedEvent"
_started = true;
if (_InitializedEvent != null) if (_InitializedEvent != null)
{ {
_InitializedEvent.Set(); _InitializedEvent.Set();
} }
_started = true;
Log.Info("TV service: Started"); Log.Info("TV service: Started");

// Wait for termination
while (true) while (true)
{ {
Thread.Sleep(1000); Thread.Sleep(1000);
} }
} }
} }
catch (ThreadAbortException)
{
Log.Info("TvService is beeing stopped");
}
catch (Exception ex) catch (Exception ex)
{ {
//wait for thread to exit. eg. when stopping tvservice if (_started)
Log.Error("TvService OnStart failed : {0}", ex.ToString()); Log.Error("TvService terminated unexpectedly: {0}", ex.ToString());
else
Log.Error("TvService failed not start: {0}", ex.ToString());
}
finally
{
_started = true; // otherwise the onstop code will not complete. _started = true; // otherwise the onstop code will not complete.
OnStop(); OnStop();
} }
Expand Down

0 comments on commit 62dda43

Please sign in to comment.