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