我在我的.net安装程序应用程序中遇到了一个问题,它将同时安装三个Windows应用程序。在这三个应用程序中,一个是Windows服务。因此,我的安装程序项目有三个来自这三个Windows应用程序的主要输出。
安装后,所有这些都将按预期安装,安装后Windows服务将自动“启动”。
但是,如果我卸载应用程序(当Windows服务处于“RUNNING”模式时),安装程序将显示“正在使用的文件”对话框,最终将导致服务未被卸载,而其他内容将被删除。但是,如果Windows服务在卸载之前停止,它将很好地完成。
我认为发生上述问题是因为安装程序应用程序将尝试删除service.exe文件(因为它也捆绑到安装程序中)。
我尝试了以下替代方案:
我尝试通过添加自定义安装程序来解决此问题,我尝试停止该服务。但是,这似乎也没有奏效。原因是,默认的“卸载”操作将在“卸载”自定义操作之前执行。 (FAILED)
将Windows服务应用程序的“主输出”的“永久”属性设置为“true”。我假设安装程序只是跳过与主输出相关的文件。但是(失败)
任何人都遇到过这种问题,请分享你的想法。
如何在卸载前停止服务,以便成功完成卸载?
答案 0 :(得分:0)
我很久以前就遇到过与Windows服务类似的问题,并且可以通过调用WaitForStatus(ServiceControllerStatus)
方法来解决它。该服务需要一些时间来关闭,并且您将在服务完全停止之前继续。编写卸载逻辑以及Shutdown
状态停止时您想要执行的操作。
如果您要卸载并希望在卸载前停止服务,则需要覆盖卸载自定义操作,添加代码以停止它,然后调用base.Uninstall
。
请记住,具有15秒限制的WaitForStatus
可能没有足够的时间来关闭服务,具体取决于它的响应速度以及关闭时的操作。还要确保在Dispose()
上调用ServiceController
(或在此示例中为关闭),因为如果不这样做,那么内部服务句柄将不会立即释放,如果它仍在使用中该服务无法卸载。
这只是如何在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);
}
}