简体   繁体   English

.net安装程序,自定义操作,停止和卸载Windows服务

[英].net Installer, Custom Action, stop and uninstall windows service

I'm facing an issue in my .net installer application which will install three windows application together. 我在我的.net安装程序应用程序中遇到了一个问题,它将同时安装三个Windows应用程序。 In these three apps, one is a Windows Service. 在这三个应用程序中,一个是Windows服务。 So, my installer project has three primary output from these three windows apps. 因此,我的安装程序项目有三个来自这三个Windows应用程序的主要输出。

When installed, all these will be installed as expected and the Windows Service will be automatically "STARTED" after the installation. 安装后,所有这些都将按预期安装,安装后Windows服务将自动“启动”。

However, if I uninstall the application (while the windows service is in "RUNNING" mode), the installer will show a "file in use" dialog and will eventually end up with the service not being uninstalled while the other things will be removed. 但是,如果我卸载应用程序(当Windows服务处于“RUNNING”模式时),安装程序将显示“正在使用的文件”对话框,最终将导致服务未被卸载,而其他内容将被删除。 However, if the Windows Service is stopped before uninstall, it will be completed nicely. 但是,如果Windows服务在卸载之前停止,它将很好地完成。

I assume that the above problem occurs because the installer app will try to remove the service.exe file (as it is also bundled into the installer). 我认为出现上述问题是因为安装程序应用程序将尝试删除service.exe文件(因为它也捆绑到安装程序中)。

I tried the below alternates: 我尝试了以下替代方案:

  1. I tried to overcome this by adding a custom installer in which I tried to stop the service. 我试图通过添加自定义安装程序来解决这个问题,我试图在其中停止服务。 But, that also doesn't seem to be working. 但是,这似乎也没有奏效。 Reason for that is, the default "uninstall" action will be executed before the "uninstall" custom action. 原因是,默认的“卸载”操作将在“卸载”自定义操作之前执行。 (FAILED) (FAILED)

  2. Set the "Permanent" property of the "Primary output" of the Windows Service application to "true". 将Windows服务应用程序的“主输出”的“永久”属性设置为“true”。 I was under the assumption that the installer will simply skip the files related to the primary output. 我假设安装程序只是跳过与主输出相关的文件。 But (FAILED) 但是(失败)

Anyone faced this kind of an issue ever and please share your thoughts on the same. 任何人都遇到过这种问题,请分享你的想法。

How can I stop the service before uninstall so that the un-installation will be completed successfully? 如何在卸载前停止服务,以便成功完成卸载?

I had the similar problem with windows services long time ago and was able to solve it by calling WaitForStatus(ServiceControllerStatus) method. 我很久以前就遇到过与windows服务类似的问题,并且能够通过调用WaitForStatus(ServiceControllerStatus)方法来解决它。 The service needs some time to shut down, and you're continuing on before the service has fully stopped. 该服务需要一些时间来关闭,并且您将在服务完全停止之前继续。 Write the logic for uninstall and whatever you want to do when Shutdown status has stopped. 编写卸载逻辑以及Shutdown状态停止时要执行的操作。

If you're uninstalling and you want to stop the service before uninstall then you need to override the uninstall custom action, adding your code to stop it, then call base.Uninstall . 如果您正在卸载并希望在卸载之前停止服务,则需要覆盖卸载自定义操作,添加代码以停止它,然后调用base.Uninstall Keep in mind that a WaitForStatus with a 15 second limit might not be enough time for a service to shut down, depending how responsive it is and what it does in a shutdown. 请记住,具有15秒限制的WaitForStatus可能没有足够的时间来关闭服务,具体取决于它的响应速度以及它在关闭时的作用。 Also make sure you call Dispose() on the ServiceController (or Close as in this example) because if you don't then the internal service handle won't be immediately released, and if it is still in use the service can't be uninstalled. 还要确保在ServiceController上调用Dispose() (或者在此示例中为Close),因为如果不这样做,那么内部服务句柄将不会立即释放,如果它仍在使用中,则服务不能卸载。

MSDN link MSDN链接

This is just example of how this could be implemented and logged in EventLogger: 这只是如何在EventLogger中实现和记录的示例:

public override void Uninstall(System.Collections.IDictionary savedState)
{
 ServiceController controller = new ServiceController("My Service");
 try
 {
  if (controller.Status == ServiceControllerStatus.Running | controller.Status == ServiceControllerStatus.Paused)
  {
   controller.Stop();
   controller.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 0, 30));
   controller.Close();
  }
 }
 catch (Exception ex)
 {
  string source = "My Service Installer";
  string log = "Application";
  if (!EventLog.SourceExists(source))
  {
   EventLog.CreateEventSource(source, log);
  }
  EventLog eLog = new EventLog();
  eLog.Source = source;
  eLog.WriteEntry(string.Concat(@"The service could not be stopped. Please stop the service manually. Error: ", ex.Message), EventLogEntryType.Error);
 }
 finally
 {
  base.Uninstall(savedState);
 }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM