Antworten:
Gehen Sie im Serviceprojekt wie folgt vor:
Jetzt müssen Sie ein Setup-Projekt erstellen. Verwenden Sie am besten den Setup-Assistenten.
Klicken Sie mit der rechten Maustaste auf Ihre Lösung und fügen Sie ein neues Projekt hinzu: Hinzufügen> Neues Projekt> Setup- und Bereitstellungsprojekte> Setup-Assistent
ein. Dies kann für verschiedene Versionen von Visual Studio leicht variieren. b. Visual Studio 2010 befindet sich unter: Vorlagen installieren> Andere Projekttypen> Setup und Bereitstellung> Visual Studio Installer
Wählen Sie im zweiten Schritt "Setup für eine Windows-Anwendung erstellen".
Wählen Sie im 3. Schritt "Primäre Ausgabe von ...".
Klicken Sie sich durch, um fertig zu werden.
Bearbeiten Sie als Nächstes Ihr Installationsprogramm, um sicherzustellen, dass die richtige Ausgabe enthalten ist.
Sie können den Namen der Installationsausgabe bearbeiten, indem Sie mit der rechten Maustaste auf das Installationsprojekt in Ihrer Lösung klicken und Eigenschaften auswählen. Ändern Sie den Namen der Ausgabedatei: in einen beliebigen Wert. Durch die Auswahl als auch das Installationsprojekt und suchen Sie in den Eigenschaften - Fenster, können Sie bearbeiten die Product Name
, Title
, Manufacturer
usw ...
Erstellen Sie als Nächstes Ihr Installationsprogramm, und es werden eine MSI und eine setup.exe erstellt. Wählen Sie aus, was Sie zum Bereitstellen Ihres Dienstes verwenden möchten.
Service name contains invalid characters, is empty, or is too long (max length = 80)
beim Hinzufügen des Installationsprogramms eine Fehlermeldung angezeigt wird, klicken Sie erneut mit der rechten Maustaste in den grauen Bereich, gehen Sie zu Eigenschaften und stellen Sie sicher, dass der Wert für den Dienstnamen festgelegt ist.
Ich folge Kelseys ersten Schritten, um die Installationsklassen zu meinem Serviceprojekt hinzuzufügen, aber anstatt ein MSI- oder setup.exe-Installationsprogramm zu erstellen, mache ich den Service selbstinstallierend / deinstallierend. Hier ist ein Beispielcode von einem meiner Dienste, den Sie als Ausgangspunkt verwenden können.
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
und Startobjekt : (none)
. Ich musste den Ausgabetyp ändern Console Application
und mein Startobjekt festlegen, z myservice.Program
. Wenn es Konsequenzen gibt, von denen ich nichts weiß, teilen Sie uns dies bitte mit.
Weder Kelsey- noch Brendan-Lösungen funktionieren für mich in der Visual Studio 2015-Community nicht.
Hier sind meine kurzen Schritte zum Erstellen eines Dienstes mit dem Installationsprogramm:
->
New->
ProjectDoppelklicken Sie auf serviceInstaller1. Visual Studio erstellt ein serviceInstaller1_AfterInstall
Ereignis. Code schreiben:
private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
{
using (System.ServiceProcess.ServiceController sc = new
System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName))
{
sc.Start();
}
}
Lösung erstellen. Klicken Sie mit der rechten Maustaste auf das Projekt und wählen Sie "Ordner im Datei-Explorer öffnen". Gehen Sie zu bin \ Debug .
Erstellen Sie install.bat mit dem folgenden Skript:
:::::::::::::::::::::::::::::::::::::::::
:: 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
)Für VS2017 müssen Sie die VS-Erweiterung "Microsoft Visual Studio 2017 Installer Projects" hinzufügen. Dadurch erhalten Sie zusätzliche Visual Studio Installer-Projektvorlagen. https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.MicrosoftVisualStudio2017InstallerProjects#overview
Um den Windows-Dienst zu installieren, können Sie ein neues Projekt vom Typ Setup-Assistent hinzufügen und die Schritte aus Kelseys Antwort https://stackoverflow.com/a/9021107/1040040 ausführen
InstallUtil-Klassen (ServiceInstaller) werden von der Windows Installer-Community als Anti-Pattern angesehen. Es ist eine fragile, außer Betrieb befindliche Neuerfindung des Rads, die die Tatsache ignoriert, dass Windows Installer integrierte Unterstützung für Dienste bietet.
Visual Studio-Bereitstellungsprojekte (auch in der nächsten Version von Visual Studio nicht hoch angesehen und veraltet) bieten keine native Unterstützung für Dienste. Sie können jedoch Zusammenführungsmodule verbrauchen. Ich würde mir diesen Blog-Artikel ansehen, um zu verstehen, wie ein Zusammenführungsmodul mit Windows Installer XML erstellt wird, das den Dienst ausdrücken und dieses Zusammenführungsmodul dann in Ihrer VDPROJ-Lösung verwenden kann.
Erweitern von InstallShield mithilfe von Windows Installer XML - Windows Services