如何从 Windows 服务 C# 取消关机
Posted
技术标签:
【中文标题】如何从 Windows 服务 C# 取消关机【英文标题】:How cancel shutdown from a windows service 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();
【问题讨论】:
【参考方案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();
【讨论】:
如何在 C# 中使用 AbortSystemShutdown 函数? 使用 PInvoke。这里有一些关于它的信息pinvoke.net/default.aspx/advapi32/AbortSystemShutdown.html 它很旧,但有人有完整的代码示例吗?我用谷歌找不到 C# 的任何东西。而且只是不明白在我的代码中在哪里使用您的示例的每一行。我的意思是我不明白将 DllImport 部分放在哪里以及在哪里使用 if() 语句进行拦截。提前致谢。 @user3916429 看看这里:Platform Invoke Tutorial。这个问题的答案看起来很有帮助:***.com/questions/17620396/…以上是关于如何从 Windows 服务 C# 取消关机的主要内容,如果未能解决你的问题,请参考以下文章