Cara membuat penginstal untuk .net Layanan Windows menggunakan Visual Studio

Jawaban:

227

Dalam proyek layanan lakukan hal berikut:

  1. Dalam solusi, klik dua kali layanan Anda .cs file. Seharusnya memunculkan layar yang semuanya abu-abu dan berbicara tentang menyeret hal-hal dari kotak peralatan.
  2. Kemudian klik kanan pada area abu-abu dan pilih add installer. Ini akan menambahkan file proyek penginstal ke proyek Anda.
  3. Kemudian Anda akan memiliki 2 komponen pada tampilan desain ProjectInstaller.cs (serviceProcessInstaller1 dan serviceInstaller1). Anda kemudian harus mengatur properti yang Anda butuhkan seperti nama layanan dan pengguna yang seharusnya dijalankan.

Sekarang Anda perlu membuat proyek pengaturan. Hal terbaik untuk dilakukan adalah menggunakan wizard pengaturan.

  1. Klik kanan pada solusi Anda dan tambahkan proyek baru: Tambah> Proyek Baru> Setup dan Deployment Projects> Setup Wizard

    Sebuah. Ini bisa sedikit berbeda untuk versi Visual Studio yang berbeda. b. Visual Studio 2010 terletak di: Instal Template> Jenis Proyek Lainnya> Pengaturan dan Penempatan> Pemasang Visual Studio

  2. Pada langkah kedua pilih "Buat Pengaturan untuk Aplikasi Windows."

  3. Pada langkah ke-3, pilih "Output primer dari ..."

  4. Klik untuk Selesai.

Selanjutnya edit installer Anda untuk memastikan output yang benar disertakan.

  1. Klik kanan pada proyek pengaturan di Solution Explorer Anda.
  2. Pilih Lihat> Tindakan Kustom. (Dalam VS2008 itu mungkin Lihat> Editor> Tindakan Kustom)
  3. Klik kanan pada tindakan Instal di pohon Tindakan Kustom dan pilih 'Tambahkan Tindakan Kustom ...'
  4. Dalam dialog "Pilih Item dalam Proyek", pilih Folder Aplikasi dan klik OK.
  5. Klik OK untuk memilih opsi "Output utama dari ...". Node baru harus dibuat.
  6. Ulangi langkah 4 - 5 untuk tindakan komit, kembalikan, dan hapus instalan.

Anda dapat mengedit nama output pemasang dengan mengklik kanan proyek Installer di solusi Anda dan pilih Properties. Ubah 'Nama file keluaran:' menjadi apa pun yang Anda inginkan. Dengan memilih proyek installer juga dan melihat jendela properti, Anda dapat mengedit Product Name, Title, Manufacturer, dll ...

Selanjutnya buat installer Anda dan itu akan menghasilkan MSI dan setup.exe. Pilih mana yang ingin Anda gunakan untuk menggunakan layanan Anda.

Kelsey
sumber
37
@ El Ronnoco, saya punya jawabannya jauh sebelum saya kirim. Saya ingin mendokumentasikannya di sini karena saya selalu harus mencarinya setiap 6 - 12 bulan (dan itu tidak mudah ditemukan) jadi sekarang saya dapat dengan mudah dicari untuk semua orang dan saya dapat menemukannya sendiri dengan cepat :)
Kelsey
1
Sayangnya, itu juga jawaban yang salah. Ya, saya tahu Anda akan menemukan ini di buku dan MSDN, tetapi ini merupakan kasus di mana satu grup di Microsoft tidak berbicara dengan grup lain di Microsoft dan muncul dengan solusi yang lebih rendah untuk masalah yang sudah dipecahkan. Lihat blog.iswix.com/2006/07/msi-vs-net.html untuk informasi lebih lanjut.
Christopher Painter
9
@Christopher Painter Saya telah menggunakan installer MS sejak2k5 dan tidak pernah memiliki masalah. Apakah Anda setuju atau tidak dan menganggapnya sebagai 'anti-pola' bukanlah inti dari pertanyaan ini, itu adalah bagaimana saya melakukannya x dengan y, bukan bagaimana saya melakukan a dengan b. Ketika saya memposting pertanyaan itu untuk keperluan dokumentasi.
Kelsey
3
Maka Anda sudah beruntung selama 6 tahun Anda tidak tahu itu. Anda mungkin ingin membaca: robmensching.com/blog/posts/2007/4/19/…
Christopher Painter
1
Jika Anda mendapatkan Service name contains invalid characters, is empty, or is too long (max length = 80)kesalahan saat menambahkan Penginstal lalu klik kanan di area abu-abu lagi, buka Properti dan pastikan bahwa nilai Nama Layanan diatur.
wolfyuk
51

Saya mengikuti serangkaian langkah pertama Kelsey untuk menambahkan kelas pemasang ke proyek layanan saya, tetapi alih-alih membuat penginstal MSI atau setup.exe, saya membuat layanan pemasangan / penghapusan sendiri. Berikut sedikit kode sampel dari salah satu layanan saya yang dapat Anda gunakan sebagai titik awal.

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

sumber
1
Karena penasaran, apa manfaatnya memiliki layanan memasang sendiri / tidak memasang? Jika layanan menginstal sendiri, bagaimana Anda memulai layanan yang pertama sehingga dapat diinstal di tempat pertama? Jika ada mekanisme untuk memulai layanan tanpa menginstalnya, mengapa repot-repot menginstalnya sama sekali?
Kiley Naro
3
@ Christopher - Saya tidak. Solusi saya bukan pengganti installer lengkap yang akan Anda gunakan untuk mendistribusikan perangkat lunak. Saya menghadirkan opsi lain yang berfungsi untuk beberapa situasi, seperti milik saya di mana saya menulis perangkat lunak yang mendorong PC tertanam di kios yang tidak dijaga.
4
Ketika Anda menginstalnya pada mesin produksi, ingatlah untuk menjalankannya sebagai administrator. Saya membuat file BAT yang memanggil file EXE dengan parameter / i tetapi tidak berfungsi pada lingkungan produksi, meskipun saya mengeksekusi file BAT sebagai administrator. Saya harus membuka prompt baris perintah sebagai administrator dan meminta file EXE / i secara eksplisit (tanpa menggunakan file BAT). Setidaknya itu terjadi pada saya di Windows Server 2012.
Francisco Goldenstein
1
RE: Tidak Ada Output di Command Line. Menggunakan VS 2017 Komunitas proyek layanan baru saya gagal untuk jenis Output: Windows Applicationdan objek Startup: (none). Saya harus mengubah tipe Output ke Console Applicationdan mengatur objek startup saya misalnya myservice.Program. Jika mungkin ada konsekuensi yang tidak saya sadari, mohon saran.
Jonathan
1
Apakah kode contoh memiliki kesalahan ketik? Mengapa ada tiga layanan perbedaan (CSMessageQueueService, MyService, MyQueueService)?
Nils Guillermin
27

Nor Kelsey, atau solusi Brendan tidak berfungsi untuk saya di Visual Studio 2015 Community.

Inilah langkah-langkah singkat saya bagaimana cara membuat layanan dengan installer:

  1. Jalankan Visual Studio, Pergi ke File->New->Project
  2. Pilih .NET Framework 4, di 'Cari Template yang Dipasang' ketik 'Layanan'
  3. Pilih 'Layanan Windows'. Ketik Nama dan Lokasi. Tekan OK.
  4. Klik dua kali Service1.cs, klik kanan pada designer dan pilih 'Add Installer'
  5. Klik dua kali ProjectInstaller.cs. Untuk serviceProcessInstaller1 buka tab Properti dan ubah nilai properti 'Akun' menjadi 'Layanan Lokal'. Untuk serviceInstaller1 ubah 'ServiceName' dan atur 'StartType' menjadi 'Automatic'.
  6. Klik dua kali serviceInstaller1. Visual Studio menciptakan serviceInstaller1_AfterInstallacara. Tulis kode:

    private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
    {
        using (System.ServiceProcess.ServiceController sc = new 
        System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName))
        {
            sc.Start();
        }
    }
  7. Bangun solusi. Klik kanan pada proyek dan pilih 'Buka Folder di File Explorer'. Pergi ke bin \ Debug .

  8. Buat install.bat dengan skrip di bawah ini:

    :::::::::::::::::::::::::::::::::::::::::
    :: 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. Buat file uninstall.bat (ubah baris pena-ult /ike /u)
  10. Untuk menginstal dan memulai layanan, jalankan install.bat, untuk berhenti dan hapus instalan, jalankan uninstall.bat
Alexey Obukhov
sumber
14

Untuk VS2017 Anda perlu menambahkan ekstensi VS "Microsoft Visual Studio 2017 Installer Projects". Ini akan memberi Anda templat proyek Visual Studio Installer tambahan. https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.MicrosoftVisualStudio2017InstallerProjects#overview

Untuk menginstal layanan windows Anda dapat menambahkan proyek jenis setup wizard baru dan ikuti langkah-langkah dari jawaban Kelsey https://stackoverflow.com/a/9021107/1040040

JustSomeDev
sumber
1

Kelas InstallUtil (ServiceInstaller) dianggap sebagai anti-pola oleh komunitas Pemasang Windows. Ini rapuh, keluar dari proses, menciptakan kembali roda yang mengabaikan fakta bahwa Pemasang Windows memiliki dukungan bawaan untuk Layanan.

Proyek-proyek penyebaran Visual Studio (juga tidak begitu dihargai dan ditinggalkan dalam rilis Visual Studio berikutnya) tidak memiliki dukungan asli untuk layanan. Tetapi mereka dapat mengkonsumsi modul gabungan. Jadi saya akan melihat artikel blog ini untuk memahami cara membuat modul gabungan menggunakan Windows Installer XML yang dapat mengekspresikan layanan dan kemudian menggunakan modul gabungan itu dalam solusi VDPROJ Anda.

Augmenting InstallShield menggunakan Windows Installer XML - Layanan Windows

Tutorial Layanan Windows IsWiX

IsWiX Windows Service Video

Christopher Painter
sumber
1
Di Visual Studio lama ada proyek penyebaran, dengan installer pembuatan mudah. Sekarang saya harus membeli komponen perangkat lunak pihak ketiga?
Alexey Obukhov
@AlexeyObukhov Anda dapat menggunakan Wix secara gratis, itulah yang digunakan VS sendiri, tetapi masalah dengan Wix sama dengan masalah dengan Git - kurva belajar vertikal dekat.
Alan B