在卸载时自动停止Windows服务

时间:2012-05-25 17:03:43

标签: windows-services servicecontroller

安装我的服务后,我有一个处理程序,可以在安装完服务后启动它。

private void InitializeComponent()
{
    ...
    this.VDMServiceInstaller.AfterInstall += ServiceInstaller_AfterInstall;
}


private void ServiceInstaller_AfterInstall(object sender, InstallEventArgs e)
{
    ServiceController sc = new ServiceController("MyService");
    sc.Start();
}

我想在卸载服务之前停止服务,所以我为InitializeComponent()添加了一个额外的处理程序。

this.ServiceInstaller.BeforeUninstall += ServiceInstaller_BeforeUninstall;

并添加了功能:

private void ServiceInstaller_BeforeUninstall(object sender, InstallEventArgs e)
{
    try
    {
        ServiceController sc = new ServiceController("MyService");
        if (sc.CanStop)
        {
            sc.Stop();
            sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);
        }
    }
    catch (Exception exception)
    {}
}

但该服务在卸载前不会停止。我不正确地使用ServiceController.Stop()函数吗?

3 个答案:

答案 0 :(得分:1)

以下内容可以帮助您:

    protected override void OnBeforeUninstall(IDictionary savedState)
    {
       ServiceController controller = new ServiceController("ServiceName");

       try
       {

          if(controller.Status == ServiceControllerStatus.Running | controller.Status == ServiceControllerStatus.Paused)
          {
             controller.stop();
          }
          controller.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0,0,0,15));

          controller.Close();
       }
       catch(Exception ex)
       { 
          EventLog log = new EventLog();
          log.WriteEntry("Service failed to stop");
       }

       finally
       {
          base.OnBeforeUninstall(savedState);
       }
   }

答案 1 :(得分:0)

这是我试图阻止的窗口:

Locked files dialog

我已经测试了所有可用的覆盖,并且在提示关闭应用程序的对话框出现之前没有执行任何覆盖。

甚至类构造函数也不够早。

我的结论是,正如安装程序项目所示,您无法在对话框之前通过代码停止服务。

由于没有其他方法可以在项目中执行代码,因此我没有看到任何方法来实现这一目标。

我真的希望它有所不同,因为我自己非常需要这个,但是没有任何"钩子"在安装程序项目中可用,它足够早地进入以解决问题。


我最好的建议是做两个安装程序。

作为第二个包装器的一个,并且在安装时正常启动第二个安装程序。

但是在卸载时,它会先停止服务,然后卸载第二个服务。

但这对我的喜好来说太过分了,所以我没有进一步探讨这个问题。

答案 2 :(得分:0)

我想做类似的事情,最终在安装程序项目中使用以下代码来处理触发BeforeUninstall事件的时间:

private void SessionLoginMonitorInstaller_BeforeUninstall(object sender, InstallEventArgs e)
{
    try
    {
        using (ServiceController sv = new ServiceController(SessionLoginMonitorInstaller.ServiceName))
        {
            if(sv.Status != ServiceControllerStatus.Stopped)
            {
                sv.Stop();
                sv.WaitForStatus(ServiceControllerStatus.Stopped);
            }
        }
    }
    catch(Exception ex)
    {
        EventLog.WriteEntry("Logon Monitor Service", ex.Message, EventLogEntryType.Warning);
    }
}

项目的“自定义操作”部分还具有一个操作,用于卸载Windows Service项目的主要输出。这对我有用,并且每次测试都为我提供了干净的卸载。

相关问题