Cómo cerrar la computadora desde C #

¿Cuál es la mejor manera de apagar la computadora desde un progtwig C #?

He encontrado algunos métodos que funcionan, los publicaré a continuación, pero ninguno de ellos es muy elegante. Estoy buscando algo que sea más simple y nativo .net.

Funciona comenzando con Windows XP, no disponible en win 2000 o inferior:

Esta es la forma más rápida de hacerlo:

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

De lo contrario, use P / Invoke o WMI como han dicho otros.

Editar: cómo evitar crear una ventana

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

Tomado de: una publicación de Geekpedia

Este método usa WMI para cerrar ventanas.

Deberá agregar una referencia a System.Management a su proyecto para usar esto.

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

Este hilo proporciona el código necesario: http://bytes.com/forum/thread251367.html

pero aquí está el código relevante:

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

Uso:

 DoExitWin( EWX_SHUTDOWN ); 

o

 DoExitWin( EWX_REBOOT ); 

Diferentes métodos:

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

B. Windows Management Instrumentation (WMI)

C. System.Runtime.InteropServices Pinvoke

D. Gestión del sistema

Después de enviar, he visto tantos otros también han publicado …

El método feo de la vieja escuela. Use la función ExitWindowsEx de la API Win32.

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

En el código de producción debe verificar los valores de retorno de las llamadas API, pero lo dejé para que el ejemplo sea más claro.

Corto y dulce. Llamar a un progtwig externo:

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

Nota: Esto llama al progtwig Shutdown.exe de Windows, por lo que solo funcionará si ese progtwig está disponible. Puede tener problemas en Windows 2000 (donde shutdown.exe solo está disponible en el kit de recursos) o XP Embedded .

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

Deberia trabajar.

Para reiniciar, es / r

Esto reiniciará la caja de la PC directamente y limpiamente, sin diálogos.

Puede iniciar el proceso de cierre:

  • shutdown -s -t 0 – Apagado
  • shutdown -r -t 0 – Reiniciar

Tuve problemas para tratar de usar el método WMI aceptado anteriormente porque siempre recibí privilegios, no excepciones, a pesar de ejecutar el progtwig como administrador.

La solución fue que el proceso solicite el privilegio por sí mismo. Encontré la respuesta en http://www.dotnet247.com/247reference/msgs/58/292150.aspx escrita por un tipo llamado Richard Hill.

He pegado el uso básico de su solución a continuación en caso de que ese enlace envejezca.

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

Tenga en cuenta que shutdown.exe es solo una envoltura alrededor de InitiateSystemShutdownEx , que proporciona algunas sutilezas que faltan en ExitWindowsEx

No hay un método nativo .net para apagar la computadora. Necesita P / Invocar la llamada a la API de ExitWindows o ExitWindowsEx.

Probé el método WMI de roomaroo para cerrar Windows 2003 Server, pero no funcionó hasta que agregué `[STAThread] ‘(es decir, el modelo de subproceso” Single Threaded Apartment “) a la statement Main ():

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

Luego traté de cerrar un hilo, y para que funcione, tuve que establecer el “Estado del apartamento” del hilo en STA también:

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

Soy un novato de C #, por lo que no estoy completamente seguro de la importancia de los hilos STA en términos de apagar el sistema (incluso después de leer el enlace que publiqué arriba). Tal vez alguien más puede elaborar …

** Respuesta elaborada …

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

Si desea apagar la computadora de forma remota, puede usar

 Using System.Diagnostics; 

en cualquier botón, haga clic

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

Use shutdown.exe. Para evitar problemas con pasar args, la ejecución compleja, la ejecución desde WindowForms usa el script de ejecución de 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 PSOutput = PowerShellInstance.Invoke(); } 

System.Management.Automation.dll debe estar instalado en el sistema operativo y disponible en GAC.

Lo siento por mi ingles.

Solo para agregar a la respuesta de Pop Catalin, aquí hay un trazador de líneas que apaga la computadora sin mostrar ninguna ventana:

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

Si agrega la referencia System.Windows.Forms a su proyecto, puede encontrar en este espacio de nombres la clase Application que tiene métodos estáticos. Uno de ellos es lo que quiere / necesita / busca, y se llama “SetSuspendState”. Utilicé esta función en el pasado, y con ella logro cerrar mi computadora fácilmente. Hay opciones sobre cómo quiere apagar su computadora con esta función. Toma 3 parámetros. Primero, el enum PowerState (Hibernate o Suspend), luego el bool force y el bool disableWakeEvent. Puede leer más acerca de esta función en Internet. La siguiente línea de ejecución cerrará su computadora como esperaba (espero que sí):

 System.Windows.Forms.Application.SetSuspendState(PowerState.Hibernate, true, false); 
 #include #include int main() { system("C:\\Windows\\System32\\shutdown /s/t 0"); return 0; }