如何从 C# 关闭计算机

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/102567/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 14:05:58  来源:igfitidea点击:

How to shut down the computer from C#

提问by roomaroo

What's the best way to shut down the computer from a C# program?

从 C# 程序关闭计算机的最佳方法是什么?

I've found a few methods that work - I'll post them below - but none of them are very elegant. I'm looking for something that's simpler and natively .net.

我发现了一些有效的方法 - 我将在下面发布它们 - 但它们都不是很优雅。我正在寻找更简单的本地 .net 的东西。

采纳答案by roomaroo

Taken from: a Geekpedia post

摘自:Geekpedia 帖子

This method uses WMIto shutdown windows.

此方法使用WMI来关闭窗口。

You'll need to add a reference to System.Management to your project to use this.

您需要将 System.Management 的引用添加到您的项目中才能使用它。

using System.Management;

void Shutdown()
{
    ManagementBaseObject mboShutdown = null;
    ManagementClass mcWin32 = new ManagementClass("Win32_OperatingSystem");
    mcWin32.Get();

    // You can't shutdown without security privileges
    mcWin32.Scope.Options.EnablePrivileges = true;
    ManagementBaseObject mboShutdownParams =
             mcWin32.GetMethodParameters("Win32Shutdown");

     // Flag 1 means we want to shut down the system. Use "2" to reboot.
    mboShutdownParams["Flags"] = "1";
    mboShutdownParams["Reserved"] = "0";
    foreach (ManagementObject manObj in mcWin32.GetInstances())
    {
        mboShutdown = manObj.InvokeMethod("Win32Shutdown", 
                                       mboShutdownParams, null);
    }
}

回答by RichS

You can launch the shutdown process:

您可以启动关机过程:

  • shutdown -s -t 0- Shutdown
  • shutdown -r -t 0- Restart
  • shutdown -s -t 0- 关掉
  • shutdown -r -t 0- 重新开始

回答by roomaroo

Short and sweet. Call an external program:

简短而甜蜜。调用外部程序:

    using System.Diagnostics;

    void Shutdown()
    {
        Process.Start("shutdown.exe", "-s -t 00");
    }

Note: This calls Windows' Shutdown.exe program, so it'll only work if that program is available. You might have problems on Windows 2000 (where shutdown.exe is only available in the resource kit) or XP Embedded.

注意:这会调用 Windows 的 Shutdown.exe 程序,因此它只有在该程序可用时才能工作。您可能在 Windows 2000(shutdown.exe 仅在资源工具包中可用)或XP Embedded上遇到问题。

回答by Stephen Wrighton

This thread provides the code necessary: http://bytes.com/forum/thread251367.html

该线程提供了必要的代码:http: //bytes.com/forum/thread251367.html

but here's the relevant code:

但这是相关的代码:

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack=1)]
internal struct TokPriv1Luid
{
    public int Count;
    public long Luid;
    public int Attr;
}

[DllImport("kernel32.dll", ExactSpelling=true) ]
internal static extern IntPtr GetCurrentProcess();

[DllImport("advapi32.dll", ExactSpelling=true, SetLastError=true) ]
internal static extern bool OpenProcessToken( IntPtr h, int acc, ref IntPtr
phtok );

[DllImport("advapi32.dll", SetLastError=true) ]
internal static extern bool LookupPrivilegeValue( string host, string name,
ref long pluid );

[DllImport("advapi32.dll", ExactSpelling=true, SetLastError=true) ]
internal static extern bool AdjustTokenPrivileges( IntPtr htok, bool disall,
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen );

[DllImport("user32.dll", ExactSpelling=true, SetLastError=true) ]
internal static extern bool ExitWindowsEx( int flg, int rea );

internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
internal const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
internal const int EWX_LOGOFF = 0x00000000;
internal const int EWX_SHUTDOWN = 0x00000001;
internal const int EWX_REBOOT = 0x00000002;
internal const int EWX_FORCE = 0x00000004;
internal const int EWX_POWEROFF = 0x00000008;
internal const int EWX_FORCEIFHUNG = 0x00000010;

private void DoExitWin( int flg )
{
    bool ok;
    TokPriv1Luid tp;
    IntPtr hproc = GetCurrentProcess();
    IntPtr htok = IntPtr.Zero;
    ok = OpenProcessToken( hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok );
    tp.Count = 1;
    tp.Luid = 0;
    tp.Attr = SE_PRIVILEGE_ENABLED;
    ok = LookupPrivilegeValue( null, SE_SHUTDOWN_NAME, ref tp.Luid );
    ok = AdjustTokenPrivileges( htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero );
    ok = ExitWindowsEx( flg, 0 );
    }

Usage:

用法:

DoExitWin( EWX_SHUTDOWN );

or

或者

DoExitWin( EWX_REBOOT );

回答by Yes - that Jake.

There is no .net native method for shutting off the computer. You need to P/Invoke the ExitWindows or ExitWindowsEx API call.

没有用于关闭计算机的 .net 本机方法。您需要 P/Invoke ExitWindows 或 ExitWindowsEx API 调用。

回答by roomaroo

The old-school ugly method. Use the ExitWindowsExfunction from the Win32 API.

老派的丑陋方法。使用ExitWindowsExWin32 API 中的函数。

using System.Runtime.InteropServices;

void Shutdown2()
{
    const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
    const short SE_PRIVILEGE_ENABLED = 2;
    const uint EWX_SHUTDOWN = 1;
    const short TOKEN_ADJUST_PRIVILEGES = 32;
    const short TOKEN_QUERY = 8;
    IntPtr hToken;
    TOKEN_PRIVILEGES tkp;

    // Get shutdown privileges...
    OpenProcessToken(Process.GetCurrentProcess().Handle, 
          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hToken);
    tkp.PrivilegeCount = 1;
    tkp.Privileges.Attributes = SE_PRIVILEGE_ENABLED;
    LookupPrivilegeValue("", SE_SHUTDOWN_NAME, out tkp.Privileges.pLuid);
    AdjustTokenPrivileges(hToken, false, ref tkp, 0U, IntPtr.Zero, 
          IntPtr.Zero);

    // Now we have the privileges, shutdown Windows
    ExitWindowsEx(EWX_SHUTDOWN, 0);
}

// Structures needed for the API calls
private struct LUID
{
    public int LowPart;
    public int HighPart;
}
private struct LUID_AND_ATTRIBUTES
{
    public LUID pLuid;
    public int Attributes;
}
private struct TOKEN_PRIVILEGES
{
    public int PrivilegeCount;
    public LUID_AND_ATTRIBUTES Privileges;
}

[DllImport("advapi32.dll")]
static extern int OpenProcessToken(IntPtr ProcessHandle, 
                     int DesiredAccess, out IntPtr TokenHandle);

[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AdjustTokenPrivileges(IntPtr TokenHandle,
    [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
    ref TOKEN_PRIVILEGES NewState,
    UInt32 BufferLength,
    IntPtr PreviousState,
    IntPtr ReturnLength);

[DllImport("advapi32.dll")]
static extern int LookupPrivilegeValue(string lpSystemName, 
                       string lpName, out LUID lpLuid);

[DllImport("user32.dll", SetLastError = true)]
static extern int ExitWindowsEx(uint uFlags, uint dwReason);

In production code you should be checking the return values of the API calls, but I left that out to make the example clearer.

在生产代码中,您应该检查 API 调用的返回值,但为了使示例更清晰,我将其省略。

回答by Pop Catalin

Works starting with windows XP, not available in win 2000 or lower:

从 Windows XP 开始工作,在 win 2000 或更低版本中不可用:

This is the quickest way to do it:

这是最快的方法:

Process.Start("shutdown","/s /t 0");

Otherwise use P/Invoke or WMI like others have said.

否则像其他人所说的那样使用 P/Invoke 或 WMI。

Edit: how to avoid creating a window

编辑:如何避免创建窗口

var psi = new ProcessStartInfo("shutdown","/s /t 0");
psi.CreateNoWindow = true;
psi.UseShellExecute = false;
Process.Start(psi);

回答by lakshmanaraj

Different methods:

不同的方法:

A. System.Diagnostics.Process.Start("Shutdown", "-s -t 10");

一种。 System.Diagnostics.Process.Start("Shutdown", "-s -t 10");

B. Windows Management Instrumentation (WMI)

B. Windows 管理规范 (WMI)

C. System.Runtime.InteropServices Pinvoke

C. System.Runtime.InteropServices Pinvoke

D. System Management

D. 系统管理

After I submit, I have seen so many others also have posted...

我提交后,我看到很多人也发了...

回答by lakshmanaraj

If you want to shut down computer remotely then you can use

如果你想远程关闭计算机,那么你可以使用

Using System.Diagnostics;

on any button click

在任何按钮上单击

{
    Process.Start("Shutdown","-i");
}

回答by MisterEd

I tried roomaroo's WMI methodto shutdown Windows 2003 Server, but it would not work until I added `[STAThread]' (i.e. "Single Threaded Apartment" threading model) to the Main() declaration:

我尝试了roomaroo 的 WMI 方法来关闭 Windows 2003 Server,但是直到我将 `[STAThread]'(即“单线程单元”线程模型)添加到 Main() 声明中它才会起作用:

[STAThread]
public static void Main(string[] args) {
    Shutdown();
}

I then tried to shutdown from a thread, and to get that to work I had to set the "Apartment State" of the thread to STA as well:

然后我尝试从一个线程关闭,为了让它工作,我还必须将线程的“公寓状态”设置为 STA:

using System.Management;
using System.Threading;

public static class Program {

    [STAThread]
    public static void Main(string[] args) {
        Thread t = new Thread(new ThreadStart(Program.Shutdown));
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
        ...
    }

    public static void Shutdown() {
        // roomaroo's code
    }
}

I'm a C# noob, so I'm not entirely sure of the significance of STA threads in terms of shutting down the system (even after reading the link I posted above). Perhaps someone else can elaborate...?

我是 C# 菜鸟,所以我不完全确定 STA 线程在关闭系统方面的重要性(即使在阅读了我上面发布的链接之后)。也许其他人可以详细说明......?