Eseguire lo shutdown e/o il reboot di Windows da programma.

Su un newsgroup ho letto di una persona che chiedeva come eseguire lo shutdown  di Windows da programma. Con documentazione MSDN alla mano, ho scritto un paio di funzioni che fanno shutdown e reboot (bel modo di sfruttare la pausa pranzo, eh? :-)).

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
private struct LUID
{
    public uint LowPart;
    public uint HighPart;
};

[StructLayout(LayoutKind.Sequential)]
private struct TOKEN_PRIVILEGES
{
    public int PrivilegeCount;
    public LUID Privileges;
    public int Attributes;
};

[DllImport("kernel32.dll")]
private extern
IntPtr GetCurrentProcess();

[DllImport("advapi32.dll", SetLastError=true)]
private extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, ref
IntPtr TokenHandle);

[DllImport("advapi32.dll", SetLastError=true)]
private extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref
LUID lpLuid);

[DllImport("advapi32.dll", SetLastError=true) ]
private extern bool AdjustTokenPrivileges(IntPtr TokenHandle, int DisableAllprivileges, [MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGES NewState, int
BufferLength, IntPtr PreviousState, IntPtr ReturnLength);

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

// Costanti per AdjustTokenProvilege
private const int SE_PRIVILEGE_ENABLED = 0x00000002;
private const int TOKEN_QUERY = 0x00000008
;
private const int TOKEN_ADJUST_PRIVILEGES = 0x00000020
;

// Costanti per ExitWindowsEx
private const int EWX_LOGOFF = 0x00000000;
private const int EWX_SHUTDOWN = 0x00000001
;
private const int EWX_REBOOT = 0x00000002
;
private const int EWX_FORCE = 0x00000004
;
private const int EWX_POWEROFF = 0x00000008
;
private const int EWX_FORCEIFHUNG = 0x00000010;

private void SetTokenPrivileges()
{
    TOKEN_PRIVILEGES newState =
new
TOKEN_PRIVILEGES();
    LUID luid =
new
LUID();
   
    LookupPrivilegeValue(
null, "SeShutdownPrivilege", ref
luid);
    IntPtr processHandle = GetCurrentProcess();
    IntPtr tokenHandle = IntPtr.Zero;
    OpenProcessToken(processHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
ref
tokenHandle);
    newState.PrivilegeCount =
1
;
    newState.Privileges = luid;
    newState.Attributes = SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(tokenHandle,
0, ref
newState, Marshal.SizeOf(newState), IntPtr.Zero, IntPtr.Zero);
}

public void Reboot()
{
    SetTokenPrivileges();
    ExitWindowsEx(EWX_REBOOT,
0
);
}

public void Shutdown()
{
    SetTokenPrivileges();
    ExitWindowsEx(EWX_SHUTDOWN,
0
);
}

Come da documentazione, su sistemi NT/2000/XP/2003 è necessario dare al token che esegue lo shutdown/reboot l'attributo "SeShutdownPrivilege". Questo compito è assegnato alla funzione SetTokenPrivileges().

"Wrappare" il tutto in una classe è un giochetto.

Lo posto qui, così, se serve a qualcuno...

Print | posted on Thursday, July 21, 2005 2:08 PM

Comments have been closed on this topic.