Respostas:
No projeto de serviço, faça o seguinte:
Agora você precisa fazer um projeto de instalação. A melhor coisa a fazer é usar o assistente de instalação.
Clique com o botão direito do mouse na sua solução e adicione um novo projeto: Adicionar> Novo Projeto> Projetos de Configuração e Implantação> Assistente de Configuração
uma. Isso pode variar um pouco para diferentes versões do Visual Studio. b. O Visual Studio 2010 está localizado em: Modelos de Instalação> Outros Tipos de Projeto> Instalação e Implantação> Instalador do Visual Studio
Na segunda etapa, selecione "Criar uma instalação para um aplicativo do Windows".
Na terceira etapa, selecione "Saída primária de ..."
Clique em para concluir.
Em seguida, edite seu instalador para garantir que a saída correta esteja incluída.
Você pode editar o nome da saída do instalador clicando com o botão direito do mouse no projeto Installer em sua solução e selecione Propriedades. Mude o 'Nome do arquivo de saída:' para o que quiser. Selecionando o projeto instalador bem e olhando para as janelas de propriedades, você pode editar o Product Name
, Title
, Manufacturer
, etc ...
Em seguida, crie seu instalador e ele produzirá um MSI e um setup.exe. Escolha o que você deseja usar para implantar seu serviço.
Service name contains invalid characters, is empty, or is too long (max length = 80)
erro ao adicionar o Instalador, clique com o botão direito do mouse na área cinza novamente, vá para Propriedades e verifique se o valor Nome do Serviço está definido.
Sigo as primeiras etapas de Kelsey para adicionar as classes do instalador ao meu projeto de serviço, mas, em vez de criar um instalador MSI ou setup.exe, eu faço o serviço instalando / desinstalando automaticamente. Aqui está um pouco de código de exemplo de um dos meus serviços que você pode usar como ponto 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
e objeto de inicialização: (none)
. Eu tive que mudar o tipo de saída para Console Application
e definir meu objeto de inicialização, por exemplo myservice.Program
. Se houver ramificações que eu não saiba, por favor, informe.
As soluções Kelsey e Brendan não funcionam para mim na Comunidade do Visual Studio 2015.
Aqui estão minhas breves etapas como criar serviço com o instalador:
->
New->
ProjectClique duas vezes em serviceInstaller1. Visual Studio cria serviceInstaller1_AfterInstall
evento. Escreva o código:
private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
{
using (System.ServiceProcess.ServiceController sc = new
System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName))
{
sc.Start();
}
}
Compilar solução. Clique com o botão direito do mouse no projeto e selecione 'Abrir pasta no File Explorer'. Vá para bin \ Debug .
Crie install.bat com o script abaixo:
:::::::::::::::::::::::::::::::::::::::::
:: 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
para /u
)Para o VS2017, você precisará adicionar a extensão VS "Microsoft Visual Studio 2017 Installer Projects". Isso fornecerá modelos de projeto adicionais do Visual Studio Installer. https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.MicrosoftVisualStudio2017InstallerProjects#overview
Para instalar o serviço Windows, você pode adicionar um novo projeto do tipo assistente de configuração e siga as etapas da resposta de Kelsey https://stackoverflow.com/a/9021107/1040040
As classes InstallUtil (ServiceInstaller) são consideradas um antipadrão pela comunidade do Windows Installer. É uma reinvenção da roda frágil e fora de processo que ignora o fato de o Windows Installer ter suporte interno para os Serviços.
Os projetos de implantação do Visual Studio (também não são altamente considerados e preteridos na próxima versão do Visual Studio) não têm suporte nativo para serviços. Mas eles podem consumir módulos de mesclagem. Então, eu daria uma olhada neste artigo do blog para entender como criar um módulo de mesclagem usando o Windows Installer XML que pode expressar o serviço e, em seguida, consumir esse módulo de mesclagem na sua solução VDPROJ.
Aprimorando o InstallShield usando o Windows Installer XML - Serviços do Windows