예제 #1
0
        /// <summary>
        /// Checks if serviceName is installed
        /// </summary>
        /// <param name="serviceName">the service name</param>
        /// <returns>true if installed, false if no access or isn't installed</returns>
        private static bool IsServiceInstalled(string serviceName)
        {
            bool isServiceInstalled;

            try
            {
                isServiceInstalled = ServiceInstaller.IsInstalled(serviceName);
            }
            catch (Exception ex)
            {
                Console.WriteLine(
                    "Unable to check if service is installed, this is usually because elevated privileges are needed");
#if DEBUG
                DebugLogger.WriteLine(ex);
#endif
                return(false);
            }
            return(isServiceInstalled);
        }
예제 #2
0
 ///<summary>Describes a new Win32 service.</summary>
 /// <param name="Name">The name of the service used in the service database.</param>
 /// <param name="DisplayName">The name of the service that will be displayed in the services snap-in.</param>
 /// <param name="Description">The description of the service that will be displayed in the service snap-in.</param>
 /// <param name="Run">Indicates if you want the service to run or not on program startup.</param>
 /// <param name="ServiceType">Indicates the type of service you will be running. By default this is "Default."</param>
 /// <param name="ServiceAccessType">Access to the service. Before granting the requested access, the system checks the access token of the calling process.</param>
 /// <param name="ServiceStartType">Service start options. By default this is "AutoStart."</param>
 /// <param name="ServiceErrorControl">Severity of the error, and action taken, if this service fails to start.</param>
 /// <param name="ServiceControls">The controls or actions the service responds to.</param>
 public ServiceAttribute(
     string Name, 
     string DisplayName = null, 
     string Description = null, 
     bool Run = true, 
     ServicesAPI.ServiceType ServiceType = ServicesAPI.ServiceType.SERVICE_WIN32_OWN_PROCESS, 
     ServiceInstaller.ServiceAccessType ServiceAccessType = ServiceInstaller.ServiceAccessType.SERVICE_ALL_ACCESS, 
     ServiceInstaller.ServiceStartType ServiceStartType = ServiceInstaller.ServiceStartType.SERVICE_AUTO_START, 
     ServiceInstaller.ServiceErrorControl ServiceErrorControl = ServiceInstaller.ServiceErrorControl.SERVICE_ERROR_NORMAL, 
     ServicesAPI.ControlsAccepted ServiceControls= ServicesAPI.ControlsAccepted.SERVICE_ACCEPT_ALL)
 {
     this.Name = Name;
     this.DisplayName = DisplayName ?? this.Name;
     this.Description = Description ?? this.Name;
     this.Run = Run;
     this.ServiceType = ServiceType;
     this.ServiceAccessType = ServiceAccessType;// ServiceInstaller.ServiceAccessType.SERVICE_ALL_ACCESS;
     this.ServiceStartType = ServiceStartType;
     this.ServiceErrorControl = ServiceErrorControl;
     this.ServiceControls = ServiceControls;
     this.LogName = "Services";
 }
예제 #3
0
        /// <summary>
        /// Creates a service object and adds it to the specified service control manager database.
        /// </summary>
        /// <param name="ServicePath">
        /// The fully qualified path to the service binary file. If the path contains a space, it must be quoted so that it is correctly interpreted. For example, "d:\\my share\\myservice.exe" should be specified as "\"d:\\my share\\myservice.exe\"".
        /// <para>The path can also include arguments for an auto-start service. For example, "d:\\myshare\\myservice.exe arg1 arg2". These arguments are passed to the service entry point (typically the main function).</para>
        /// <para>If you specify a path on another computer, the share must be accessible by the computer account of the local computer because this is the security context used in the remote call. However, this requirement allows any potential vulnerabilities in the remote computer to affect the local computer. Therefore, it is best to use a local file.</para>
        /// </param>
        /// <param name="Name">The name of the service to install. The maximum string length is 256 characters. The service control manager database preserves the case of the characters, but service name comparisons are always case insensitive. Forward-slash (/) and backslash (\) are not valid service name characters.</param>
        /// <param name="DisplayName">The display name to be used by user interface programs to identify the service. This string has a maximum length of 256 characters. The name is case-preserved in the service control manager. Display name comparisons are always case-insensitive.</param>
        /// <param name="Description">The description to be used by user interface programs</param>
        /// <param name="ServType">The service type.</param>
        /// <param name="ServAccessType"></param>
        /// <param name="ServStartType"></param>
        /// <param name="ServErrorControl"></param>
        /// <returns></returns>
        internal static bool Install(string ServicePath, string Name, string DisplayName, string Description, ServicesAPI.ServiceType ServType, ServiceInstaller.ServiceAccessType ServAccessType, ServiceInstaller.ServiceStartType ServStartType, ServiceInstaller.ServiceErrorControl ServErrorControl)
        {
            if (Name.Length > 256) throw new ServiceInstallException("The maximum length for a service name is 256 characters.");
            if (Name.IndexOf(@"\") >= 0 || Name.IndexOf(@"/") >= 0) throw new ServiceInstallException(@"Service names cannot contain \ or / characters.");
            if (DisplayName.Length > 256) throw new ServiceInstallException("The maximum length for a display name is 256 characters.");
            
            //The spec says that if a service's path has a space in it, then we must quote it...
            //if (ServicePath.IndexOf(" ") >= 0)
            //  ServicePath = "\"" + ServicePath + "\"";
            //ServicePath = ServicePath.Replace(@"\", @"\\");

            IntPtr sc_handle = IntPtr.Zero;
            IntPtr sv_handle = IntPtr.Zero;

            try
            {
                sc_handle = OpenSCManagerA(null, null, ServiceControlManagerAccessType.SC_MANAGER_CREATE_SERVICE);
                if (sc_handle == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                sv_handle = CreateService(sc_handle, Name, DisplayName, ServAccessType, ServType, ServStartType,
                    ServErrorControl, ServicePath, null, IntPtr.Zero, null, null, null);
                //IntPtr sv_handle = ServicesAPI.CreateService(sc_handle, Name, DisplayName, 0xF0000 | 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080 | 0x0100, 0x00000010, 0x00000002, 0x00000001, ServicePath, null, 0, null, null, null);
                if (sv_handle == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
                

                //Sets a service's description by adding a registry entry for it.
                if (!string.IsNullOrEmpty(Description))
                {
                    try
                    {
                        using (
                            Microsoft.Win32.RegistryKey serviceKey =
                                Microsoft.Win32.Registry.LocalMachine.OpenSubKey(
                                    @"System\CurrentControlSet\Services\" + Name, true))
                        {
                            if (serviceKey != null)
                            {
                                serviceKey.SetValue("Description", Description);
                            }
                            else
                            {
                                DebugLogger.WriteLine("Unable to find service in registry, can't set Description");
                            }
                        }
                    }
                    catch
                    {
                        return false;
                    }
                }

                return true;
            }
            catch
            {
                throw;
            }
            finally
            {
                if (sv_handle != IntPtr.Zero)
                {
                    CloseServiceHandle(sv_handle);
                }
                if (sc_handle != IntPtr.Zero)
                {
                    CloseServiceHandle(sc_handle);
                }
            }
        }
예제 #4
0
 internal static extern IntPtr CreateService(IntPtr scHandle,
     string lpSvcName,
     string lpDisplayName,
     ServiceInstaller.ServiceAccessType dwDesiredAccess,
     ServicesAPI.ServiceType dwServiceType,
     ServiceInstaller.ServiceStartType dwStartType,
     ServiceInstaller.ServiceErrorControl dwErrorControl,
     string lpPathName,
     string lpLoadOrderGroup,
     IntPtr lpdwTagId,
     string lpDependencies,
     string lpServiceStartName,
     string lpPassword);
예제 #5
0
        ///<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;
                }
            }
        }