Respuestas:
En el proyecto de servicio, haga lo siguiente:
Ahora necesita hacer un proyecto de configuración. Lo mejor que puede hacer es usar el asistente de configuración.
Haga clic derecho en su solución y agregue un nuevo proyecto: Agregar> Nuevo proyecto> Proyectos de configuración e implementación> Asistente de configuración
a. Esto podría variar ligeramente para diferentes versiones de Visual Studio. si. Visual Studio 2010 se encuentra en: Plantillas de instalación> Otros tipos de proyectos> Configuración e implementación> Instalador de Visual Studio
En el segundo paso, seleccione "Crear una configuración para una aplicación de Windows".
En el tercer paso, seleccione "Salida primaria de ..."
Haga clic para finalizar.
Luego edite su instalador para asegurarse de que se incluye la salida correcta.
Puede editar el nombre de salida del instalador haciendo clic derecho en el proyecto Instalador en su solución y seleccionando Propiedades. Cambie el 'Nombre del archivo de salida:' a lo que quiera. Al seleccionar el proyecto de instalación, así y mirando a las ventanas de propiedades, puede editar el Product Name
, Title
, Manufacturer
, etc ...
Luego construya su instalador y producirá un MSI y un setup.exe. Elija el que quiera usar para implementar su servicio.
Service name contains invalid characters, is empty, or is too long (max length = 80)
error al agregar el instalador, haga clic derecho en el área gris nuevamente, vaya a Propiedades y asegúrese de que el valor del Nombre del servicio esté configurado.
Sigo los primeros pasos de Kelsey para agregar las clases de instalador a mi proyecto de servicio, pero en lugar de crear un instalador MSI o setup.exe, hago que el servicio se instale / desinstale automáticamente. Aquí hay un poco de código de muestra de uno de mis servicios que puede usar como punto de partida.
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
y el objeto de inicio: (none)
. Tuve que cambiar el tipo de salida Console Application
y establecer mi objeto de inicio, por ejemplo myservice.Program
. Si puede haber ramificaciones que desconozco, por favor avise.
Ni Kelsey, ni las soluciones de Brendan no me funcionan en Visual Studio 2015 Community.
Aquí están mis breves pasos sobre cómo crear un servicio con el instalador:
->
New->
ProjectHaga doble clic en serviceInstaller1. Visual Studio crea serviceInstaller1_AfterInstall
eventos. Escribir código:
private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
{
using (System.ServiceProcess.ServiceController sc = new
System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName))
{
sc.Start();
}
}
Construir solución. Haga clic derecho en el proyecto y seleccione 'Abrir carpeta en el Explorador de archivos'. Vaya a bin \ Debug .
Cree install.bat con el siguiente script:
:::::::::::::::::::::::::::::::::::::::::
:: 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
a /u
)Para VS2017, deberá agregar la extensión VS "Proyectos del instalador de Microsoft Visual Studio 2017". Esto le dará plantillas de proyecto adicionales del instalador de Visual Studio. https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.MicrosoftVisualStudio2017InstallerProjects#overview
Para instalar el servicio de Windows, puede agregar un nuevo proyecto tipo asistente de configuración y seguir los pasos de la respuesta de Kelsey https://stackoverflow.com/a/9021107/1040040
Las clases InstallUtil (ServiceInstaller) son consideradas un antipatrón por la comunidad de Windows Installer. Es una reinvención de la rueda frágil, fuera de proceso, que ignora el hecho de que Windows Installer tiene soporte incorporado para los Servicios.
Los proyectos de implementación de Visual Studio (que tampoco se consideran ni se consideran en desuso en la próxima versión de Visual Studio) no tienen soporte nativo para los servicios. Pero pueden consumir módulos de fusión. Por lo tanto, echaría un vistazo a este artículo de blog para comprender cómo crear un módulo de combinación utilizando Windows Installer XML que pueda expresar el servicio y luego consumir ese módulo de combinación en su solución VDPROJ.
Aumento de InstallShield utilizando Windows Installer XML - Servicios de Windows