Я пишу C# программу, которая вызывает ExitWindowsEx
для перезагрузки компьютера. Используя код из этой ссылки , я повысил привилегию. Программа отлично работает на Windows 7 и 10, но не работает на Windows Server 2012 R2 с обычным пользователем. Если я запускаю программу от имени администратора, но система просто выходит из системы и сразу возвращается на страницу входа.
Политика безопасности завершения работы
Стандартный пользователь не добавлен. Этот пользователь не имеет права перезагрузки. Поэтому я не смог перезагрузиться?
Я пытался вызвать процесс shutdown.exe с правами администратора, ОС могла перезагрузиться. В чем разница между вызовом функции ExitWindowsEx
и процессом запуска shutdown.exe? Прикрепите мой код:
static void RebootComputer()
{
IntPtr tokenHandle = IntPtr.Zero;
try
{
// get process token
if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle,
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
out tokenHandle))
{
throw new Win32Exception(Marshal.GetLastWin32Error(),
"Failed to open process token handle");
}
// lookup the shutdown privilege
NativeMethods.TOKEN_PRIVILEGES tokenPrivs = new NativeMethods.TOKEN_PRIVILEGES();
tokenPrivs.PrivilegeCount = 1;
tokenPrivs.Privileges = new NativeMethods.LUID_AND_ATTRIBUTES[1];
tokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!NativeMethods.LookupPrivilegeValue(null,
SE_SHUTDOWN_NAME,
out tokenPrivs.Privileges[0].Luid))
{
throw new Win32Exception(Marshal.GetLastWin32Error(),
"Failed to open lookup shutdown privilege");
}
// add the shutdown privilege to the process token
if (!NativeMethods.AdjustTokenPrivileges(tokenHandle,
false,
ref tokenPrivs,
0,
IntPtr.Zero,
IntPtr.Zero))
{
throw new Win32Exception(Marshal.GetLastWin32Error(),
"Failed to adjust process token privileges");
}
// reboot
if (!NativeMethods.ExitWindowsEx(NativeMethods.ExitWindows.ShutDown,
NativeMethods.ShutdownReason.MajorApplication |
NativeMethods.ShutdownReason.MinorInstallation |
NativeMethods.ShutdownReason.FlagPlanned))
{
throw new Win32Exception(Marshal.GetLastWin32Error(),
"Failed to reboot system");
}
}
catch (Exception e)
{
WriteSystemEventLog("Failed to reboot the computer. Exception Message: 0x" + e.HResult.ToString("x")+"\r\n" + e.Message);
}
finally
{
// close the process token
if (tokenHandle != IntPtr.Zero)
{
NativeMethods.CloseHandle(tokenHandle);
}
}
}
// call shutdown.exe works
static void Reboot()
{
var psi = new ProcessStartInfo("shutdown", "/r /t 0");
psi.CreateNoWindow = false;
psi.UseShellExecute = false;
Process.Start(psi);
}
NativeMethod:
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public uint LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public uint Attributes;
}
public struct TOKEN_PRIVILEGES
{
public uint PrivilegeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public LUID_AND_ATTRIBUTES[] Privileges;
}
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ExitWindowsEx(ExitWindows uFlags,
ShutdownReason dwReason);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool OpenProcessToken(IntPtr ProcessHandle,
uint DesiredAccess,
out IntPtr TokenHandle);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool LookupPrivilegeValue(string lpSystemName,
string lpName,
out LUID lpLuid);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle,
[MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
ref TOKEN_PRIVILEGES NewState,
uint Zero,
IntPtr Null1,
IntPtr Null2);