167 votes

Installer un service Windows .NET sans InstallUtil.exe

J'ai un service Windows standard .NET écrit en C #.

Peut-il s'installer sans utiliser InstallUtil? Dois-je utiliser la classe d'installation de service? Comment devrais-je l'utiliser?

Je veux pouvoir appeler ce qui suit:

MyService.exe -install

et cela aura le même effet que d'appeler:

InstallUtil MyService.exe

159voto

Marc Gravell Points 482669

Oui, c'est tout à fait possible (c'est-à-dire que je fais exactement cela); il vous suffit de référencer la bonne DLL (System.ServiceProcess.dll) et d'ajouter une classe d'installation ...

Voici un exemple.

40voto

adrianbanks Points 36858

Jetez un oeil à la InstallHelper méthode de la ManagedInstaller classe. Vous pouvez installer un service à l'aide de:

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

C'est exactement ce que InstallUtil. Les arguments sont les mêmes que pour InstallUtil.

Les avantages de cette méthode sont qu'elle n'implique pas de déconner dans le registre, et il utilise le même mécanisme que InstallUtil.

19voto

romkyns Points 17295

Vous pouvez toujours revenir à la bonne vieille WinAPI appels, bien que la quantité de travail est non-trivial. Il n'est pas nécessaire .NET services être installé via un .NET-conscient mécanisme.

Pour l'installer:

  • Ouvrez le gestionnaire des services via OpenSCManager.
  • Appelez CreateService à l'inscription du service.
  • Éventuellement appel ChangeServiceConfig2 pour définir une description.
  • Fermer le service et le gestionnaire de services poignées CloseServiceHandle.

Pour désinstaller:

  • Ouvrez le gestionnaire des services via OpenSCManager.
  • Ouvrir le service à l'aide de OpenService.
  • Supprimer le service en appelant DeleteService sur le handle retourné par OpenService.
  • Fermer le service et le gestionnaire de services poignées CloseServiceHandle.

La principale raison pour laquelle je préfère ce sur l'aide de l' ServiceInstaller/ServiceProcessInstaller , c'est que vous pouvez vous inscrire au service, avec vos propres arguments de ligne de commande. Par exemple, vous pouvez l'enregistrer en tant que "MyApp.exe -service", puis si l'utilisateur exécute votre application sans aucun argument, vous pouvez offrir une INTERFACE utilisateur pour installer/supprimer le service.

L'exécution de Réflecteur sur ServiceInstaller peut remplir les détails manquants à partir de cette brève explication.

P. S. Clairement ce ne sera pas "le même effet que l'appelant: InstallUtil MyService.exe" - en particulier, vous ne serez pas en mesure de le désinstaller à l'aide de InstallUtil. Mais il semble que c'était peut-être pas une réelle exigence stricte pour vous.

9voto

Brad Bruce Points 4359

Voici une classe que j'utilise pour écrire des services. J'ai généralement un écran interactif qui s'affiche lorsque le service n'est pas appelé. À partir de là, j'utilise le cours si nécessaire. Il permet plusieurs instances nommées sur la même machine, par exemple le champ InstanceID.

Exemple d'appel

   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;
                }
 

La classe elle-même

 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);
    	}
    }
}
 

2voto

John M Points 2933

En cas d'installation d'une application de ligne de commande en tant que service Windows, essayez l'utilitaire ' NSSM '. Détails ServerFault connexes trouvés ici .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X