如何从 C# 关闭,Process.Start("shutdown") 在 Windows XP 中不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3724276/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to shut down from C#, Process.Start("shutdown") not working in Windows XP
提问by Codejoy
After some poking around on how to reset my computer and or shut it down from C# I found this explanation on how to do that:
在仔细研究了如何重置我的计算机或从 C# 关闭它之后,我找到了有关如何执行此操作的解释:
ManagementBaseObject outParameters = null;
ManagementClass sysOS = new ManagementClass("Win32_OperatingSystem");
sysOS.Get();
// Enables required security privilege.
sysOS.Scope.Options.EnablePrivileges = true;
// Get our in parameters
ManagementBaseObject inParameters = sysOS.GetMethodParameters("Win32Shutdown");
// Pass the flag of 0 = System Shutdown
inParameters["Flags"] = "1"; //shut down.
inParameters["Reserved"] = "0";
foreach (ManagementObject manObj in sysOS.GetInstances())
{
outParameters = manObj.InvokeMethod("Win32Shutdown", inParameters, null);
}
This worked in Windows 7, but not on the Windows XP box I tried it on. So I figured well lets go with a simpler solution:
这在 Windows 7 中有效,但在我试过的 Windows XP 机器上无效。所以我认为让我们使用一个更简单的解决方案:
Process.Start("shutdown", "/s /t 00");
Alas that as well seems to work on my windows 7 box, but not my Windows XP box. I have only tried it on one Windows XP machine, but it flashes up like a command prompt, my program that is up is minimized to the system tray and then nothing happens..so its like it wants to do something but ultimately nothing happens. (I do have code that purposely puts my program to the sys tray when the close X is hit, and the user has to purposely exit it... ) is there an issue with that? My FormClosing code is this:
唉,这似乎也适用于我的 Windows 7 机器,但不适用于我的 Windows XP 机器。我只在一台 Windows XP 机器上尝试过它,但它像命令提示符一样闪烁,我启动的程序被最小化到系统托盘,然后什么也没有发生......所以它就像它想做某事但最终什么也没发生。(当关闭 X 被击中时,我确实有代码故意将我的程序放入系统托盘,并且用户必须故意退出它......)这有问题吗?我的 FormClosing 代码是这样的:
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (!canExit)
{
e.Cancel = true;
this.WindowState = FormWindowState.Minimized;
}
else
{
// Write out the logs.
List<String> logs = LogUtil.getLog(); // mic.getLog();
// Create a writer and open the file
TextWriter tw = new StreamWriter(userAppData + "\logTMC.txt", true);
// Write a line of text to the file
tw.WriteLine("----- " + DateTime.Now + " ------");
foreach (String log in logs)
{
tw.WriteLine(log);
}
// Close the stream
tw.Close();
}
}
I am not sure why I can reset, and shutdown my pc from C# in Windows 7, but not on Windows XP...maybe I missed something? An extra command? A better way to close out the log file I have open when the form closes? Some way to force a shutdown or reset no matter what, the Windows XP box I am using does indeed have an SVN server as a windows service running, but I am not sure if this makes a difference or not.
我不确定为什么我可以在 Windows 7 中从 C# 重置和关闭我的电脑,但不能在 Windows XP 上......也许我错过了什么?一个额外的命令?关闭表单关闭时打开的日志文件的更好方法是什么?无论如何,某种强制关闭或重置的方法,我使用的 Windows XP 机器确实有一个 SVN 服务器作为 Windows 服务在运行,但我不确定这是否有所作为。
So I am not really sure where to investigate my problem. Does the Process.Start()
have a way to see a return or a try catch to see what might of caused it not to shut down or is it a "fire and forget" type a deal?
所以我不确定在哪里调查我的问题。是否Process.Start()
有办法查看返回或尝试捕获以查看可能导致它不关闭的原因,还是“一劳永逸”类型的交易?
回答by Christian.K
You could use the ExitWindowsEx
API via pinvoke.net.
您可以ExitWindowsEx
通过 pinvoke.net使用API。
See the ExitWindowsEx, ExitWindows-Enumand ShutdownReason-Enumon pinvoke.net for more information. Note that your process must have the SE_SHUTDOWN_NAME
priviledge aquired (for example via AdjustTokenPrivilegesAPI).
有关更多信息,请参阅pinvoke.net 上的ExitWindowsEx、ExitWindows-Enum和ShutdownReason-Enum。请注意,您的流程必须SE_SHUTDOWN_NAME
获得特权(例如通过AdjustTokenPrivilegesAPI)。
The answers to this stackoverflow questioncontain some "complete" examples (although most of them are missing errorchecking and resource cleanup - the latter might not matter when you successfully shutdown, YMMV).
这个stackoverflow问题的答案包含一些“完整”的例子(尽管其中大多数都缺少错误检查和资源清理——后者在你成功关闭时可能无关紧要,YMMV)。
Finally, note that using Process.Start()
as you showed, without a fully qualified name to shutdown.exe
is also problematic from a security standpoint. Someone could put a malicious EXE named shutdown in your PATH. Since you probably need to run with admin rights to be able to execute the "real" shutdown.exe, this can cause some trouble. If you specify something like Process.Start(Environment.ExpandEnvironmentVariables("%windir%\system32\shutdown.exe"))
you can at least assume that the real shutdown.exe is protected from malicious replacement by file system rights (if the attacker himself is an admin your basically busted anyway).
最后,请注意,从安全角度来看,Process.Start()
如您所见,没有完全限定名称 toshutdown.exe
的使用也是有问题的。有人可能会在您的 PATH 中放置一个名为 shutdown 的恶意 EXE。由于您可能需要以管理员权限运行才能执行“真正的”shutdown.exe,这可能会导致一些麻烦。如果您指定类似的内容,Process.Start(Environment.ExpandEnvironmentVariables("%windir%\system32\shutdown.exe"))
您至少可以假设真正的 shutdown.exe 受到保护,不会被文件系统权限恶意替换(如果攻击者本人是管理员,那么您基本上已经被破坏了)。
回答by Nope
I can't add comments yet, so have to post it as an answer.
我还不能添加评论,所以必须把它作为答案发布。
There is an article on this site, showing several methods on shutting down the PC here: How to shut down the computer from C#
该站点上有一篇文章,在此处展示了几种关闭 PC 的方法:如何从 C# 关闭计算机
At a glance I noticed in the above link, for XP, Pop Catalin uses Process.Start("shutdown","/s /t 0");
. I'm not sure if using 1 0
is going to make any difference.
我在上面的链接中一眼就注意到,对于 XP,Pop Catalin 使用Process.Start("shutdown","/s /t 0");
. 我不确定使用 10
是否会有所作为。
回答by Phil
I believe it's correct. You just have to change the command to:
我相信这是正确的。您只需将命令更改为:
shutdown.exe -s -t 00
It works on my Windows box (from cmd).
它适用于我的 Windows 机器(来自 cmd)。