Então, nós produzimos um serviço do Windows para alimentar nossos aplicativos cliente e tudo está indo muito bem. O cliente apresentou uma solicitação de configuração divertida que requer duas instâncias desse serviço em execução no mesmo servidor e configuradas para apontar para bancos de dados separados.
Até agora, não consegui fazer isso acontecer e esperava que meus colegas membros do stackoverflow pudessem dar algumas dicas do porquê.
Configuração atual:
Eu configurei o projeto que contém o serviço do Windows, vamos chamá-lo de AppService de agora em diante, e o arquivo ProjectInstaller.cs que lida com as etapas de instalação personalizadas para definir o nome do serviço com base em uma chave no App.config assim :
this.serviceInstaller1.ServiceName = Util.ServiceName;
this.serviceInstaller1.DisplayName = Util.ServiceName;
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
Nesse caso, Util é apenas uma classe estática que carrega o nome do serviço do arquivo de configuração.
Daqui em diante, tentei duas maneiras diferentes de instalar os dois serviços e ambos falharam de maneira idêntica.
A primeira maneira era simplesmente instalar a primeira cópia do serviço, copiar o diretório instalado e renomeá-lo e, em seguida, executar o seguinte comando após modificar a configuração do aplicativo para alterar o nome do serviço desejado:
InstallUtil.exe /i AppService.exe
Quando isso não funcionou, tentei criar um segundo projeto de instalador, editei o arquivo de configuração e construí o segundo instalador. Quando executei o instalador, ele funcionou bem, mas o serviço não apareceu em services.msc, então executei o comando anterior na segunda base de código instalada.
Ambas as vezes, recebi a seguinte saída do InstallUtil (somente peças relevantes):
Executando uma instalação transacionada.
Iniciando a fase de instalação da instalação.
Instalando o serviço App Service Two ... O Service App Service Two foi instalado com êxito. Criando EventLog fonte App Service Two no aplicativo de log ...
Ocorreu uma exceção durante a fase de instalação. System.NullReferenceException: Referência de objeto não definida para uma instância de um objeto.
A fase de reversão da instalação está começando.
Restaurando o log de eventos ao estado anterior para o App Service Two de origem. Aplicativo de serviço O serviço dois está sendo removido do sistema ... Aplicativo de serviço O serviço dois foi removido com êxito do sistema.
A fase de reversão foi concluída com sucesso.
A instalação transacionada foi concluída. A instalação falhou e o rollback foi executado.
Desculpe pela postagem prolixa, queria ter certeza de que há informações relevantes o suficiente. A parte que até agora me deixou perplexo é que ele afirma que a instalação do serviço foi concluída com êxito e só depois de criar a origem do EventLog é que a NullReferenceException parece ser lançada. Portanto, se alguém souber o que estou fazendo de errado ou tiver uma abordagem melhor, ficaria muito grato.
http://journalofasoftwaredev.wordpress.com/2008/07/16/multiple-instances-of-same-windows-service/
. Você pode inserir o código no instalador para obter o nome do serviço que deseja ao executar o installutil.Essa solução funcionou para mim.
fonte
[path to your exe]
tem que ser o caminho completo e não se esqueça do espaço depoisbinpath=
Você pode executar várias versões do mesmo serviço, fazendo o seguinte:
1) Copie o executável e a configuração do serviço para sua própria pasta.
2) Copie Install.Exe para a pasta executável do serviço (da pasta .net framework)
3) Crie um arquivo de configuração chamado Install.exe.config na pasta executável do serviço com o seguinte conteúdo (nomes de serviço exclusivos):
4) Crie um arquivo em lote para instalar o serviço com o seguinte conteúdo:
5) Enquanto estiver lá, crie um arquivo em lote de desinstalação
EDITAR:
Observe se eu perdi algo, aqui está a classe ServiceInstaller (ajuste conforme necessário):
fonte
Pergunta antiga, eu sei, mas tive sorte ao usar a opção / servicename em InstallUtil.exe. No entanto, não o vejo listado na ajuda integrada.
Não tenho certeza de onde li sobre isso pela primeira vez, mas não vi desde então. YMMV.
fonte
An exception occurred during the Install phase. System.ComponentModel.Win32Exception: The specified service already exists
Outra maneira rápida de especificar um valor personalizado para
ServiceName
eDisplayName
é usarinstallutil
parâmetros de linha de comando.Em sua
ProjectInstaller
classe, substitua métodos virtuaisInstall(IDictionary stateSaver)
eUninstall(IDictionary savedState)
Instale o serviço
installutil
adicionando seu nome personalizado usando o/servicename
parâmetro:Observe que se você não especificar
/servicename
na linha de comando, o serviço será instalado com os valores ServiceName e DisplayName especificados nas propriedades / configuração do ProjectInstallerfonte
Não tive muita sorte com os métodos acima ao usar nosso software de implantação automatizado para instalar / desinstalar frequentemente serviços do Windows lado a lado, mas acabei descobrindo o seguinte, que me permite passar um parâmetro para especificar um sufixo ao nome do serviço na linha de comando. Ele também permite que o designer funcione corretamente e pode ser facilmente adaptado para substituir o nome inteiro, se necessário.
Com isso em mente, posso fazer o seguinte: Se eu chamei o serviço de "Serviço incrível", posso instalar uma versão UAT do serviço da seguinte maneira:
InstallUtil.exe /ServiceSuffix="UAT" MyService.exe
Isso criará o serviço com o nome "Awesome Service - UAT". Usamos isso para executar versões DEVINT, TESTING e ACCEPTANCE do mesmo serviço em execução lado a lado em uma única máquina. Cada versão tem seu próprio conjunto de arquivos / configurações - não tentei fazer isso para instalar vários serviços apontando para o mesmo conjunto de arquivos.
NOTA: você deve usar o mesmo
/ServiceSuffix
parâmetro para desinstalar o serviço, então você executaria o seguinte para desinstalar:InstallUtil.exe /u /ServiceSuffix="UAT" MyService.exe
fonte
/ServiceSuffix="UAT"
é usado pelo instalador para definir o sufixo no serviço. No meu exemplo, o valor passado éUAT
. No meu cenário, eu só queria adicionar um sufixo ao nome existente do serviço, mas não há razão para você não poder adaptar isso para substituir o nome inteiramente pelo valor que é passado.O que fiz para fazer isso funcionar foi armazenar o nome do serviço e o nome de exibição em um app.config para meu serviço. Em seguida, em minha classe do instalador, carrego o app.config como um XmlDocument e uso xpath para obter os valores e aplicá-los a ServiceInstaller.ServiceName e ServiceInstaller.DisplayName, antes de chamar InitializeComponent (). Isso pressupõe que você ainda não está definindo essas propriedades em InitializeComponent (), caso em que as configurações de seu arquivo de configuração serão ignoradas. O código a seguir é o que estou chamando do meu construtor de classe do instalador, antes de InitializeComponent ():
Não acredito que a leitura do arquivo de configuração diretamente do ConfigurationManager.AppSettings ou algo semelhante funcione como quando o instalador é executado, ele é executado no contexto do InstallUtil.exe, não do .exe do seu serviço. Você pode conseguir fazer algo com ConfigurationManager.OpenExeConfiguration, no entanto, no meu caso, isso não funcionou porque estava tentando obter uma seção de configuração personalizada que não foi carregada.
fonte
Apenas para melhorar a resposta perfeita de @ chris.house.00 isso , você pode considerar a função a seguir para ler suas configurações de aplicativos:
fonte
Tive uma situação semelhante, em que precisava ter um serviço anterior e um serviço atualizado rodando lado a lado no mesmo servidor. (Foi mais do que apenas uma mudança no banco de dados, foram mudanças no código também). Portanto, eu não poderia simplesmente executar o mesmo .exe duas vezes. Eu precisava de um novo .exe que foi compilado com novas DLLs, mas do mesmo projeto. Apenas alterar o nome do serviço e o nome de exibição do serviço não funcionou para mim, ainda recebo o "erro de serviço já existia" que acredito ser porque estou usando um projeto de implantação. O que finalmente funcionou para mim é que nas propriedades do projeto de implantação há uma propriedade chamada "ProductCode", que é um Guid.
Depois disso, reconstruir o projeto de instalação para um novo .exe ou .msi instalado com êxito.
fonte
A abordagem mais simples é baseada no nome do serviço no nome dll:
fonte