【问题标题】:How cancel shutdown from a windows service C#如何从 Windows 服务 C# 取消关机
【发布时间】:2010-04-27 09:43:14
【问题描述】:

我启动了一个 Windows 服务(用 C# .net2.0 编写)。

我想检测计算机何时关闭/重新启动并取消它。 取消后我想做一些操作并重新启动窗口。

试过了,还是不行

using Microsoft.Win32;
partial class MyService: ServiceBase
{
    protected override void OnStart(string[] args)
    {
        SystemEvents.SessionEnding += new SessionEndingEventHandler(OnSessionEnding);
    }

    private void OnSessionEnding(object sender, SessionEndingEventArgs e)
    {
        e.Cancel = true;
        //Do some work...
    }
}

另一个测试:

partial class MyService: ServiceBase
{
    protected override void OnShutdown()
    {
        //Do some work...
        //base.OnShutdown();
    }
}

【问题讨论】:

    标签: c# windows-services c#-2.0 system-shutdown


    【解决方案1】:

    我不会搞砸这个。 Windows 会将您的进程视为挂起的进程(除非您直接访问 Win32 API)。

    我的建议是注意您正在关闭,并可能将活动安排在启动时发生?

    更新:
    我认为你会被困在这里,因为你的服务不会知道为什么 Windows 正在关闭。你会有一个无限循环:

    • Windows 关机触发。
    • 服务通知、中止关闭、启动应用程序。
    • 用户使用应用程序继续关机。
    • 窗口关闭触发。
    • 服务通知......

    【讨论】:

    • 我无法在启动时进行活动,因为当用户注销/关闭/重新启动时,我想从我的 Windows 服务中使用 winform 应用程序午餐。我的 winform 应用程序有一个按钮“立即重新启动”,还有一个“稍后提醒我”,然后做一些其他工作......
    • @scrat:另一个禁忌,Windows 服务没有构建,不应该用于与 GUI 交互。
    • @James 他确实说他的服务会启动另一个应用程序。
    • @Neil,问题是after the cancel I want to do some actions。我没有看到他说应该在哪里启动另一个应用程序?此外,通过设置标志可以轻松避免无限循环...
    • @James 在上面的评论中:“我无法在启动时进行活动,因为当用户注销/关闭时,我想从我的 Windows 服务中使用一个 winform 应用程序 /重新开始。” (强调我的)。我想你可以在某处“设置一个标志”,但这是模棱两可的,可能是某种注册表设置或某处的文件。对我来说,这只是为了让一些原本不一定是个好主意的东西发挥作用而进行黑客攻击。
    【解决方案2】:

    我的建议是将您的操作写入文件或注册表,例如

    DoSomething = true
    DoSomethingElse = false
    

    您可以在OnStart 中阅读并处理。

    【讨论】:

      【解决方案3】:

      您可以使用 shell 命令shutdown -a 中止关机。我不知道是否有可能检测到关机...

      【讨论】:

        【解决方案4】:

        最后我放弃了检测和取消 Windows 关机/重启的想法, 但现在我只想检测“shutdown -r -t xx”

        请注意运行程序的操作系统是 Windows XP。

        我试过了,但在 WindowsXP 上我没有 ExitCode:

        Process process = new Process();
        
        do
        {
            process.StartInfo.FileName = "shutdown.exe";
            process.StartInfo.Arguments = "/a";
            process.Start();
            process.WaitForExit();
            MessageBox.Show(string.Format("ExitCode={0}",process.ExitCode));
            Thread.Sleep(1000);
        }
        while (process.ExitCode != 0) ;
        

        【讨论】:

        • 我已经用实际的示例代码修改了我上面的答案,希望可以正常工作,这样您就不必开始这个过程了。
        • @ho Windows 在我检测到关机之前杀死了其他进程,所以这不是更好的解决方案。我决定在“shutdown -r -t xx”此时停止启动我的程序时检测超时窗口。
        • shutdown -r -t xx 后检测超时窗口的解决方案是根据检测窗口的标题:pinvoke.net/default.aspx/user32.EnumWindows
        【解决方案5】:

        解决方案是通过 winform 检测关机:http://msdn.microsoft.com/fr-fr/library/microsoft.win32.systemevents.sessionending%28VS.80%29.aspx

        但是 Windows 在我检测到它之前就杀死了其他进程,所以这不是更好的解决方案!

        【讨论】:

          【解决方案6】:

          AbortSystemShutdown 可能会起作用:

          http://msdn.microsoft.com/en-us/library/aa376630%28VS.85%29.aspx

          虽然我同意 Neil 的观点,但这样做可能不是一个好主意。

          编辑:添加示例代码

          using System.Runtime.InteropServices;
          
          [DllImport("advapi32.dll", SetLastError=true)]
          static extern bool AbortSystemShutdown(string lpMachineName);
          
          
          if (!AbortSystemShutdown("localhost"))
          {
              int err = Marshal.GetLastWin32Error();
          }        
          

          【讨论】:

          猜你喜欢
          • 2013-07-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多