Пример #1
0
        public unsafe void Install()
        {
            string username = Username;
            string password = Password;

            if (string.IsNullOrEmpty(username))
            {
                username = LocalServiceName;
            }

            if (ServiceCommandLine == null)
            {
                string processName    = Process.GetCurrentProcess().MainModule.FileName;
                string entryPointName = System.Reflection.Assembly.GetEntryAssembly().Location;
                string arguments      = ServiceName;

                // if process and entry point aren't the same then we are running hosted so pass
                // in the entrypoint as the first argument
                if (!string.Equals(processName, entryPointName, StringComparison.OrdinalIgnoreCase))
                {
                    arguments = $"\"{entryPointName}\" {arguments}";
                }

                ServiceCommandLine = $"\"{processName}\" {arguments}";
            }

            //Build servicesDependedOn string
            string servicesDependedOn = null;

            if (ServicesDependedOn.Length > 0)
            {
                StringBuilder buff = new StringBuilder();
                for (int i = 0; i < ServicesDependedOn.Length; ++i)
                {
                    //The servicesDependedOn need to be separated by a null
                    buff.Append(ServicesDependedOn[i]);
                    buff.Append('\0');
                }
                // an extra null at the end indicates end of list.
                buff.Append('\0');

                servicesDependedOn = buff.ToString();
            }

            // Open the service manager
            IntPtr serviceManagerHandle = Interop.Advapi32.OpenSCManager(null, null, Interop.Advapi32.ServiceControllerOptions.SC_MANAGER_ALL);
            IntPtr serviceHandle        = IntPtr.Zero;

            if (serviceManagerHandle == IntPtr.Zero)
            {
                throw new InvalidOperationException("Cannot open Service Control Manager");
            }

            try
            {
                // Install the service
                serviceHandle = Interop.Advapi32.CreateService(serviceManagerHandle, ServiceName,
                                                               DisplayName, Interop.Advapi32.ServiceAccessOptions.ACCESS_TYPE_ALL, Interop.Advapi32.ServiceTypeOptions.SERVICE_TYPE_WIN32_OWN_PROCESS,
                                                               (int)StartType, Interop.Advapi32.ServiceStartErrorModes.ERROR_CONTROL_NORMAL,
                                                               ServiceCommandLine, null, IntPtr.Zero, servicesDependedOn, username, password);

                if (serviceHandle == IntPtr.Zero)
                {
                    throw new Win32Exception("Cannot create service");
                }

                // A local variable in an unsafe method is already fixed -- so we don't need a "fixed { }" blocks to protect
                // across the p/invoke calls below.

                if (Description.Length != 0)
                {
                    Interop.Advapi32.SERVICE_DESCRIPTION serviceDesc = new Interop.Advapi32.SERVICE_DESCRIPTION();
                    serviceDesc.description = Marshal.StringToHGlobalUni(Description);
                    bool success = Interop.Advapi32.ChangeServiceConfig2(serviceHandle, Interop.Advapi32.ServiceConfigOptions.SERVICE_CONFIG_DESCRIPTION, ref serviceDesc);
                    Marshal.FreeHGlobal(serviceDesc.description);
                    if (!success)
                    {
                        throw new Win32Exception("Cannot set description");
                    }
                }

                // Start the service after creating it
                using (ServiceController svc = new ServiceController(ServiceName))
                {
                    if (svc.Status != ServiceControllerStatus.Running)
                    {
                        svc.Start();
                        svc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(30));
                    }
                }
            }
            finally
            {
                if (serviceHandle != IntPtr.Zero)
                {
                    Interop.Advapi32.CloseServiceHandle(serviceHandle);
                }

                Interop.Advapi32.CloseServiceHandle(serviceManagerHandle);
            }
        }
Пример #2
0
        // Install and start the test service, after starting any prerequisite services it depends on
        public unsafe void Install()
        {
            string username = Username;
            string password = Password;

            if (ServiceCommandLine == null)
            {
                string processName    = Process.GetCurrentProcess().MainModule.FileName;
                string entryPointName = System.Reflection.Assembly.GetEntryAssembly().Location;
                string arguments      = ServiceName;

                // if process and entry point aren't the same then we are running hosted so pass
                // in the entrypoint as the first argument
                if (!string.Equals(processName, entryPointName, StringComparison.OrdinalIgnoreCase))
                {
                    arguments = $"\"{entryPointName}\" {arguments}";
                }

                ServiceCommandLine = $"\"{processName}\" {arguments}";
            }

            // Build servicesDependedOn string
            // These are prerequisite services that must be started before this service
            string servicesDependedOn = null;

            if (ServicesDependedOn.Length > 0)
            {
                StringBuilder buff = new StringBuilder();
                for (int i = 0; i < ServicesDependedOn.Length; ++i)
                {
                    //The servicesDependedOn need to be separated by a null
                    buff.Append(ServicesDependedOn[i]);
                    buff.Append('\0');
                }
                // an extra null at the end indicates end of list.
                buff.Append('\0');

                servicesDependedOn = buff.ToString();
            }

            // Open the service manager
            using (var serviceManagerHandle = new SafeServiceHandle(Interop.Advapi32.OpenSCManager(null, null, Interop.Advapi32.ServiceControllerOptions.SC_MANAGER_ALL)))
            {
                if (serviceManagerHandle.IsInvalid)
                {
                    throw new InvalidOperationException("Cannot open Service Control Manager");
                }

                TestService.DebugTrace($"TestServiceInstaller: creating service '{ServiceName}' with prerequisite services {servicesDependedOn}");

                // Install the service
                using (var serviceHandle = new SafeServiceHandle(Interop.Advapi32.CreateService(serviceManagerHandle, ServiceName,
                                                                                                DisplayName, Interop.Advapi32.ServiceAccessOptions.ACCESS_TYPE_ALL, Interop.Advapi32.ServiceTypeOptions.SERVICE_WIN32_OWN_PROCESS,
                                                                                                (int)StartType, Interop.Advapi32.ServiceStartErrorModes.ERROR_CONTROL_NORMAL,
                                                                                                ServiceCommandLine, null, IntPtr.Zero, servicesDependedOn, username, password)))
                {
                    if (serviceHandle.IsInvalid)
                    {
                        int    errorCode    = Marshal.GetLastWin32Error();
                        string errorMessage = new Win32Exception(errorCode).Message;
                        throw new Win32Exception(errorCode, $"Cannot create service '{ServiceName}' with display name '{DisplayName}'. {errorMessage}");
                    }

                    // A local variable in an unsafe method is already fixed -- so we don't need a "fixed { }" blocks to protect
                    // across the p/invoke calls below.

                    if (Description.Length != 0)
                    {
                        Interop.Advapi32.SERVICE_DESCRIPTION serviceDesc = new Interop.Advapi32.SERVICE_DESCRIPTION();
                        serviceDesc.description = Marshal.StringToHGlobalUni(Description);
                        bool success = Interop.Advapi32.ChangeServiceConfig2(serviceHandle, Interop.Advapi32.ServiceConfigOptions.SERVICE_CONFIG_DESCRIPTION, ref serviceDesc);
                        Marshal.FreeHGlobal(serviceDesc.description);
                        if (!success)
                        {
                            int    errorCode    = Marshal.GetLastWin32Error();
                            string errorMessage = new Win32Exception(errorCode).Message;
                            throw new Win32Exception(errorCode, $"Cannot set description on '{ServiceName}' with display name '{DisplayName}'. {errorMessage}");
                        }
                    }

                    // Start the service after creating it
                    using (ServiceController svc = new ServiceController(ServiceName))
                    {
                        if (svc.Status != ServiceControllerStatus.Running)
                        {
                            TestService.DebugTrace($"TestServiceInstaller: instructing ServiceController to start service '{ServiceName}'");
                            svc.Start();
                            if (!ServiceName.StartsWith("PropagateExceptionFromOnStart"))
                            {
                                svc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(240));
                            }
                        }
                        else
                        {
                            TestService.DebugTrace($"TestServiceInstaller: service '{ServiceName}' already running");
                        }
                    }
                }
            }
        }