ติดตั้งบริการ. windows windows โดยไม่มี InstallUtil.exe


166

ฉันมีบริการ windows .NET มาตรฐานที่เขียนด้วยภาษา C #

สามารถติดตั้งเองได้โดยไม่ต้องใช้ InstallUtil หรือไม่ ฉันควรใช้คลาสตัวติดตั้งบริการหรือไม่ ฉันจะใช้มันได้อย่างไร

ฉันต้องการโทรต่อไปนี้:

MyService.exe -install

และมันจะมีผลเช่นเดียวกับการโทร:

InstallUtil MyService.exe

1
ฉันเพิ่งเจอคำถามนี้ แต่คำตอบที่นี่ค่อนข้างล้าสมัย ตอนนี้ (ตั้งแต่ 2015 อย่างน้อย) เราก็สามารถใช้คำสั่ง SC ติดตั้ง Windows บริการตามที่อธิบายไว้ที่นี่stackoverflow.com/a/34220957/512993 คำเตือน: ฉันเขียนคำตอบว่า
Hoàng Long

คำตอบ:


158

ใช่ว่าเป็นไปได้อย่างเต็มที่ (เช่นฉันทำสิ่งนี้อย่างแน่นอน); คุณเพียงแค่ต้องการอ้างอิง dll ที่ถูกต้อง (System.ServiceProcess.dll) และเพิ่มคลาสตัวติดตั้ง ...

นี่คือตัวอย่าง:

[RunInstaller(true)]
public sealed class MyServiceInstallerProcess : ServiceProcessInstaller
{
    public MyServiceInstallerProcess()
    {
        this.Account = ServiceAccount.NetworkService;
    }
}

[RunInstaller(true)]
public sealed class MyServiceInstaller : ServiceInstaller
{
    public MyServiceInstaller()
    {
        this.Description = "Service Description";
        this.DisplayName = "Service Name";
        this.ServiceName = "ServiceName";
        this.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
    }
}

static void Install(bool undo, string[] args)
{
    try
    {
        Console.WriteLine(undo ? "uninstalling" : "installing");
        using (AssemblyInstaller inst = new AssemblyInstaller(typeof(Program).Assembly, args))
        {
            IDictionary state = new Hashtable();
            inst.UseNewContext = true;
            try
            {
                if (undo)
                {
                    inst.Uninstall(state);
                }
                else
                {
                    inst.Install(state);
                    inst.Commit(state);
                }
            }
            catch
            {
                try
                {
                    inst.Rollback(state);
                }
                catch { }
                throw;
            }
        }
    }
    catch (Exception ex)
    {
        Console.Error.WriteLine(ex.Message);
    }
}


5
@MarcGravell คุณควรใส่รหัสที่นี่เนื่องจากคำตอบนี้ไม่มีประโยชน์หากไม่ได้ใช้
Richard Szalay

@MarcGravell ในตัวอย่างที่เชื่อมโยงของคุณมีการกำหนดstatic void Install(bool undo, string[] args)นอกคลาส (etc) คุณช่วยอธิบายได้อย่างไรว่าคุณใช้สิ่งนี้อย่างไร
khargoosh

39

ดูที่เมธอดInstallHelperของคลาสManagedInstaller คุณสามารถติดตั้งบริการโดยใช้:

string[] args;
ManagedInstallerClass.InstallHelper(args);

นี่คือสิ่งที่ InstallUtil ทำ อาร์กิวเมนต์เหมือนกันกับ InstallUtil

ประโยชน์ของวิธีนี้คือมันไม่เกี่ยวข้องกับการล้อเล่นในรีจิสทรีและใช้กลไกเดียวกับ InstallUtil



13
เหตุใดคุณจึงแนะนำสิ่งนี้เมื่อเอกสารบอกว่านี่ไม่ได้หมายถึงรหัสผู้ใช้?
Leeks and Leaks

6
ฉันใช้วิธีการนี้เพราะ 1. มันง่าย 2. มันเป็นสิ่งที่InstallUtil3. คุณไม่จำเป็นต้องเปลี่ยนการติดตั้งเมื่อบน x86 / x64 4. มันไม่ได้เปลี่ยนไปในหลาย ๆ เวอร์ชันของ. Net - ถ้ามันทำ มันจะถูกเลือกในการทดสอบและฉันจะแก้ไขแล้ว
adrianbanks

19

คุณสามารถถอยกลับไปสู่การโทรแบบเก่าที่ดีของ WinAPI ได้แม้ว่าจำนวนงานที่เกี่ยวข้องนั้นไม่สำคัญ ไม่มีข้อกำหนดว่าจะติดตั้งบริการ. NET ผ่านกลไก. NET.

ติดตั้ง:

  • เปิดตัวจัดการบริการผ่าน OpenSCManagerเปิดตัวจัดการบริการผ่านทาง
  • โทรCreateServiceเพื่อลงทะเบียนบริการ
  • เลือกที่ChangeServiceConfig2จะโทรเพื่อตั้งคำอธิบาย
  • CloseServiceHandleปิดให้บริการและผู้จัดการบริการจับกับ

หากต้องการถอนการติดตั้ง:

  • OpenSCManagerเปิดตัวจัดการบริการผ่านทาง
  • OpenServiceเปิดใช้บริการ
  • ลบบริการโดยการเรียกที่จับส่งกลับโดยDeleteServiceOpenService
  • CloseServiceHandleปิดให้บริการและผู้จัดการบริการจับกับ

เหตุผลหลักที่ฉันชอบสิ่งนี้มากกว่าการใช้ServiceInstaller/ ServiceProcessInstallerคือคุณสามารถลงทะเบียนบริการกับอาร์กิวเมนต์บรรทัดคำสั่งที่กำหนดเองของคุณเอง ตัวอย่างเช่นคุณอาจลงทะเบียนเป็น"MyApp.exe -service"หากผู้ใช้เรียกใช้แอปของคุณโดยไม่มีข้อโต้แย้งใด ๆ คุณสามารถเสนอ UI เพื่อติดตั้ง / ลบบริการ

เปิดตัวสะท้อนแสงServiceInstallerสามารถกรอกรายละเอียดที่หายไปจากคำอธิบายสั้น ๆ นี้

PS ชัดเจนว่าสิ่งนี้จะไม่มี "ผลเหมือนกับการโทร: InstallUtil MyService.exe" - โดยเฉพาะคุณจะไม่สามารถถอนการติดตั้งโดยใช้ InstallUtil แต่ดูเหมือนว่านี่อาจไม่ใช่ข้อกำหนดที่เข้มงวดสำหรับคุณ


ขั้นตอนของคุณง่ายต่อการติดตาม googling พิเศษเล็ก ๆ น้อย ๆ เพื่อไปที่เอกสารMSDN WIN APIและสิ่งนี้ก็เขียนเอง!
Michael Plautz

9

นี่คือคลาสที่ฉันใช้เมื่อเขียนบริการ ฉันมักจะมีหน้าจอแบบโต้ตอบที่เกิดขึ้นเมื่อไม่มีการเรียกใช้บริการ จากนั้นฉันใช้ชั้นเรียนตามต้องการ อนุญาตให้มีอินสแตนซ์ที่มีชื่อหลายรายการบนเครื่องเดียวกัน - ได้จากฟิลด์ InstanceID

ตัวอย่างการโทร

  IntegratedServiceInstaller Inst = new IntegratedServiceInstaller();
  Inst.Install("MySvc", "My Sample Service", "Service that executes something",
                    _InstanceID,
// System.ServiceProcess.ServiceAccount.LocalService,      // this is more secure, but only available in XP and above and WS-2003 and above
  System.ServiceProcess.ServiceAccount.LocalSystem,       // this is required for WS-2000
  System.ServiceProcess.ServiceStartMode.Automatic);
  if (controller == null)
  {
    controller = new System.ServiceProcess.ServiceController(String.Format("MySvc_{0}", _InstanceID), ".");
                }
                if (controller.Status == System.ServiceProcess.ServiceControllerStatus.Running)
                {
                    Start_Stop.Text = "Stop Service";
                    Start_Stop_Debugging.Enabled = false;
                }
                else
                {
                    Start_Stop.Text = "Start Service";
                    Start_Stop_Debugging.Enabled = true;
                }

ชั้นเรียนของตัวเอง

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Microsoft.Win32;

namespace MySvc
{
    class IntegratedServiceInstaller
    {
        public void Install(String ServiceName, String DisplayName, String Description,
            String InstanceID,
            System.ServiceProcess.ServiceAccount Account, 
            System.ServiceProcess.ServiceStartMode StartMode)
        {
            //http://www.theblacksparrow.com/
            System.ServiceProcess.ServiceProcessInstaller ProcessInstaller = new System.ServiceProcess.ServiceProcessInstaller();
            ProcessInstaller.Account = Account;

            System.ServiceProcess.ServiceInstaller SINST = new System.ServiceProcess.ServiceInstaller();

            System.Configuration.Install.InstallContext Context = new System.Configuration.Install.InstallContext();
            string processPath = Process.GetCurrentProcess().MainModule.FileName;
            if (processPath != null && processPath.Length > 0)
            {
                System.IO.FileInfo fi = new System.IO.FileInfo(processPath);

                String path = String.Format("/assemblypath={0}", fi.FullName);
                String[] cmdline = { path };
                Context = new System.Configuration.Install.InstallContext("", cmdline);
            }

            SINST.Context = Context;
            SINST.DisplayName = String.Format("{0} - {1}", DisplayName, InstanceID);
            SINST.Description = String.Format("{0} - {1}", Description, InstanceID);
            SINST.ServiceName = String.Format("{0}_{1}", ServiceName, InstanceID);
            SINST.StartType = StartMode;
            SINST.Parent = ProcessInstaller;

            // http://bytes.com/forum/thread527221.html
            SINST.ServicesDependedOn = new String[] { "Spooler", "Netlogon", "Netman" };

            System.Collections.Specialized.ListDictionary state = new System.Collections.Specialized.ListDictionary();
            SINST.Install(state);

            // http://www.dotnet247.com/247reference/msgs/43/219565.aspx
            using (RegistryKey oKey = Registry.LocalMachine.OpenSubKey(String.Format(@"SYSTEM\CurrentControlSet\Services\{0}_{1}", ServiceName, InstanceID), true))
            {
                try
                {
                    Object sValue = oKey.GetValue("ImagePath");
                    oKey.SetValue("ImagePath", sValue);
                }
                catch (Exception Ex)
                {
                    System.Windows.Forms.MessageBox.Show(Ex.Message);
                }
            }

        }
        public void Uninstall(String ServiceName, String InstanceID)
        {
            //http://www.theblacksparrow.com/
            System.ServiceProcess.ServiceInstaller SINST = new System.ServiceProcess.ServiceInstaller();

            System.Configuration.Install.InstallContext Context = new System.Configuration.Install.InstallContext("c:\\install.log", null);
            SINST.Context = Context;
            SINST.ServiceName = String.Format("{0}_{1}", ServiceName, InstanceID);
            SINST.Uninstall(null);
        }
    }
}

มีอะไรเกี่ยวกับthedavejay.com 2012/05/4 ?
Kiquenet

สิ่งนี้ยังสามารถใช้ในการ "passively" ลงทะเบียนปฏิบัติการที่แตกต่างกันฉันเปลี่ยนชิ้นGetCurrentProcessส่วนด้วยพารามิเตอร์และใช้มันสำเร็จ ใช้งานได้ดี!
Cee McSharpface

_InstanceID คืออะไร
jjxtra

ฉันมีแอปพลิเคชันที่ฉันใช้บริการเดียวกันหลายชุดชี้ไปที่ฐานข้อมูลที่แตกต่างกัน ฉันแยกพวกมันด้วย ID อินสแตนซ์ซึ่งเก็บไว้ในไฟล์การกำหนดค่า ผู้เช่าหลายคนสำหรับการบริการ ...
Brad Bruce

5

ตัวอย่างข้างต้นไม่ได้ผลสำหรับฉันจริง ๆ และลิงก์ไปยังฟอรัมเป็นโซลูชัน # 1 น่ากลัวที่จะขุดผ่าน นี่คือคลาสที่ฉันเขียน (บางส่วน) และบิตอื่น ๆ ถูกรวมเข้ากับลิงก์นี้ที่ฉันพบว่าถูกฝังอยู่ที่ไหนสักแห่ง

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.ServiceProcess;
using System.Runtime.InteropServices;

namespace SystemControl {
    class Services {

#region "Environment Variables"
        public static string GetEnvironment(string name, bool ExpandVariables=true) {
            if ( ExpandVariables ) {
                return System.Environment.GetEnvironmentVariable( name );
            } else {
                return (string)Microsoft.Win32.Registry.LocalMachine.OpenSubKey( @"SYSTEM\CurrentControlSet\Control\Session Manager\Environment\" ).GetValue( name, "", Microsoft.Win32.RegistryValueOptions.DoNotExpandEnvironmentNames );
            }
        }

        public static void SetEnvironment( string name, string value ) {
            System.Environment.SetEnvironmentVariable(name, value);
        }
#endregion

#region "ServiceCalls Native"
        public static ServiceController[] List { get { return ServiceController.GetServices(); } }

        public static void Start( string serviceName, int timeoutMilliseconds ) {
            ServiceController service=new ServiceController( serviceName );
            try {
                TimeSpan timeout=TimeSpan.FromMilliseconds( timeoutMilliseconds );

                service.Start();
                service.WaitForStatus( ServiceControllerStatus.Running, timeout );
            } catch {
                // ...
            }
        }

        public static void Stop( string serviceName, int timeoutMilliseconds ) {
            ServiceController service=new ServiceController( serviceName );
            try {
                TimeSpan timeout=TimeSpan.FromMilliseconds( timeoutMilliseconds );

                service.Stop();
                service.WaitForStatus( ServiceControllerStatus.Stopped, timeout );
            } catch {
                // ...
            }
        }

        public static void Restart( string serviceName, int timeoutMilliseconds ) {
            ServiceController service=new ServiceController( serviceName );
            try {
                int millisec1=Environment.TickCount;
                TimeSpan timeout=TimeSpan.FromMilliseconds( timeoutMilliseconds );

                service.Stop();
                service.WaitForStatus( ServiceControllerStatus.Stopped, timeout );

                // count the rest of the timeout
                int millisec2=Environment.TickCount;
                timeout=TimeSpan.FromMilliseconds( timeoutMilliseconds-( millisec2-millisec1 ) );

                service.Start();
                service.WaitForStatus( ServiceControllerStatus.Running, timeout );
            } catch {
                // ...
            }
        }

        public static bool IsInstalled( string serviceName ) {
            // get list of Windows services
            ServiceController[] services=ServiceController.GetServices();

            // try to find service name
            foreach ( ServiceController service in services ) {
                if ( service.ServiceName==serviceName )
                    return true;
            }
            return false;
        }
#endregion

#region "ServiceCalls API"
        private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
        private const int SERVICE_WIN32_OWN_PROCESS = 0x00000010;

        [Flags]
        public enum ServiceManagerRights {
            Connect = 0x0001,
            CreateService = 0x0002,
            EnumerateService = 0x0004,
            Lock = 0x0008,
            QueryLockStatus = 0x0010,
            ModifyBootConfig = 0x0020,
            StandardRightsRequired = 0xF0000,
            AllAccess = (StandardRightsRequired | Connect | CreateService |
            EnumerateService | Lock | QueryLockStatus | ModifyBootConfig)
        }

        [Flags]
        public enum ServiceRights {
            QueryConfig = 0x1,
            ChangeConfig = 0x2,
            QueryStatus = 0x4,
            EnumerateDependants = 0x8,
            Start = 0x10,
            Stop = 0x20,
            PauseContinue = 0x40,
            Interrogate = 0x80,
            UserDefinedControl = 0x100,
            Delete = 0x00010000,
            StandardRightsRequired = 0xF0000,
            AllAccess = (StandardRightsRequired | QueryConfig | ChangeConfig |
            QueryStatus | EnumerateDependants | Start | Stop | PauseContinue |
            Interrogate | UserDefinedControl)
        }

        public enum ServiceBootFlag {
            Start = 0x00000000,
            SystemStart = 0x00000001,
            AutoStart = 0x00000002,
            DemandStart = 0x00000003,
            Disabled = 0x00000004
        }

        public enum ServiceState {
            Unknown = -1, // The state cannot be (has not been) retrieved.
            NotFound = 0, // The service is not known on the host server.
            Stop = 1, // The service is NET stopped.
            Run = 2, // The service is NET started.
            Stopping = 3,
            Starting = 4,
        }

        public enum ServiceControl {
            Stop = 0x00000001,
            Pause = 0x00000002,
            Continue = 0x00000003,
            Interrogate = 0x00000004,
            Shutdown = 0x00000005,
            ParamChange = 0x00000006,
            NetBindAdd = 0x00000007,
            NetBindRemove = 0x00000008,
            NetBindEnable = 0x00000009,
            NetBindDisable = 0x0000000A
        }

        public enum ServiceError {
            Ignore = 0x00000000,
            Normal = 0x00000001,
            Severe = 0x00000002,
            Critical = 0x00000003
        }

        [StructLayout(LayoutKind.Sequential)]
        private class SERVICE_STATUS {
            public int dwServiceType = 0;
            public ServiceState dwCurrentState = 0;
            public int dwControlsAccepted = 0;
            public int dwWin32ExitCode = 0;
            public int dwServiceSpecificExitCode = 0;
            public int dwCheckPoint = 0;
            public int dwWaitHint = 0;
        }

        [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerA")]
        private static extern IntPtr OpenSCManager(string lpMachineName, string lpDatabaseName, ServiceManagerRights dwDesiredAccess);
        [DllImport("advapi32.dll", EntryPoint = "OpenServiceA", CharSet = CharSet.Ansi)]
        private static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, ServiceRights dwDesiredAccess);
        [DllImport("advapi32.dll", EntryPoint = "CreateServiceA")]
        private static extern IntPtr CreateService(IntPtr hSCManager, string lpServiceName, string lpDisplayName, ServiceRights dwDesiredAccess, int dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string lpDependencies, string lp, string lpPassword);
        [DllImport("advapi32.dll")]
        private static extern int CloseServiceHandle(IntPtr hSCObject);
        [DllImport("advapi32.dll")]
        private static extern int QueryServiceStatus(IntPtr hService, SERVICE_STATUS lpServiceStatus);
        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern int DeleteService(IntPtr hService);
        [DllImport("advapi32.dll")]
        private static extern int ControlService(IntPtr hService, ServiceControl dwControl, SERVICE_STATUS lpServiceStatus);
        [DllImport("advapi32.dll", EntryPoint = "StartServiceA")]
        private static extern int StartService(IntPtr hService, int dwNumServiceArgs, int lpServiceArgVectors);

        /// <summary>
        /// Takes a service name and tries to stop and then uninstall the windows serviceError
        /// </summary>
        /// <param name="ServiceName">The windows service name to uninstall</param>
        public static void Uninstall(string ServiceName)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr service = OpenService(scman, ServiceName, ServiceRights.StandardRightsRequired | ServiceRights.Stop | ServiceRights.QueryStatus);
                if (service == IntPtr.Zero)
                {
                    throw new ApplicationException("Service not installed.");
                }
                try
                {
                    StopService(service);
                    int ret = DeleteService(service);
                    if (ret == 0)
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new ApplicationException("Could not delete service " + error);
                    }
                }
                finally
                {
                    CloseServiceHandle(service);
                }
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Accepts a service name and returns true if the service with that service name exists
        /// </summary>
        /// <param name="ServiceName">The service name that we will check for existence</param>
        /// <returns>True if that service exists false otherwise</returns>
        public static bool ServiceIsInstalled(string ServiceName)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr service = OpenService(scman, ServiceName,
                ServiceRights.QueryStatus);
                if (service == IntPtr.Zero) return false;
                CloseServiceHandle(service);
                return true;
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Takes a service name, a service display name and the path to the service executable and installs / starts the windows service.
        /// </summary>
        /// <param name="ServiceName">The service name that this service will have</param>
        /// <param name="DisplayName">The display name that this service will have</param>
        /// <param name="FileName">The path to the executable of the service</param>
        public static void InstallAndStart(string ServiceName, string DisplayName,
        string FileName)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect |
            ServiceManagerRights.CreateService);
            try
            {
                IntPtr service = OpenService(scman, ServiceName,
                ServiceRights.QueryStatus | ServiceRights.Start);
                if (service == IntPtr.Zero)
                {
                    service = CreateService(scman, ServiceName, DisplayName,
                    ServiceRights.QueryStatus | ServiceRights.Start, SERVICE_WIN32_OWN_PROCESS,
                    ServiceBootFlag.AutoStart, ServiceError.Normal, FileName, null, IntPtr.Zero,
                    null, null, null);
                }
                if (service == IntPtr.Zero)
                {
                    throw new ApplicationException("Failed to install service.");
                }
                try
                {
                    StartService(service);
                }
                finally
                {
                    CloseServiceHandle(service);
                }
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Takes a service name and starts it
        /// </summary>
        /// <param name="Name">The service name</param>
        public static void StartService(string Name)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr hService = OpenService(scman, Name, ServiceRights.QueryStatus |
                ServiceRights.Start);
                if (hService == IntPtr.Zero)
                {
                    throw new ApplicationException("Could not open service.");
                }
                try
                {
                    StartService(hService);
                }
                finally
                {
                    CloseServiceHandle(hService);
                }
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Stops the provided windows service
        /// </summary>
        /// <param name="Name">The service name that will be stopped</param>
        public static void StopService(string Name)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr hService = OpenService(scman, Name, ServiceRights.QueryStatus |
                ServiceRights.Stop);
                if (hService == IntPtr.Zero)
                {
                    throw new ApplicationException("Could not open service.");
                }
                try
                {
                    StopService(hService);
                }
                finally
                {
                    CloseServiceHandle(hService);
                }
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Stars the provided windows service
        /// </summary>
        /// <param name="hService">The handle to the windows service</param>
        private static void StartService(IntPtr hService)
        {
            SERVICE_STATUS status = new SERVICE_STATUS();
            StartService(hService, 0, 0);
            WaitForServiceStatus(hService, ServiceState.Starting, ServiceState.Run);
        }

        /// <summary>
        /// Stops the provided windows service
        /// </summary>
        /// <param name="hService">The handle to the windows service</param>
        private static void StopService(IntPtr hService)
        {
            SERVICE_STATUS status = new SERVICE_STATUS();
            ControlService(hService, ServiceControl.Stop, status);
            WaitForServiceStatus(hService, ServiceState.Stopping, ServiceState.Stop);
        }

        /// <summary>
        /// Takes a service name and returns the <code>ServiceState</code> of the corresponding service
        /// </summary>
        /// <param name="ServiceName">The service name that we will check for his <code>ServiceState</code></param>
        /// <returns>The ServiceState of the service we wanted to check</returns>
        public static ServiceState GetServiceStatus(string ServiceName)
        {
            IntPtr scman = OpenSCManager(ServiceManagerRights.Connect);
            try
            {
                IntPtr hService = OpenService(scman, ServiceName,
                ServiceRights.QueryStatus);
                if (hService == IntPtr.Zero)
                {
                    return ServiceState.NotFound;
                }
                try
                {
                    return GetServiceStatus(hService);
                }
                finally
                {
                    CloseServiceHandle(scman);
                }
            }
            finally
            {
                CloseServiceHandle(scman);
            }
        }

        /// <summary>
        /// Gets the service state by using the handle of the provided windows service
        /// </summary>
        /// <param name="hService">The handle to the service</param>
        /// <returns>The <code>ServiceState</code> of the service</returns>
        private static ServiceState GetServiceStatus(IntPtr hService)
        {
            SERVICE_STATUS ssStatus = new SERVICE_STATUS();
            if (QueryServiceStatus(hService, ssStatus) == 0)
            {
                throw new ApplicationException("Failed to query service status.");
            }
            return ssStatus.dwCurrentState;
        }

        /// <summary>
        /// Returns true when the service status has been changes from wait status to desired status
        /// ,this method waits around 10 seconds for this operation.
        /// </summary>
        /// <param name="hService">The handle to the service</param>
        /// <param name="WaitStatus">The current state of the service</param>
        /// <param name="DesiredStatus">The desired state of the service</param>
        /// <returns>bool if the service has successfully changed states within the allowed timeline</returns>
        private static bool WaitForServiceStatus(IntPtr hService, ServiceState
        WaitStatus, ServiceState DesiredStatus)
        {
            SERVICE_STATUS ssStatus = new SERVICE_STATUS();
            int dwOldCheckPoint;
            int dwStartTickCount;

            QueryServiceStatus(hService, ssStatus);
            if (ssStatus.dwCurrentState == DesiredStatus) return true;
            dwStartTickCount = Environment.TickCount;
            dwOldCheckPoint = ssStatus.dwCheckPoint;

            while (ssStatus.dwCurrentState == WaitStatus)
            {
                // Do not wait longer than the wait hint. A good interval is
                // one tenth the wait hint, but no less than 1 second and no
                // more than 10 seconds.

                int dwWaitTime = ssStatus.dwWaitHint / 10;

                if (dwWaitTime < 1000) dwWaitTime = 1000;
                else if (dwWaitTime > 10000) dwWaitTime = 10000;

                System.Threading.Thread.Sleep(dwWaitTime);

                // Check the status again.

                if (QueryServiceStatus(hService, ssStatus) == 0) break;

                if (ssStatus.dwCheckPoint > dwOldCheckPoint)
                {
                    // The service is making progress.
                    dwStartTickCount = Environment.TickCount;
                    dwOldCheckPoint = ssStatus.dwCheckPoint;
                }
                else
                {
                    if (Environment.TickCount - dwStartTickCount > ssStatus.dwWaitHint)
                    {
                        // No progress made within the wait hint
                        break;
                    }
                }
            }
            return (ssStatus.dwCurrentState == DesiredStatus);
        }

        /// <summary>
        /// Opens the service manager
        /// </summary>
        /// <param name="Rights">The service manager rights</param>
        /// <returns>the handle to the service manager</returns>
        private static IntPtr OpenSCManager(ServiceManagerRights Rights)
        {
            IntPtr scman = OpenSCManager(null, null, Rights);
            if (scman == IntPtr.Zero)
            {
                throw new ApplicationException("Could not connect to service control manager.");
            }
            return scman;
        }

#endregion

    }
}

ในการติดตั้งบริการให้รันคำสั่ง InstallAndStart ดังนี้:

  SystemControl.InstallAndStart(
                                 "apache",
                                 "Apache Web Server",
                                 @"""c:\apache\bin\httpd.exe"" -k runservice"
  );

ตรวจสอบให้แน่ใจว่าบัญชีที่ใช้งานโปรแกรมมีสิทธิ์ในการติดตั้งบริการ คุณสามารถ 'เรียกใช้ในฐานะผู้ดูแลระบบ' ในโปรแกรมได้ตลอดเวลา

ฉันยังได้รวมหลายคำสั่งสำหรับการเข้าถึงแบบ non-api ซึ่งไม่ได้ติดตั้งหรือลบบริการ แต่คุณสามารถแสดงรายการและควบคุมหลาย ๆ ตัวได้ (เริ่มหยุดหยุดรีสตาร์ท) คุณจำเป็นต้องยกระดับสิทธิ์สำหรับการติดตั้งหรือลบบริการเท่านั้น

มีคู่ของคำสั่งในการรับและการตั้งค่าตัวแปรสภาพแวดล้อมเป็นอย่างดีเช่นหรือOPENSSL_CONF TEMPส่วนใหญ่พารามิเตอร์และชื่อเมธอดควรอธิบายได้ด้วยตนเอง


ServiceState enum มีการพิมพ์ผิด มันควรจะเป็น:Unknown = -1, NotFound = 0, Stopped = 1, StartPending = 2, StopPending = 3, Running = 4
sohil

2

ในกรณีที่พยายามติดตั้งแอปพลิเคชันบรรทัดคำสั่งเป็นบริการ Windows ให้ลองใช้ยูทิลิตี้ ' NSSM ' รายละเอียดที่เกี่ยวข้อง ServerFault พบที่นี่


-3
Process QProc = new Process();
QProc.StartInfo.FileName = "cmd";
QProc.StartInfo.Arguments ="/c InstallUtil "+ "\""+ filefullPath +"\"";
QProc.StartInfo.WorkingDirectory = Environment.GetEnvironmentVariable("windir") + @"\Microsoft.NET\Framework\v2.0.50727\";
QProc.StartInfo.UseShellExecute = false;
// QProc.StartInfo.CreateNoWindow = true;
QProc.StartInfo.RedirectStandardOutput = true;
QProc.Start();
// QProc.WaitForExit();
QProc.Close();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.