views:

15787

answers:

11

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

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.

+1  A: 

You can launch the shutdown process:

  • "shutdown -s -t 0" - Shutdown
  • "shutdown -r -t 0" - Restart
RichS
+19  A: 

Taken from: a Geekpedia post

This method uses WMI to shutdown windows.

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

    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);
        }
    }
roomaroo
Using WMI makes it easier to track errors. What happens if the shutdown command doesn't work for some reason?
Rob Walker
A: 

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.

roomaroo
+10  A: 

This thread provides the code necessary: 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 );
*/
Stephen Wrighton
A: 

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

Jekke
+4  A: 

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

    using System.Diagnostics;
    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.

roomaroo
+18  A: 

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

This is the quickest way to do it:

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

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

Pop Catalin
+1: That'll do me quite nicely, thanks
Binary Worrier
A: 

What Jekke said. P/Invoke.

http://www.pinvoke.net/default.aspx/user32.ExitWindowsEx

Axl
+5  A: 

Different methods:

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

B. Windows Management Instrumentation (WMI)

http://www.csharpfriends.com/Forums/ShowPost.aspx?PostID=36953

http://www.dreamincode.net/forums/showtopic33948.htm

C. System.Runtime.InteropServices Pinvoke

http://bytes.com/groups/net-c/251367-shutdown-my-computer-using-c

D. System Management

http://www.geekpedia.com/code36_Shut-down-system-using-Csharp.html

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

lakshmanaraj
B and D are the same method (WMI)
Lucas
A: 

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

Using System.Diagnostics;

on any button click { Process.Start("Shutdown","-i"); }

A: 

Process.Start("shutdown.exe", "-s -t 00");

in this line of code, what does "-t" and "00" stands for? why do you need to add it?

tugshhhk
Type "shutdown /?" at the command prompt to see the syntax. -s means shutdown, as opposed to -r, which is restart. -t is a timeout. By default the shutdown command waits 30 seconds before starting to shut the PC down. -t 00 makes it shut down immediately.
roomaroo