Установите сервис окон.NET без InstallUtil.exe

У меня есть стандартный сервис окон.NET, записанный в C#.

Это может установить себя, не используя InstallUtil? Я должен использовать сервисный класс установщика? Как я должен использовать его?

Я хочу смочь назвать следующее:

MyService.exe -install

И это будет иметь тот же эффект как вызов:

InstallUtil MyService.exe
163
задан K DawG 29 July 2018 в 05:47
поделиться

4 ответа

Да, это полностью возможно (т.е. Я делаю точно это); просто необходимо сослаться на право 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);
    }
}
154
ответ дан Ian Kemp 23 November 2019 в 21:19
поделиться

Вот класс, который я использую при записи сервисов. У меня обычно есть интерактивный экран, который подходит, когда сервис не называют. Оттуда я использую класс по мере необходимости. Это допускает несколько именованных экземпляров на той же машине - следовательно Демонстрационный Вызов поля

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);
        }
    }
}
9
ответ дан Brad Bruce 23 November 2019 в 21:19
поделиться

Обратите внимание на метод InstallHelper класса ManagedInstaller . Вы можете установить службу, используя:

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

Это именно то, что делает InstallUtil. Аргументы те же, что и для InstallUtil.

Преимущества этого метода заключаются в том, что он не вызывает беспорядка в реестре и использует тот же механизм, что и InstallUtil.

39
ответ дан 23 November 2019 в 21:19
поделиться

Вы всегда можете вернуться к старым добрым вызовам WinAPI, хотя объем работы нетривиален. Не требуется, чтобы службы .NET устанавливались с помощью механизма, поддерживающего .NET.

Для установки:

  • Откройте диспетчер служб через OpenSCManager .
  • Позвоните по телефону CreateService ], чтобы зарегистрировать службу.
  • При необходимости вызовите ChangeServiceConfig2 , чтобы задать описание.
  • Закройте службы и дескрипторы диспетчера служб с помощью CloseServiceHandle .

Для удаления:

  • Откройте диспетчер служб через OpenSCManager .
  • Откройте службу, используя OpenService .
  • Удалите службу, вызвав DeleteService для дескриптора, возвращенного OpenService .
  • Закройте службы и обработчики диспетчера служб с помощью CloseServiceHandle .

Основная причина, по которой я предпочитаю это использование ServiceInstaller / ServiceProcessInstaller , заключается в том, что вы можете зарегистрируйте службу с вашими собственными аргументами командной строки. Например, вы можете зарегистрировать его как "MyApp.exe -service" , а затем, если пользователь запустит ваше приложение без каких-либо аргументов, вы можете предложить ему пользовательский интерфейс для установки / удаления службы.

Запуск Reflector на ServiceInstaller может заполнить детали, отсутствующие в этом кратком объяснении.

PS Ясно, что это не будет иметь «такого же эффекта, как вызов: InstallUtil MyService.exe» - в частности, вы не будете можно удалить с помощью InstallUtil. Но похоже, что, возможно, это было не так.

19
ответ дан 23 November 2019 в 21:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: