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

Posted

技术标签:

【中文标题】.net 安装程序、自定义操作、停止和卸载 windows 服务【英文标题】:.net Installer, Custom Action, stop and uninstall windows service 【发布时间】:2013-01-06 19:52:28 【问题描述】:

我在我的 .net 安装程序应用程序中遇到了一个问题,它将一起安装三个 Windows 应用程序。在这三个应用程序中,一个是 Windows 服务。因此,我的安装程序项目具有来自这三个 Windows 应用程序的三个主要输出。

安装后,所有这些都将按预期安装,安装后Windows服务将自动“启动”。

但是,如果我卸载应用程序(当 Windows 服务处于“运行”模式时),安装程序将显示“正在使用的文件”对话框,最终会导致服务未卸载,而其他内容将被移除。但是,如果在卸载之前停止 Windows 服务,它将很好地完成。

我认为出现上述问题是因为安装程序应用程序将尝试删除 service.exe 文件(因为它也捆绑到安装程序中)。

我尝试了以下替代方法:

    我试图通过添加一个自定义安装程序来解决这个问题,在该安装程序中我试图停止服务。但是,这似乎也不起作用。原因是,默认的“卸载”操作将在“卸载”自定义操作之前执行。 (失败)

    将 Windows 服务应用程序的“主要输出”的“永久”属性设置为“真”。我假设安装程序将简单地跳过与主要输出相关的文件。但是(失败)

任何人都遇到过这种问题,请分享您的想法。

如何在卸载前停止服务,以便卸载成功?

【问题讨论】:

【参考方案1】:

我很久以前就遇到过类似的windows服务问题,通过调用WaitForStatus(ServiceControllerStatus)方法解决了。该服务需要一些时间来关闭,并且您在服务完全停止之前继续。编写卸载逻辑以及当Shutdown 状态停止时您想做的任何事情。

如果您正在卸载并且想要在卸载之前停止服务,那么您需要覆盖卸载自定义操作,添加您的代码来停止它,然后调用base.Uninstall。 请记住,具有 15 秒限制的WaitForStatus 可能不足以让服务关闭,这取决于它的响应速度以及它在关闭时的作用。还要确保在ServiceController 上调用Dispose()(或在本例中关闭),因为如果你不这样做,那么内部服务句柄将不会立即释放,如果它仍在使用中,则服务可以'不会被卸载。

MSDN link

这只是如何在 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);
 

【讨论】:

谢谢严。我已经有东西了,请看下面的代码:ServiceController controller = new ServiceController(this._mtlTestServiceName);尝试 if (controller.Status == ServiceControllerStatus.Running | controller.Status == ServiceControllerStatus.Paused) controller.Stop(); controller.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 0, 15));控制器。关闭(); 但到目前为止没有用:(

以上是关于.net 安装程序、自定义操作、停止和卸载 windows 服务的主要内容,如果未能解决你的问题,请参考以下文章

自定义卸载动作 c#

关于NSIS静默安装在控制面板上自定义卸载图标?

自定义 VS 2008 安装项目卸载程序

卸载期间自定义操作不起作用

win10-mysql卸载干净

使用 WIX 安装程序在自定义操作中停止设置错误