Comment créer un programme d'installation pour un service Windows .net à l'aide de Visual Studio

152

Comment créer un programme d'installation pour un service Windows que j'ai créé à l'aide de Visual Studio?

Kelsey
la source
Ceci est déjà documenté dans l'article suivant de la base de
connaissances

Réponses:

227

Dans le projet de service, procédez comme suit:

  1. Dans l'explorateur de solutions, double-cliquez sur le fichier .cs de vos services. Il devrait faire apparaître un écran qui est tout gris et parle de faire glisser des éléments de la boîte à outils.
  2. Cliquez ensuite avec le bouton droit sur la zone grise et sélectionnez Ajouter un installateur. Cela ajoutera un fichier de projet d'installation à votre projet.
  3. Ensuite, vous aurez 2 composants sur la vue de conception de ProjectInstaller.cs (serviceProcessInstaller1 et serviceInstaller1). Vous devez ensuite configurer les propriétés dont vous avez besoin, telles que le nom du service et l'utilisateur sous lequel il doit s'exécuter.

Vous devez maintenant créer un projet d'installation. La meilleure chose à faire est d'utiliser l'assistant de configuration.

  1. Faites un clic droit sur votre solution et ajoutez un nouveau projet: Ajouter> Nouveau projet> Projets de configuration et de déploiement> Assistant de configuration

    une. Cela peut varier légèrement pour différentes versions de Visual Studio. b. Visual Studio 2010, il se trouve dans: Modèles d'installation> Autres types de projets> Installation et déploiement> Programme d'installation de Visual Studio

  2. À la deuxième étape, sélectionnez «Créer une installation pour une application Windows».

  3. À la 3ème étape, sélectionnez "Sortie principale de ..."

  4. Cliquez sur pour terminer.

Modifiez ensuite votre programme d'installation pour vous assurer que la sortie correcte est incluse.

  1. Cliquez avec le bouton droit sur le projet d'installation dans votre Explorateur de solutions.
  2. Sélectionnez Affichage> Actions personnalisées. (Dans VS2008, il peut s'agir de Affichage> Éditeur> Actions personnalisées)
  3. Cliquez avec le bouton droit de la souris sur l'action Installer dans l'arborescence Actions personnalisées et sélectionnez "Ajouter une action personnalisée ..."
  4. Dans la boîte de dialogue "Sélectionner un élément dans le projet", sélectionnez Dossier d'application et cliquez sur OK.
  5. Cliquez sur OK pour sélectionner l'option "Sortie principale de ...". Un nouveau nœud doit être créé.
  6. Répétez les étapes 4 à 5 pour les actions de validation, de restauration et de désinstallation.

Vous pouvez modifier le nom de sortie du programme d'installation en cliquant avec le bouton droit sur le projet Installer dans votre solution et en sélectionnant Propriétés. Changez le 'Nom du fichier de sortie:' en celui que vous voulez. En sélectionnant le projet d'installation ainsi et en regardant les propriétés de fenêtres, vous pouvez modifier le Product Name, Title, Manufacturer, etc ...

Ensuite, construisez votre programme d'installation et il produira un MSI et un setup.exe. Choisissez celui que vous souhaitez utiliser pour déployer votre service.

Kelsey
la source
37
@El Ronnoco, j'avais la réponse bien avant de poster. Je voulais le documenter ici parce que je dois toujours le chercher tous les 6 à 12 mois (et cela n'a pas été aussi facile à trouver) alors maintenant je l'ai facilement consultable pour tout le monde et je peux le trouver moi-même rapidement :)
Kelsey
1
Malheureusement, c'est aussi la mauvaise réponse. Oui, je sais que vous trouverez cela dans les livres et MSDN, mais c'est un cas où un groupe de Microsoft n'a pas parlé à un autre groupe de Microsoft et a proposé une solution inférieure à un problème qui avait déjà été résolu. Voir blog.iswix.com/2006/07/msi-vs-net.html pour plus d'informations.
Christopher Painter
9
@Christopher Painter J'utilise l'installateur MS depuis2k5 et il n'a jamais eu de problème. Que vous soyez d'accord ou non avec cela et que vous le considérez comme un «anti-modèle» n'est pas le but de cette question, c'est comment faire x avec y, pas comment faire a avec b. Quand j'ai posté la question, c'était à des fins de documentation.
Kelsey
3
Ensuite, vous avez de la chance depuis 6 ans, vous ne le savez pas. Vous voudrez peut-être lire: robmensching.com/blog/posts/2007/4/19/…
Christopher Painter
1
Si vous obtenez une Service name contains invalid characters, is empty, or is too long (max length = 80)erreur lors de l'ajout du programme d'installation, cliquez à nouveau avec le bouton droit de la souris dans la zone grise, accédez à Propriétés et assurez-vous que la valeur du nom du service est définie.
wolfyuk
51

Je suis le premier ensemble d'étapes de Kelsey pour ajouter les classes du programme d'installation à mon projet de service, mais au lieu de créer un programme d'installation MSI ou setup.exe, je fais auto-installer / désinstaller le service. Voici un exemple de code d'un de mes services que vous pouvez utiliser comme point de départ.

public static int Main(string[] args)
{
    if (System.Environment.UserInteractive)
    {
        // we only care about the first two characters
        string arg = args[0].ToLowerInvariant().Substring(0, 2);

        switch (arg)
        {
            case "/i":  // install
                return InstallService();

            case "/u":  // uninstall
                return UninstallService();

            default:  // unknown option
                Console.WriteLine("Argument not recognized: {0}", args[0]);
                Console.WriteLine(string.Empty);
                DisplayUsage();
                return 1;
        }
    }
    else
    {
        // run as a standard service as we weren't started by a user
        ServiceBase.Run(new CSMessageQueueService());
    }

    return 0;
}

private static int InstallService()
{
    var service = new MyService();

    try
    {
        // perform specific install steps for our queue service.
        service.InstallService();

        // install the service with the Windows Service Control Manager (SCM)
        ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });
    }
    catch (Exception ex)
    {
        if (ex.InnerException != null && ex.InnerException.GetType() == typeof(Win32Exception))
        {
            Win32Exception wex = (Win32Exception)ex.InnerException;
            Console.WriteLine("Error(0x{0:X}): Service already installed!", wex.ErrorCode);
            return wex.ErrorCode;
        }
        else
        {
            Console.WriteLine(ex.ToString());
            return -1;
        }
    }

    return 0;
}

private static int UninstallService()
{
    var service = new MyQueueService();

    try
    {
        // perform specific uninstall steps for our queue service
        service.UninstallService();

        // uninstall the service from the Windows Service Control Manager (SCM)
        ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
    }
    catch (Exception ex)
    {
        if (ex.InnerException.GetType() == typeof(Win32Exception))
        {
            Win32Exception wex = (Win32Exception)ex.InnerException;
            Console.WriteLine("Error(0x{0:X}): Service not installed!", wex.ErrorCode);
            return wex.ErrorCode;
        }
        else
        {
            Console.WriteLine(ex.ToString());
            return -1;
        }
    }

    return 0;
}

la source
1
Par curiosité, quel est l'avantage d'avoir un service auto-installable / désinstallant? Si le service s'installe, comment démarrer le service en premier afin qu'il puisse être installé en premier lieu? S'il existe un mécanisme pour démarrer le service sans l'installer, pourquoi s'embêter à l'installer?
Kiley Naro le
3
@Christopher - Moi non. Ma solution ne remplace pas un programme d'installation complet que vous utiliseriez pour distribuer des logiciels. Je présente une autre option qui fonctionne pour certaines situations, comme la mienne, où j'écris des logiciels qui pilotent des PC embarqués dans des kiosques sans surveillance.
4
Lorsque vous l'installez sur une machine de production, n'oubliez pas de l'exécuter en tant qu'administrateur. J'ai créé un fichier BAT qui appelle le fichier EXE avec le paramètre / i mais cela n'a pas fonctionné sur l'environnement de production, même si j'ai exécuté le fichier BAT en tant qu'administrateur. J'ai dû ouvrir une invite de ligne de commande en tant qu'administrateur et appeler explicitement le fichier EXE / i (sans utiliser le fichier BAT). Au moins, cela m'est arrivé sur un Windows Server 2012.
Francisco Goldenstein
1
RE: Pas de sortie sur la ligne de commande. En utilisant VS 2017 Communauté mon nouveau projet de service par défaut type de sortie: Windows Applicationet objet de démarrage: (none). J'ai dû changer le type de sortie Console Applicationet définir mon objet de démarrage, par exemple myservice.Program. S'il peut y avoir des ramifications dont je ne suis pas au courant, veuillez en informer.
Jonathan
1
L'exemple de code a-t-il des fautes de frappe? Pourquoi existe-t-il trois services de différence (CSMessageQueueService, MyService, MyQueueService)?
Nils Guillermin
27

Ni Kelsey, ni les solutions Brendan ne fonctionnent pour moi dans Visual Studio 2015 Community.

Voici mes brèves étapes pour créer un service avec l'installateur:

  1. Exécutez Visual Studio, accédez à File->New->Project
  2. Sélectionnez .NET Framework 4, dans 'Rechercher les modèles installés', tapez 'Service'
  3. Sélectionnez «Service Windows». Saisissez le nom et l'emplacement. presseOK .
  4. Double-cliquez sur Service1.cs, faites un clic droit dans le concepteur et sélectionnez `` Ajouter un programme d'installation ''
  5. Double-cliquez sur ProjectInstaller.cs. Pour serviceProcessInstaller1, ouvrez l'onglet Propriétés et remplacez la valeur de la propriété «Compte» par «LocalService». Pour serviceInstaller1, modifiez «ServiceName» et définissez «StartType» sur «Automatic».
  6. Double-cliquez sur serviceInstaller1. Visual Studio crée un serviceInstaller1_AfterInstallévénement. Ecrire le code:

    private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
    {
        using (System.ServiceProcess.ServiceController sc = new 
        System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName))
        {
            sc.Start();
        }
    }
  7. Créer une solution. Faites un clic droit sur le projet et sélectionnez «Ouvrir le dossier dans l'explorateur de fichiers». Accédez à bin \ Debug .

  8. Créez install.bat avec le script ci-dessous:

    :::::::::::::::::::::::::::::::::::::::::
    :: Automatically check & get admin rights
    :::::::::::::::::::::::::::::::::::::::::
    @echo off
    CLS 
    ECHO.
    ECHO =============================
    ECHO Running Admin shell
    ECHO =============================
    
    :checkPrivileges 
    NET FILE 1>NUL 2>NUL
    if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges ) 
    
    :getPrivileges 
    if '%1'=='ELEV' (shift & goto gotPrivileges)  
    ECHO. 
    ECHO **************************************
    ECHO Invoking UAC for Privilege Escalation 
    ECHO **************************************
    
    setlocal DisableDelayedExpansion
    set "batchPath=%~0"
    setlocal EnableDelayedExpansion
    ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\OEgetPrivileges.vbs" 
    ECHO UAC.ShellExecute "!batchPath!", "ELEV", "", "runas", 1 >> "%temp%\OEgetPrivileges.vbs" 
    "%temp%\OEgetPrivileges.vbs" 
    exit /B 
    
    :gotPrivileges 
    ::::::::::::::::::::::::::::
    :START
    ::::::::::::::::::::::::::::
    setlocal & pushd .
    
    cd /d %~dp0
    %windir%\Microsoft.NET\Framework\v4.0.30319\InstallUtil /i "WindowsService1.exe"
    pause
  9. Créer un fichier uninstall.bat (changement dans la ligne pen-ult /i par /u)
  10. Pour installer et démarrer le service, exécutez install.bat, pour arrêter et désinstaller, exécutez uninstall.bat
Alexey Obukhov
la source
14

Pour VS2017, vous devrez ajouter l'extension VS «Projets d'installation Microsoft Visual Studio 2017». Cela vous donnera des modèles de projet Visual Studio Installer supplémentaires. https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.MicrosoftVisualStudio2017InstallerProjects#overview

Pour installer le service Windows, vous pouvez ajouter un nouveau projet de type assistant d'installation et suivre les étapes de la réponse de Kelsey https://stackoverflow.com/a/9021107/1040040

JustSomeDev
la source
1

Les classes InstallUtil (ServiceInstaller) sont considérées comme un anti-modèle par la communauté Windows Installer. C'est une réinvention fragile, hors processus, de la roue qui ignore le fait que Windows Installer a un support intégré pour les services.

Les projets de déploiement Visual Studio (également peu appréciés et obsolètes dans la prochaine version de Visual Studio) ne disposent pas de la prise en charge native des services. Mais ils peuvent consommer des modules de fusion. Je voudrais donc jeter un œil à cet article de blog pour comprendre comment créer un module de fusion à l'aide de Windows Installer XML qui peut exprimer le service, puis consommer ce module de fusion dans votre solution VDPROJ.

Augmenter InstallShield à l'aide de Windows Installer XML - Services Windows

Didacticiel du service Windows IsWiX

Vidéo du service Windows IsWiX

Christopher Peintre
la source
1
Dans l'ancien Visual Studio, il y avait un projet de déploiement, avec un programme d'installation de création facile. Maintenant, je dois acheter un composant logiciel tiers?
Alexey Obukhov
@AlexeyObukhov Vous pouvez utiliser Wix gratuitement, c'est ce que VS utilise lui-même, mais le problème avec Wix est le même que le problème avec Git - la courbe d'apprentissage presque verticale.
Alan B le