///<summary>Executes your service. If multiple services are defined in the assembly, it will run them all in separate threads.</summary> /// <param name="Args">The arguments passed in from the command line.</param> /// <param name="Types">An array of types we want to inspect for services.</param> public static void RunServices(string[] Args, Type[] Types) { Console.WriteLine("Service Installer"); //Reads in all the classes in the assembly and finds one that derives //from this class. If it finds one, it checks the attributes to see //if we should run it. If we should, we create an instance of it and //start it on its way... //Type[] types = a.GetTypes(); System.Collections.ArrayList alDispatchTables = new System.Collections.ArrayList(); List<ServiceBase> alServices = new List<ServiceBase>(); foreach(Type t in Types) { if (t.IsClass && t.BaseType != null && t.BaseType.Equals(typeof(ServiceBase))) { //Gets all the custom attributes of type ServiceAttribute in the class. object[] attributes = t.GetCustomAttributes(typeof(ServiceAttribute), true); foreach(ServiceAttribute info in attributes) { if (info.Run) { ServiceBase s = (ServiceBase)Activator.CreateInstance(t); alServices.Add(s); //Make sure we have a name set for this guy... if (string.IsNullOrWhiteSpace( s.Name)) throw new ServiceRuntimeException("A service was created without a name."); if (Args.Length == 0) { Console.WriteLine(); Console.WriteLine("{0} Service", s.Name); Console.WriteLine("=================================="); Console.WriteLine("Install"); Console.WriteLine("\t{0} i", System.AppDomain.CurrentDomain.FriendlyName); Console.WriteLine("Uninstall"); Console.WriteLine("\t{0} u", System.AppDomain.CurrentDomain.FriendlyName); Console.WriteLine("Interactive Mode"); Console.WriteLine("\t{0} c", System.AppDomain.CurrentDomain.FriendlyName); } bool isUacEnabled = UacHelper.IsUacEnabled; bool isUacElevated = UacHelper.IsProcessElevated; if (isUacEnabled && !isUacElevated) { Console.WriteLine( "Warning: UAC is enabled but not process is not elevated, some functionality is not possible"); ServicesAPI.SERVICE_TABLE_ENTRY entry = new ServicesAPI.SERVICE_TABLE_ENTRY(); entry.lpServiceName = info.Name; entry.lpServiceProc = new ServicesAPI.ServiceMainProc(s.baseServiceMain); alDispatchTables.Add(entry); s.Debug = false; } else { if (Args.Length > 0 && (Args[0].ToLower() == "u" || Args[0].ToLower() == "uninstall")) { //Nothing to uninstall if it's not installed... if (!IsServiceInstalled(info.Name)) break; if (!ServiceInstaller.Uninstall(info.Name)) throw new ServiceUninstallException("Unable to remove service \"" + info.DisplayName + "\""); if (!s.Uninstall()) throw new ServiceUninstallException("Service \"" + info.DisplayName + "\" was unable to uninstall itself correctly."); } else if (Args.Length > 0 && (Args[0].ToLower() == "i" || Args[0].ToLower() == "install")) { //Just install the service if we pass in "i" or "install"... //Always check to see if the service is installed and if it isn't, //then go ahead and install it... if (!IsServiceInstalled(info.Name)) { string[] envArgs = Environment.GetCommandLineArgs(); if (envArgs.Length > 0) { System.IO.FileInfo fi = new System.IO.FileInfo(envArgs[0]); if (!ServiceInstaller.Install(fi.FullName, info.Name, info.DisplayName, info.Description, info.ServiceType, info.ServiceAccessType, info.ServiceStartType, info.ServiceErrorControl)) throw new ServiceInstallException("Unable to install service \"" + info.DisplayName + "\""); if (!s.Install()) throw new ServiceInstallException("Service was not able to install itself correctly."); } } } else { //Always check to see if the service is installed and if it isn't, //then go ahead and install it... if (!IsServiceInstalled(info.Name)) { string[] envArgs = Environment.GetCommandLineArgs(); if (envArgs.Length > 0) { System.IO.FileInfo fi = new System.IO.FileInfo(envArgs[0]); if (!ServiceInstaller.Install(fi.FullName, info.Name, info.DisplayName, info.Description, info.ServiceType, info.ServiceAccessType, info.ServiceStartType, info.ServiceErrorControl)) throw new ServiceInstallException("Unable to install service \"" + info.DisplayName + "\""); if (!s.Install()) throw new ServiceInstallException("Service was not able to install itself correctly."); } } ServicesAPI.SERVICE_TABLE_ENTRY entry = new ServicesAPI.SERVICE_TABLE_ENTRY(); entry.lpServiceName = info.Name; entry.lpServiceProc = new ServicesAPI.ServiceMainProc(s.baseServiceMain); alDispatchTables.Add(entry); s.Debug = false; } } } break; //We can break b/c we only allow ONE instance of this attribute per object... } } } if (alDispatchTables.Count > 0) { //Add a null entry to tell the API it's the last entry in the table... ServicesAPI.SERVICE_TABLE_ENTRY entry = new ServicesAPI.SERVICE_TABLE_ENTRY(); entry.lpServiceName = null; entry.lpServiceProc = null; alDispatchTables.Add(entry); ServicesAPI.SERVICE_TABLE_ENTRY[] table = (ServicesAPI.SERVICE_TABLE_ENTRY[])alDispatchTables.ToArray(typeof(ServicesAPI.SERVICE_TABLE_ENTRY)); if (ServicesAPI.StartServiceCtrlDispatcher(table) == 0) { //There was an error. What was it? switch (Marshal.GetLastWin32Error()) { case ServicesAPI.ERROR_INVALID_DATA: throw new ServiceStartupException( "The specified dispatch table contains entries that are not in the proper format."); case ServicesAPI.ERROR_SERVICE_ALREADY_RUNNING: throw new ServiceStartupException("A service is already running."); case ServicesAPI.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT: //Executed when in Console Mode foreach (var s in alServices) { ServiceContainer sc = new ServiceContainer(s); s.Debug = true; s.args = Args; sc.Start(); } //throw new ServiceStartupException("A service is being run as a console application"); //"A service is being run as a console application. Try setting the Service attribute's \"Debug\" property to true if you're testing an application." //If we've started up as a console/windows app, then we'll get this error in which case we treat the program //like a normal app instead of a service and start it up in "debug" mode... break; default: throw new ServiceStartupException( "An unknown error occurred while starting up the service(s)."); } } else { //Service Mode DebugLogger.IsConsole = false; } } }
///<summary>Executes your service. If multiple services are defined in the assembly, it will run them all in separate threads.</summary> /// <param name="Args">The arguments passed in from the command line.</param> /// <param name="Types">An array of types we want to inspect for services.</param> public static void RunServices(string[] Args, Type[] Types) { Console.WriteLine("Service Installer"); //Reads in all the classes in the assembly and finds one that derives //from this class. If it finds one, it checks the attributes to see //if we should run it. If we should, we create an instance of it and //start it on its way... //Type[] types = a.GetTypes(); System.Collections.ArrayList alDispatchTables = new System.Collections.ArrayList(); List <ServiceBase> alServices = new List <ServiceBase>(); foreach (Type t in Types) { if (t.IsClass && t.BaseType != null && t.BaseType.Equals(typeof(ServiceBase))) { //Gets all the custom attributes of type ServiceAttribute in the class. object[] attributes = t.GetCustomAttributes(typeof(ServiceAttribute), true); foreach (ServiceAttribute info in attributes) { if (info.Run) { ServiceBase s = (ServiceBase)Activator.CreateInstance(t); alServices.Add(s); //Make sure we have a name set for this guy... if (string.IsNullOrWhiteSpace(s.Name)) { throw new ServiceRuntimeException("A service was created without a name."); } if (Args.Length == 0) { Console.WriteLine(); Console.WriteLine("{0} Service", s.Name); Console.WriteLine("=================================="); Console.WriteLine("Install"); Console.WriteLine("\t{0} i", System.AppDomain.CurrentDomain.FriendlyName); Console.WriteLine("Uninstall"); Console.WriteLine("\t{0} u", System.AppDomain.CurrentDomain.FriendlyName); Console.WriteLine("Interactive Mode"); Console.WriteLine("\t{0} c", System.AppDomain.CurrentDomain.FriendlyName); } bool isUacEnabled = UacHelper.IsUacEnabled; bool isUacElevated = UacHelper.IsProcessElevated; if (isUacEnabled && !isUacElevated) { Console.WriteLine( "Warning: UAC is enabled but not process is not elevated, some functionality is not possible"); ServicesAPI.SERVICE_TABLE_ENTRY entry = new ServicesAPI.SERVICE_TABLE_ENTRY(); entry.lpServiceName = info.Name; entry.lpServiceProc = new ServicesAPI.ServiceMainProc(s.baseServiceMain); alDispatchTables.Add(entry); s.Debug = false; } else { if (Args.Length > 0 && (Args[0].ToLower() == "u" || Args[0].ToLower() == "uninstall")) { //Nothing to uninstall if it's not installed... if (!IsServiceInstalled(info.Name)) { break; } if (!ServiceInstaller.Uninstall(info.Name)) { throw new ServiceUninstallException("Unable to remove service \"" + info.DisplayName + "\""); } if (!s.Uninstall()) { throw new ServiceUninstallException("Service \"" + info.DisplayName + "\" was unable to uninstall itself correctly."); } } else if (Args.Length > 0 && (Args[0].ToLower() == "i" || Args[0].ToLower() == "install")) { //Just install the service if we pass in "i" or "install"... //Always check to see if the service is installed and if it isn't, //then go ahead and install it... if (!IsServiceInstalled(info.Name)) { string[] envArgs = Environment.GetCommandLineArgs(); if (envArgs.Length > 0) { System.IO.FileInfo fi = new System.IO.FileInfo(envArgs[0]); if (!ServiceInstaller.Install(fi.FullName, info.Name, info.DisplayName, info.Description, info.ServiceType, info.ServiceAccessType, info.ServiceStartType, info.ServiceErrorControl)) { throw new ServiceInstallException("Unable to install service \"" + info.DisplayName + "\""); } if (!s.Install()) { throw new ServiceInstallException("Service was not able to install itself correctly."); } } } } else { //Always check to see if the service is installed and if it isn't, //then go ahead and install it... if (!IsServiceInstalled(info.Name)) { string[] envArgs = Environment.GetCommandLineArgs(); if (envArgs.Length > 0) { System.IO.FileInfo fi = new System.IO.FileInfo(envArgs[0]); if (!ServiceInstaller.Install(fi.FullName, info.Name, info.DisplayName, info.Description, info.ServiceType, info.ServiceAccessType, info.ServiceStartType, info.ServiceErrorControl)) { throw new ServiceInstallException("Unable to install service \"" + info.DisplayName + "\""); } if (!s.Install()) { throw new ServiceInstallException("Service was not able to install itself correctly."); } } } ServicesAPI.SERVICE_TABLE_ENTRY entry = new ServicesAPI.SERVICE_TABLE_ENTRY(); entry.lpServiceName = info.Name; entry.lpServiceProc = new ServicesAPI.ServiceMainProc(s.baseServiceMain); alDispatchTables.Add(entry); s.Debug = false; } } } break; //We can break b/c we only allow ONE instance of this attribute per object... } } } if (alDispatchTables.Count > 0) { //Add a null entry to tell the API it's the last entry in the table... ServicesAPI.SERVICE_TABLE_ENTRY entry = new ServicesAPI.SERVICE_TABLE_ENTRY(); entry.lpServiceName = null; entry.lpServiceProc = null; alDispatchTables.Add(entry); ServicesAPI.SERVICE_TABLE_ENTRY[] table = (ServicesAPI.SERVICE_TABLE_ENTRY[])alDispatchTables.ToArray(typeof(ServicesAPI.SERVICE_TABLE_ENTRY)); if (ServicesAPI.StartServiceCtrlDispatcher(table) == 0) { //There was an error. What was it? switch (Marshal.GetLastWin32Error()) { case ServicesAPI.ERROR_INVALID_DATA: throw new ServiceStartupException( "The specified dispatch table contains entries that are not in the proper format."); case ServicesAPI.ERROR_SERVICE_ALREADY_RUNNING: throw new ServiceStartupException("A service is already running."); case ServicesAPI.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT: //Executed when in Console Mode foreach (var s in alServices) { ServiceContainer sc = new ServiceContainer(s); s.Debug = true; s.args = Args; sc.Start(); } //throw new ServiceStartupException("A service is being run as a console application"); //"A service is being run as a console application. Try setting the Service attribute's \"Debug\" property to true if you're testing an application." //If we've started up as a console/windows app, then we'll get this error in which case we treat the program //like a normal app instead of a service and start it up in "debug" mode... break; default: throw new ServiceStartupException( "An unknown error occurred while starting up the service(s)."); } } else { //Service Mode DebugLogger.IsConsole = false; } } }