Як створити інсталятор для .net Windows Windows за допомогою Visual Studio


Відповіді:


227

У проекті обслуговування виконайте наступне:

  1. У провіднику рішень двічі клацніть файл ваших служб .cs. Він повинен відображати сірий екран і говорить про перетягування матеріалів із панелі інструментів.
  2. Потім клацніть правою кнопкою миші на сірій області та виберіть Додати інсталятор. Це додасть файл проекту інсталятора до вашого проекту.
  3. Тоді у вас буде два компоненти на дизайнерському перегляді ProjectInstaller.cs (serviceProcessInstaller1 та serviceInstaller1). Потім слід налаштувати такі властивості, як вам потрібно, наприклад, ім'я служби та користувач, які вони повинні працювати.

Тепер вам потрібно зробити проект налаштування. Найкраще зробити це - використовувати майстра налаштування.

  1. Клацніть правою кнопкою миші рішення та додайте новий проект: Додати> Новий проект> Проекти налаштування та розгортання> Майстер налаштування

    а. Це може дещо відрізнятися для різних версій Visual Studio. б. Visual Studio 2010 знаходиться в: Встановити шаблони> Інші типи проектів> Налаштування та розгортання> Установник Visual Studio

  2. На другому кроці виберіть «Створити налаштування для програми Windows».

  3. На 3-му кроці виберіть "Первинний вихід з ..."

  4. Клацніть через, щоб закінчити.

Далі відредагуйте інсталятор, щоб переконатися, що входить правильний вихід.

  1. Клацніть правою кнопкою миші проект налаштування у вашому Провіднику рішень.
  2. Виберіть Перегляд> Спеціальні дії. (У VS2008 це може бути Перегляд> Редактор> Спеціальні дії)
  3. Клацніть правою кнопкою миші на дію "Встановити" у дереві "Спеціальні дії" та виберіть "Додати власну дію ..."
  4. У діалоговому вікні "Вибір елемента в проекті" виберіть папку програми та натисніть кнопку ОК.
  5. Клацніть OK, щоб вибрати параметр "Первинний вихід з ...". Слід створити новий вузол.
  6. Повторіть кроки 4 - 5 для дій з фіксацією, відкатом та видаленням.

Ви можете відредагувати вихідне ім'я інсталятора, клацнувши правою кнопкою миші проект Installer у своєму рішенні та виберіть Властивості. Змініть "Ім'я вихідного файлу:" на те, що ви хочете. Вибираючи проект установки , а також і дивлячись на вікна властивостей, ви можете редагувати Product Name, Title, Manufacturerі т.д. ...

Далі побудуйте інсталятор, і він створить MSI та setup.exe. Виберіть те, що ви хочете використовувати для розгортання вашої послуги.


37
@El Ronnoco, у мене була відповідь задовго до публікації. Я хотів зафіксувати це тут, тому що мені завжди доводиться шукати його кожні 6 - 12 місяців (а це було не так просто знайти), тому тепер у мене це легко знайти для всіх, і я можу швидко знайти його :)
Келсі

1
На жаль, це також неправильна відповідь. Так, я знаю, що ви знайдете це в книгах і MSDN, але це випадок, коли одна група в Microsoft не спілкувалася з іншою групою в Microsoft і придумала неповноцінне рішення проблеми, яка вже була вирішена. Для отримання додаткової інформації див. Blog.iswix.com/2006/07/msi-vs-net.html .
Крістофер Художник

9
@Christopher Painter Я використовую інсталятор MS з2k5, і у нього ніколи не було проблем. Погоджуєтесь ви з цим чи ні, і вважаєте це "антидіаграмою", це не суть цього питання, це як я роблю x з y, а не як робити a з b. Коли я опублікував питання, це було з метою документації.
Келсі

3
Тоді вам 6 років пощастило, ви просто цього не знаєте. Ви можете прочитати: robmensching.com/blog/posts/2007/4/19/…
Крістофер Художник

1
Якщо ви отримаєте Service name contains invalid characters, is empty, or is too long (max length = 80)помилку під час додавання програми встановлення, потім знову клацніть правою кнопкою миші в сірій області, перейдіть до Властивості та переконайтесь, що встановлено значення Імені служби.
wolfyuk

51

Я дотримуюся першого кроку Kelsey, щоб додати класи монтажу до мого сервісного проекту, але замість того, щоб створити інсталятор MSI або setup.exe, я змушую службу самостійно встановити / видалити. Ось трохи зразкового коду однієї з моїх служб, який ви можете використовувати як вихідний пункт.

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

1
З цікавості, яка користь від служби самостійного встановлення / видалення? Якщо служба встановлюється сама, як запустити її першою, щоб її можна було встановити в першу чергу? Якщо існує механізм запуску послуги без її встановлення, навіщо взагалі турбуватись про її встановлення?
Кілі Наро

3
@Christopher - я ні. Моє рішення не є заміною повного інсталятора, який ви використовували б для розповсюдження програмного забезпечення. Я представляю ще один варіант, який працює в деяких ситуаціях, наприклад, у моїй, коли я пишу програмне забезпечення, яке вбудовує вбудовані ПК у кіосках без нагляду.

4
Встановлюючи його на виробничу машину, не забудьте запустити його як адміністратор. Я створив файл BAT, який викликає файл EXE з параметром / i, але він не працював у виробничому середовищі, хоча я виконав BAT-файл як адміністратор. Мені довелося відкрити командний рядок як адміністратор і явно викликати файл EXE / i (без використання файлу BAT). Принаймні, це сталося зі мною на Windows Server 2012.
Франциско Голденштейн

1
RE: Відсутній вихід у командному рядку. Використання VS 2017 Спільнота мій новий проект служби по замовчуванням для типу виведення: Windows Applicationі об'єкта запуску: (none). Мені довелося змінити тип вихідного сигналу Console Applicationі встановити свій об'єкт запуску, наприклад myservice.Program. Якщо можуть бути наслідки, про які я не знаю, будь ласка, порадьте.
Джонатан

1
Чи є в прикладі код помилки друку? Чому існують три служби різниці (CSMessageQueueService, MyService, MyQueueService)?
Nils Guillermin

27

Ні рішення Келсі, ні Брендан не працюють для мене у спільноті Visual Studio 2015.

Ось мої короткі кроки, як створити сервіс з інсталятором:

  1. Запустіть Visual Studio, перейдіть до File->New->Project
  2. Виберіть .NET Framework 4 у розділі "Шукати встановлені шаблони" типу "Служба"
  3. Виберіть "Служба Windows". Введіть назву та місцезнаходження. Натисніть OK.
  4. Двічі клацніть Service1.cs, клацніть правою кнопкою миші на дизайнері та виберіть "Додати інсталятора"
  5. Двічі клацніть ProjectInstaller.cs. Для serviceProcessInstaller1 відкрийте вкладку "Властивості" та змініть значення властивості "Обліковий запис" на "LocalService". Для serviceInstaller1 змініть 'ServiceName' та встановіть 'StartType' на 'Automatic'.
  6. Двічі клацніть serviceInstaller1. Visual Studio створює serviceInstaller1_AfterInstallподії. Написати код:

    private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
    {
        using (System.ServiceProcess.ServiceController sc = new 
        System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName))
        {
            sc.Start();
        }
    }
    
  7. Будувати рішення. Клацніть правою кнопкою миші на проект і виберіть «Відкрити папку у провіднику файлів». Перейдіть до бін \ налагодження .

  8. Створіть install.bat зі скриптом нижче:

    :::::::::::::::::::::::::::::::::::::::::
    :: 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. Створіть файл uninstall.bat (змініть рядок pen-ult /iна /u)
  10. Щоб встановити та запустити службу, запустіть install.bat, щоб зупинити та видалити запуск uninstall.bat

14

Для VS2017 вам потрібно буде додати розширення VS "Проекти інсталятора Microsoft Visual Studio 2017". Це дасть вам додаткові шаблони проектів Visual Studio Installer. https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.MicrosoftVisualStudio2017InstallerProjects#overview

Щоб встановити службу Windows, ви можете додати новий проект типу майстра налаштування та виконувати кроки з відповіді Kelsey https://stackoverflow.com/a/9021107/1040040


1

Класи InstallUtil (ServiceInstaller) вважаються анти-зразком спільнотою Windows Installer. Це неміцне, позадувельне вигадування колеса, що ігнорує той факт, що Windows Installer має вбудовану підтримку служб.

Проекти розгортання Visual Studio (також не високо оцінені та застарілі в наступному випуску Visual Studio) не мають вбудованої підтримки служб. Але вони можуть споживати модулі злиття. Отож, я перегляну цю статтю в блозі, щоб зрозуміти, як створити модуль злиття за допомогою Windows Installer XML, який може виразити послугу, а потім споживати цей модуль злиття у вашому рішенні VDPROJ.

Розширення InstallShield за допомогою Windows Installer XML - Служби Windows

Навчальний посібник з сервісу IsWiX Windows

IsWiX Windows Service Video


1
У старій Visual Studio був проект розгортання, з легким інсталятором. Тепер мені потрібно придбати сторонні програмний компонент?
Олексій Обухов

@AlexeyObukhov Ви можете користуватися Wix безкоштовно, саме цим і VS користується, але проблема з Wix така ж, як і проблема з Git - майже вертикальною кривою навчання.
Алан Б
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.