Risposte:
Nel progetto di servizio procedi come segue:
Ora devi creare un progetto di installazione. La cosa migliore da fare è utilizzare la procedura guidata di configurazione.
Fare clic con il tasto destro del mouse sulla soluzione e aggiungere un nuovo progetto: Aggiungi> Nuovo progetto> Progetti di installazione e distribuzione> Installazione guidata
un. Ciò potrebbe variare leggermente per le diverse versioni di Visual Studio. b. Visual Studio 2010 si trova in: Modelli di installazione> Altri tipi di progetto> Installazione e distribuzione> Programma di installazione di Visual Studio
Nel secondo passaggio selezionare "Crea un'installazione per un'applicazione Windows".
Al 3 ° passaggio, selezionare "Output primario da ..."
Fai clic per finire.
Quindi modifica il tuo programma di installazione per assicurarti che sia incluso l'output corretto.
È possibile modificare il nome dell'output del programma di installazione facendo clic con il pulsante destro del mouse sul progetto Installer nella soluzione e selezionare Proprietà. Cambia il 'Nome del file di output:' come preferisci. Selezionando il progetto di installazione come bene e guardando le proprietà di Windows, è possibile modificare il Product Name
, Title
, Manufacturer
, ecc ...
Successivamente costruisci il tuo programma di installazione e produrrà un MSI e un setup.exe. Scegli quello che vuoi usare per distribuire il tuo servizio.
Service name contains invalid characters, is empty, or is too long (max length = 80)
errore durante l'aggiunta del programma di installazione, fare nuovamente clic con il pulsante destro del mouse nell'area grigia, andare su Proprietà e assicurarsi che il valore del nome del servizio sia impostato.
Seguo la prima serie di passaggi di Kelsey per aggiungere le classi del programma di installazione al mio progetto di servizio, ma invece di creare un programma di installazione MSI o setup.exe, il servizio viene autoinstallato / disinstallato. Ecco un po 'di codice di esempio da uno dei miei servizi che puoi usare come punto di partenza.
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
e oggetto di avvio: (none)
. Ho dovuto cambiare il tipo di output Console Application
e impostare il mio oggetto di avvio, ad es myservice.Program
. Se potrebbero esserci delle ramificazioni di cui non sono a conoscenza, si prega di avvisare.
Né Kelsey, né le soluzioni Brendan non funzionano per me nella community di Visual Studio 2015.
Ecco i miei brevi passaggi su come creare un servizio con l'installer:
->
New->
ProjectFare doppio clic su serviceInstaller1. Visual Studio crea un serviceInstaller1_AfterInstall
evento. Scrivi il codice:
private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
{
using (System.ServiceProcess.ServiceController sc = new
System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName))
{
sc.Start();
}
}
Crea soluzione. Fare clic con il tasto destro del mouse sul progetto e selezionare "Apri cartella in Esplora file". Vai a bin \ Debug .
Crea install.bat con lo script seguente:
:::::::::::::::::::::::::::::::::::::::::
:: 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
in /u
)Per VS2017 dovrai aggiungere l'estensione VS "Progetti di installazione di Microsoft Visual Studio 2017". Ciò fornirà ulteriori modelli di progetto del programma di installazione di Visual Studio. https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.MicrosoftVisualStudio2017InstallerProjects#overview
Per installare il servizio Windows è possibile aggiungere un nuovo progetto di tipo procedura guidata e seguire i passaggi dalla risposta di Kelsey https://stackoverflow.com/a/9021107/1040040
Le classi InstallUtil (ServiceInstaller) sono considerate anti-pattern dalla community di Windows Installer. È un reinventamento fragile, fuori processo, che ignora il fatto che Windows Installer ha un supporto integrato per i servizi.
I progetti di distribuzione di Visual Studio (anche non molto apprezzati e deprecati nella prossima versione di Visual Studio) non dispongono di supporto nativo per i servizi. Ma possono consumare moduli di unione. Quindi darei un'occhiata a questo articolo del blog per capire come creare un modulo di unione utilizzando XML di Windows Installer in grado di esprimere il servizio e quindi utilizzare quel modulo di unione nella soluzione VDPROJ.
Aumentare InstallShield utilizzando XML di Windows Installer - Servizi di Windows