Odpowiedzi:
W projekcie usługi wykonaj następujące czynności:
Teraz musisz wykonać projekt konfiguracji. Najlepszą rzeczą do zrobienia jest skorzystanie z kreatora konfiguracji.
Kliknij prawym przyciskiem myszy rozwiązanie i dodaj nowy projekt: Dodaj> Nowy projekt> Projekty konfiguracji i wdrażania> Kreator instalacji
za. Może się to nieznacznie różnić w przypadku różnych wersji programu Visual Studio. b. Visual Studio 2010 znajduje się w: Zainstaluj szablony> Inne typy projektów> Konfiguracja i wdrażanie> Instalator programu Visual Studio
W drugim kroku wybierz „Utwórz konfigurację aplikacji dla systemu Windows”.
W trzecim kroku wybierz „Wyjście podstawowe z ...”
Kliknij, aby zakończyć.
Następnie wyedytuj instalator, aby upewnić się, że zawiera poprawne wyjście.
Możesz edytować nazwę wyjściową instalatora, klikając prawym przyciskiem myszy projekt Instalatora w rozwiązaniu i wybierając opcję Właściwości. Zmień „Nazwę pliku wyjściowego:” na dowolną. Po wybraniu projektu instalatora, jak również i patrząc w okna właściwości można edytować Product Name
, Title
, Manufacturer
, itd ...
Następnie skompiluj instalator, który utworzy plik MSI i plik setup.exe. Wybierz dowolną, której chcesz użyć do wdrożenia usługi.
Service name contains invalid characters, is empty, or is too long (max length = 80)
podczas dodawania Instalatora pojawi się błąd, kliknij ponownie prawym przyciskiem myszy w szarym obszarze, przejdź do Właściwości i upewnij się, że ustawiona jest wartość Nazwa usługi.
Postępuję zgodnie z pierwszym zestawem kroków Kelsey, aby dodać klasy instalatora do mojego projektu usługi, ale zamiast tworzyć instalator MSI lub setup.exe, wykonuję usługę samoczynnie instalując / odinstalowując. Oto fragment przykładowego kodu z jednej z moich usług, którego możesz użyć jako punktu wyjścia.
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;
}
Windows Application
a przedmiotem Startup: (none)
. Musiałem zmienić typ wyjścia na Console Application
i ustawić mój obiekt startowy np myservice.Program
. Jeśli mogą istnieć konsekwencje, których nie jestem świadomy, proszę o poradę.
Ani rozwiązania Kelsey, ani Brendan nie działają dla mnie w społeczności Visual Studio 2015.
Oto moje krótkie kroki, jak utworzyć usługę za pomocą instalatora:
->
New->
ProjectKliknij dwukrotnie serviceInstaller1. Visual Studio tworzy serviceInstaller1_AfterInstall
zdarzenie. Wpisz kod:
private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
{
using (System.ServiceProcess.ServiceController sc = new
System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName))
{
sc.Start();
}
}
Zbuduj rozwiązanie. Kliknij prawym przyciskiem myszy projekt i wybierz „Otwórz folder w Eksploratorze plików”. Przejdź do bin \ Debug .
Utwórz plik install.bat z poniższym skryptem:
:::::::::::::::::::::::::::::::::::::::::
:: 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
/i
na /u
)W przypadku VS2017 należy dodać rozszerzenie VS „Projekty instalatora Microsoft Visual Studio 2017”. Zapewni to dodatkowe szablony projektów Instalatora programu Visual Studio. https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.MicrosoftVisualStudio2017InstallerProjects#overview
Aby zainstalować usługę Windows, możesz dodać nowy projekt typu kreatora konfiguracji i postępować zgodnie z instrukcjami zawartymi w odpowiedzi Kelsey https://stackoverflow.com/a/9021107/1040040
Klasy InstallUtil (ServiceInstaller) są uważane przez społeczność Instalatorów Windows za anty-wzorzec. Jest to kruche wymyślenie na nowo koła, które ignoruje fakt, że Instalator Windows ma wbudowaną obsługę usług.
Projekty wdrożeniowe programu Visual Studio (również niezbyt cenione i przestarzałe w następnej wersji programu Visual Studio) nie mają natywnej obsługi usług. Ale mogą zużywać moduły scalające. Dlatego chciałbym rzucić okiem na ten artykuł na blogu, aby zrozumieć, jak utworzyć moduł scalający za pomocą pliku XML Instalatora Windows, który może wyrazić usługę, a następnie wykorzystać ten moduł scalający w rozwiązaniu VDPROJ.
Rozszerzanie programu InstallShield przy użyciu programu Windows Installer XML - usługi Windows