2010-05-18 14 views
31

Je suis en train de déployer un service Windows mais je ne sais pas trop comment le faire correctement. Je l'ai construit comme une application de console pour commencer, je l'ai maintenant transformé en un projet de service Windows et appelez simplement ma classe à partir de la méthode OnStart dans le service.Installer le service Windows sans InstallUtil.exe

Je dois maintenant installer ceci sur un serveur qui n'a pas Visual Studio dessus, qui si je l'ai compris correctement signifie que je ne peux pas utiliser le InstallUtil.exe et devez créer une classe d'installateur à la place. Est-ce correct?

J'ai jeté un coup d'oeil à une question précédente, Install a .NET windows service without InstallUtil.exe, mais je veux juste m'assurer que j'ai bien compris.

Si je crée la classe à laquelle la réponse acceptée par la question est liée, quelle est la prochaine étape? Télécharger MyService.exe et MyService.exe.config sur le serveur, double-cliquez sur le fichier exe et Bob mon oncle?

Le service ne jamais être installé sur un serveur.

+0

double - http://stackoverflow.com/questions/255056/install-a-net-windows-service-without-installutil-exe –

+0

@AZ Oui, je sais, je pensais que ce serait bien de poser la question de toute façon car je fais référence à la question précédente et la mienne est légèrement différente en ce sens que ce n'est pas un service .net (il n'a pas d'interface) voulait s'assurer que les mêmes réponses s'appliqueraient. – annelie

Répondre

17

L'outil InstallUtil.exe est simplement un wrapper autour de certains appels de réflexion par rapport au (x) composant (s) d'installation de votre service. En tant que tel, il ne fait pas grand-chose mais exerce la fonctionnalité que ces composants de l'installateur fournissent. La solution de Marc Gravell fournit simplement un moyen de le faire à partir de la ligne de commande afin que vous n'ayez plus besoin d'avoir InstallUtil.exe sur la machine cible.

Voici mon étape par étape qui repose sur la solution de Marc Gravell.

How to make a .NET Windows Service start right after the installation?

+0

Merci, je suis presque là avec ça. Je reçois une exception de sécurité disant "La source n'a pas été trouvée, mais certains ou tous les journaux d'événements n'ont pas pu être recherchés. Journaux inaccessibles: sécurité ».Je suppose que cela pourrait avoir à voir avec le compte sous lequel @ho parle de son commentaire. Je l'ai défini sur LocalService, mais je vais le changer et réessayer. Par ailleurs, une petite faute d'orthographe dans votre code, pour l'InstallService(), il est dit 'IDictionary state = new Hasttable();' plutôt que Hashtable. – annelie

+0

L'a corrigé. Merci. –

+0

Aucun problème. Droit, j'ai essayé avec tous les différents comptes, tous sauf utilisateur donne la même exception, et pour l'utilisateur, je dois entrer le nom d'utilisateur et mot de passe. Quel nom d'utilisateur et quel mot de passe devrait-il être? Pour l'utilisateur avec lequel je me connecte au serveur? – annelie

0

Pas double-cliquez, vous l'exécutez avec les paramètres de ligne de commande corrects, tapez donc quelque chose comme MyService -i puis MyService -u pour le désinstaller``.

Vous pouvez sinon utiliser sc.exe pour l'installer et le désinstaller (ou copier le fichier InstallUtil.exe).

5

Pourquoi ne pas simplement créer un projet d'installation? C'est vraiment facile.

  1. Ajouter un installateur de service au service (vous le faites sur le service de surface « design » apparemment inutile)
  2. Créer un projet d'installation et ajouter la sortie de service dans le dossier de l'application de configuration
  3. Plus important encore ajouter la sortie du projet de service à toutes les actions personnalisées

Voila, et vous avez terminé.

Voir ici pour plus: http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx

Il y a aussi une façon de demander à l'utilisateur des informations d'identification (ou fournir votre propre).

+0

Merci, je vais jeter un coup d'oeil à ceci si je ne peux pas obtenir les autres suggestions pour fonctionner. Vous n'êtes pas sûr de ce que vous voulez dire? – annelie

+0

Avec les informations d'identification, il désigne le compte sous lequel le service fonctionne. –

+0

@ho Dans quel compte le service doit-il fonctionner? Fondamentalement, le service surveille certains dossiers pour de nouveaux fichiers, télécharge des fichiers dans une base de données s'il y a de nouveaux fichiers, puis déplace les fichiers dans un dossier différent. – annelie

28

Vous pouvez toujours utiliser installutil sans visual studio, il est inclus avec le.cadre net

Sur votre serveur, ouvrez une invite de commande en tant qu'administrateur alors:

CD C:\Windows\Microsoft.NET\Framework\v4.0.version (insert your version) 

installutil "C:\Program Files\YourWindowsService\YourWindowsService.exe" (insert your service name/location) 

Pour désinstaller:

installutil /u "C:\Program Files\YourWindowsService\YourWindowsService.exe" (insert your service name/location) 
30

Je sais qu'il est une question très ancienne, mais il vaut mieux le mettre à jour avec de nouvelles information.

Vous pouvez installer le service en utilisant la commande sc:

installservice.bat:

@echo OFF 
echo Stopping old service version... 
net stop "[YOUR SERVICE NAME]" 
echo Uninstalling old service version... 
sc delete "[YOUR SERVICE NAME]" 

echo Installing service... 
rem DO NOT remove the space after "binpath="! 
sc create "[YOUR SERVICE NAME]" binpath= "[PATH_TO_YOUR_SERVICE_EXE]" start= auto 
echo Starting server complete 
pause 

Avec SC, vous pouvez faire beaucoup plus de choses aussi bien: désinstaller l'ancien service (si vous déjà installé auparavant), en vérifiant si le service avec le même nom existe ... même définir votre service pour autostart.

L'une des nombreuses références: creating a service with sc.exe; how to pass in context parameters

Je l'ai fait à la fois de cette façon & InstallUtil. Personnellement, je pense que l'utilisation de SC est plus propre et meilleure pour votre santé.

+2

Ceci est super facile et devrait être mis à jour de façon plus que les autres méthodes. – Sam

+3

Je pense que c'est le moyen le plus facile d'installer un service Windows – ykh

+1

Je suis d'accord, c'est totalement la solution la plus facile et devrait être plus loin FAR que les autres solutions UBER COMPLEX! Bon produit! –

0

Topshelf est un projet OSS qui a été lancé après que cette question a été répondue et il rend le service Windows beaucoup, beaucoup plus facile.Je recommande fortement d'examiner dans ce.

http://topshelf-project.com/

0

Ce problème est dû à la sécurité, mieux ouvrez l'invite de commandes Developer pour VS 2012 en RUN AS ADMINISTRATEUR et installer votre service, il résoudre votre problème sûrement.

2

Il s'agit d'une classe de service de base (sous-classe ServiceBase) qui peut être sous-classée pour créer un service Windows qui peut être facilement installé à partir de la ligne de commande, sans installutil.exe. Cette solution est dérivé de How to make a .NET Windows Service start right after the installation?, en ajoutant un code pour obtenir le type de service en utilisant l'appelant StackFrame

public abstract class InstallableServiceBase:ServiceBase 
{ 

    /// <summary> 
    /// returns Type of the calling service (subclass of InstallableServiceBase) 
    /// </summary> 
    /// <returns></returns> 
    protected static Type getMyType() 
    { 
     Type t = typeof(InstallableServiceBase); 
     MethodBase ret = MethodBase.GetCurrentMethod(); 
     Type retType = null; 
     try 
     { 
      StackFrame[] frames = new StackTrace().GetFrames(); 
      foreach (StackFrame x in frames) 
      { 
       ret = x.GetMethod(); 

       Type t1 = ret.DeclaringType; 

       if (t1 != null && !t1.Equals(t) && !t1.IsSubclassOf(t)) 
       { 


        break; 
       } 
       retType = t1; 
      } 
     } 
     catch 
     { 

     } 
     return retType; 
    } 
    /// <summary> 
    /// returns AssemblyInstaller for the calling service (subclass of InstallableServiceBase) 
    /// </summary> 
    /// <returns></returns> 
    protected static AssemblyInstaller GetInstaller() 
    { 
     Type t = getMyType(); 
     AssemblyInstaller installer = new AssemblyInstaller(
      t.Assembly, null); 
     installer.UseNewContext = true; 
     return installer; 
    } 

    private bool IsInstalled() 
    { 
     using (ServiceController controller = 
      new ServiceController(this.ServiceName)) 
     { 
      try 
      { 
       ServiceControllerStatus status = controller.Status; 
      } 
      catch 
      { 
       return false; 
      } 
      return true; 
     } 
    } 

    private bool IsRunning() 
    { 
     using (ServiceController controller = 
      new ServiceController(this.ServiceName)) 
     { 
      if (!this.IsInstalled()) return false; 
      return (controller.Status == ServiceControllerStatus.Running); 
     } 
    } 
    /// <summary> 
    /// protected method to be called by a public method within the real service 
    /// ie: in the real service 
    /// new internal void InstallService() 
    /// { 
    ///  base.InstallService(); 
    /// } 
    /// </summary> 
    protected void InstallService() 
    { 
     if (this.IsInstalled()) return; 

     try 
     { 
      using (AssemblyInstaller installer = GetInstaller()) 
      { 

       IDictionary state = new Hashtable(); 
       try 
       { 
        installer.Install(state); 
        installer.Commit(state); 
       } 
       catch 
       { 
        try 
        { 
         installer.Rollback(state); 
        } 
        catch { } 
        throw; 
       } 
      } 
     } 
     catch 
     { 
      throw; 
     } 
    } 
    /// <summary> 
    /// protected method to be called by a public method within the real service 
    /// ie: in the real service 
    /// new internal void UninstallService() 
    /// { 
    ///  base.UninstallService(); 
    /// } 
    /// </summary> 
    protected void UninstallService() 
    { 
     if (!this.IsInstalled()) return; 

     if (this.IsRunning()) { 
      this.StopService(); 
     } 
     try 
     { 
      using (AssemblyInstaller installer = GetInstaller()) 
      { 
       IDictionary state = new Hashtable(); 
       try 
       { 
        installer.Uninstall(state); 
       } 
       catch 
       { 
        throw; 
       } 
      } 
     } 
     catch 
     { 
      throw; 
     } 
    } 

    private void StartService() 
    { 
     if (!this.IsInstalled()) return; 

     using (ServiceController controller = 
      new ServiceController(this.ServiceName)) 
     { 
      try 
      { 
       if (controller.Status != ServiceControllerStatus.Running) 
       { 
        controller.Start(); 
        controller.WaitForStatus(ServiceControllerStatus.Running, 
         TimeSpan.FromSeconds(10)); 
       } 
      } 
      catch 
      { 
       throw; 
      } 
     } 
    } 

    private void StopService() 
    { 
     if (!this.IsInstalled()) return; 
     using (ServiceController controller = 
      new ServiceController(this.ServiceName)) 
     { 
      try 
      { 
       if (controller.Status != ServiceControllerStatus.Stopped) 
       { 
        controller.Stop(); 
        controller.WaitForStatus(ServiceControllerStatus.Stopped, 
         TimeSpan.FromSeconds(10)); 
       } 
      } 
      catch 
      { 
       throw; 
      } 
     } 
    } 
} 

Tout ce que vous avez à faire est de mettre en œuvre deux méthodes publiques/internes dans votre service réel:

new internal void InstallService() 
    { 
     base.InstallService(); 
    } 
    new internal void UninstallService() 
    { 
     base.UninstallService(); 
    } 

puis les appeler lorsque vous souhaitez installer le service:

static void Main(string[] args) 
    { 
     if (Environment.UserInteractive) 
     { 
      MyService s1 = new MyService(); 
      if (args.Length == 1) 
      { 
       switch (args[0]) 
       { 
        case "-install": 
         s1.InstallService(); 

         break; 
        case "-uninstall": 

         s1.UninstallService(); 
         break; 
        default: 
         throw new NotImplementedException(); 
       } 
      } 


     } 
     else { 
      ServiceBase[] ServicesToRun; 
      ServicesToRun = new ServiceBase[] 
      { 
       new MyService() 
      }; 
      ServiceBase.Run(MyService);    
     } 

    } 
Questions connexes