代码之家  ›  专栏  ›  技术社区  ›  roomaroo

如何从C关闭计算机#

  •  129
  • roomaroo  · 技术社区  · 17 年前

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

    我发现了一些有效的方法——我会在下面贴出来——但是没有一种方法非常优雅。我在找一个更简单、更本土化的.NET。

    18 回复  |  直到 17 年前
        1
  •  161
  •   Pop Catalin    10 年前

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

    这是最快的方法:

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

    否则,像其他人所说的那样使用p/invoke或wmi。

    编辑:如何避免创建窗口

    var psi = new ProcessStartInfo("shutdown","/s /t 0");
    psi.CreateNoWindow = true;
    psi.UseShellExecute = false;
    Process.Start(psi);
    
        2
  •  77
  •   Ian R. O'Brien Mamedov    11 年前

    取自: a Geekpedia post

    此方法使用 WMI 关闭Windows。

    您需要在项目中添加一个对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);
        }
    }
    
        3
  •  31
  •   abatishchev Karl Johan    14 年前

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

    但相关代码如下:

    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 );
        }
    

    用途:

    DoExitWin( EWX_SHUTDOWN );
    

    DoExitWin( EWX_REBOOT );
    
        4
  •  26
  •   Ian R. O'Brien Mamedov    11 年前

    不同的方法:

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

    b.Windows管理规范(WMI)

    c.system.runtime.interopservices pinvoke

    d.系统管理

    在我提交之后,我看到了很多其他人也发布了…

        5
  •  14
  •   Ian R. O'Brien Mamedov    11 年前

    老派丑陋的方法。使用 ExitWindowsEx 来自Win32 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);
    

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

        6
  •  11
  •   roomaroo    17 年前

    又矮又甜。调用外部程序:

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

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

        7
  •  9
  •   Fattie    10 年前
    System.Diagnostics.Process.Start("shutdown", "/s /t 0")
    

    应该工作。

    重新启动时,它是/R

    这将直接、干净地重新启动PC机,不需要对话框。

        8
  •  5
  •   Jason Plank Maksim Kondratyuk    13 年前

    您可以启动关机过程:

    • shutdown -s -t 0 -关闭
    • shutdown -r -t 0 -重新启动
        9
  •  5
  •   m3z Curtis    13 年前

    我在尝试使用上面接受的WMI方法时遇到了问题,因为尽管我以管理员身份运行程序,但始终获得特权而不是持有异常。

    解决方案是让进程为自己请求特权。我发现答案在 http://www.dotnet247.com/247reference/msgs/58/292150.aspx 是一个叫理查德·希尔的人写的。

    我把他的解决方案的基本用法贴在下面,以防链接变旧。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Management;
    using System.Runtime.InteropServices;
    using System.Security;
    using System.Diagnostics;
    
    namespace PowerControl
    {
        public class PowerControl_Main
        {
    
    
            public void Shutdown()
            {
                ManagementBaseObject mboShutdown = null;
                ManagementClass mcWin32 = new ManagementClass("Win32_OperatingSystem");
                mcWin32.Get();
    
                if (!TokenAdjuster.EnablePrivilege("SeShutdownPrivilege", true))
                {
                    Console.WriteLine("Could not enable SeShutdownPrivilege");
                }
                else
                {
                    Console.WriteLine("Enabled SeShutdownPrivilege");
                }
    
                // 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
                mboShutdownParams["Flags"] = "1";
                mboShutdownParams["Reserved"] = "0";
    
                foreach (ManagementObject manObj in mcWin32.GetInstances())
                {
                    try
                    {
                        mboShutdown = manObj.InvokeMethod("Win32Shutdown",
                                                       mboShutdownParams, null);
                    }
                    catch (ManagementException mex)
                    {
                        Console.WriteLine(mex.ToString());
                        Console.ReadKey();
                    }
                }
            }
    
    
        }
    
    
        public sealed class TokenAdjuster
        {
            // PInvoke stuff required to set/enable security privileges
            [DllImport("advapi32", SetLastError = true),
            SuppressUnmanagedCodeSecurityAttribute]
            static extern int OpenProcessToken(
            System.IntPtr ProcessHandle, // handle to process
            int DesiredAccess, // desired access to process
            ref IntPtr TokenHandle // handle to open access token
            );
    
            [DllImport("kernel32", SetLastError = true),
            SuppressUnmanagedCodeSecurityAttribute]
            static extern bool CloseHandle(IntPtr handle);
    
            [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            static extern int AdjustTokenPrivileges(
            IntPtr TokenHandle,
            int DisableAllPrivileges,
            IntPtr NewState,
            int BufferLength,
            IntPtr PreviousState,
            ref int ReturnLength);
    
            [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            static extern bool LookupPrivilegeValue(
            string lpSystemName,
            string lpName,
            ref LUID lpLuid);
    
            [StructLayout(LayoutKind.Sequential)]
            internal struct LUID
            {
                internal int LowPart;
                internal int HighPart;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            struct LUID_AND_ATTRIBUTES
            {
                LUID Luid;
                int Attributes;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            struct _PRIVILEGE_SET
            {
                int PrivilegeCount;
                int Control;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] // ANYSIZE_ARRAY = 1
                LUID_AND_ATTRIBUTES[] Privileges;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            internal struct TOKEN_PRIVILEGES
            {
                internal int PrivilegeCount;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
                internal int[] Privileges;
            }
            const int SE_PRIVILEGE_ENABLED = 0x00000002;
            const int TOKEN_ADJUST_PRIVILEGES = 0X00000020;
            const int TOKEN_QUERY = 0X00000008;
            const int TOKEN_ALL_ACCESS = 0X001f01ff;
            const int PROCESS_QUERY_INFORMATION = 0X00000400;
    
            public static bool EnablePrivilege(string lpszPrivilege, bool
            bEnablePrivilege)
            {
                bool retval = false;
                int ltkpOld = 0;
                IntPtr hToken = IntPtr.Zero;
                TOKEN_PRIVILEGES tkp = new TOKEN_PRIVILEGES();
                tkp.Privileges = new int[3];
                TOKEN_PRIVILEGES tkpOld = new TOKEN_PRIVILEGES();
                tkpOld.Privileges = new int[3];
                LUID tLUID = new LUID();
                tkp.PrivilegeCount = 1;
                if (bEnablePrivilege)
                    tkp.Privileges[2] = SE_PRIVILEGE_ENABLED;
                else
                    tkp.Privileges[2] = 0;
                if (LookupPrivilegeValue(null, lpszPrivilege, ref tLUID))
                {
                    Process proc = Process.GetCurrentProcess();
                    if (proc.Handle != IntPtr.Zero)
                    {
                        if (OpenProcessToken(proc.Handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                        ref hToken) != 0)
                        {
                            tkp.PrivilegeCount = 1;
                            tkp.Privileges[2] = SE_PRIVILEGE_ENABLED;
                            tkp.Privileges[1] = tLUID.HighPart;
                            tkp.Privileges[0] = tLUID.LowPart;
                            const int bufLength = 256;
                            IntPtr tu = Marshal.AllocHGlobal(bufLength);
                            Marshal.StructureToPtr(tkp, tu, true);
                            if (AdjustTokenPrivileges(hToken, 0, tu, bufLength, IntPtr.Zero, ref ltkpOld) != 0)
                            {
                                // successful AdjustTokenPrivileges doesn't mean privilege could be changed
                                if (Marshal.GetLastWin32Error() == 0)
                                {
                                    retval = true; // Token changed
                                }
                            }
                            TOKEN_PRIVILEGES tokp = (TOKEN_PRIVILEGES)Marshal.PtrToStructure(tu,
                            typeof(TOKEN_PRIVILEGES));
                            Marshal.FreeHGlobal(tu);
                        }
                    }
                }
                if (hToken != IntPtr.Zero)
                {
                    CloseHandle(hToken);
                }
                return retval;
            }
    
        }
    }
    
        10
  •  4
  •   unbob    14 年前

    注意shutdown.exe只是一个包装 InitiateSystemShutdownEx 它提供了一些在exittwindowsex中缺失的细节

        11
  •  3
  •   Anand G    6 年前

    加上波普·加泰林的回答,这里是 一班轮 它在不显示任何窗口的情况下关闭计算机:

    Process.Start(new ProcessStartInfo("shutdown", "/s /t 0") {
      CreateNoWindow = true, UseShellExecute = false
    });
    
        12
  •  2
  •   Yes - that Jake.    17 年前

    没有用于关闭计算机的.NET本机方法。您需要p/调用exitWindows或exitWindowsEx API调用。

        13
  •  2
  •   Community CDub    8 年前

    我试过 roomaroo's WMI method 关闭Windows 2003服务器,但在添加“[stathread]”(即 Single Threaded Apartment “线程模型”)到main()声明:

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

    然后我尝试从线程关闭,为了使其正常工作,我还必须将线程的“单元状态”设置为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
        }
    }
    

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

        14
  •  2
  •   adrianbanks    14 年前

    **详细回答…

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    // Remember to add a reference to the System.Management assembly
    using System.Management;
    using System.Diagnostics;
    
    namespace ShutDown
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void btnShutDown_Click(object sender, EventArgs e)
            {
                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
                mboShutdownParams["Flags"] = "1";
                mboShutdownParams["Reserved"] = "0";
    
                foreach (ManagementObject manObj in mcWin32.GetInstances())
                {
                    mboShutdown = manObj.InvokeMethod("Win32Shutdown", mboShutdownParams, null);
                }
            }
        }
    }
    
        15
  •  1
  •   user1785960    9 年前

    使用shutdown.exe。要避免传递参数、复杂执行、从WindowForms执行时出现问题,请使用PowerShell执行脚本:

    using System.Management.Automation;
    ...
    using (PowerShell PowerShellInstance = PowerShell.Create())
    {
        PowerShellInstance.AddScript("shutdown -a; shutdown -r -t 100;");
        // invoke execution on the pipeline (collecting output)
        Collection<PSObject> PSOutput = PowerShellInstance.Invoke();
    } 
    

    System.Management.Automation.dll应安装在操作系统上,并在GAC中可用。

    对不起我的英语。

        16
  •  0
  •   Jason Plank Maksim Kondratyuk    13 年前

    如果要远程关闭计算机,则可以使用

    Using System.Diagnostics;
    

    在任何按钮上单击

    {
        Process.Start("Shutdown","-i");
    }
    
        17
  •  -1
  •   Farewell Stack Exchange    12 年前

    如果将System.Windows.Forms引用添加到项目中,则可以在此命名空间中找到具有静态方法的应用程序类。其中之一是您想要/需要/寻求的,它被称为“setSuspendState”。我以前用过这个功能,用它我可以很容易地关闭我的电脑。您可以选择如何使用此功能关闭计算机。它需要3个参数。首先是枚举powerstate(hibernate或suspend),其次是bool force,第三个是bool disablewakeevent。你可以在互联网上更广泛地了解这个功能。以下执行行将按预期关闭计算机(我希望如此):

    System.Windows.Forms.Application.SetSuspendState(PowerState.Hibernate, true, false);
    
        18
  •  -3
  •   Harry dbr    11 年前
    #include<stdio.h>
    #include<stdlib.h>
    
    int main()
    {
        system("C:\\Windows\\System32\\shutdown /s/t 0");
        return 0;
    }