c# - 标准用户在 Windows Server 2012 R2 上的 ExitWindowsEx 行为差异
问题描述
我正在编写一个调用ExitWindowsEx
重启计算机的 C# 程序。使用此链接中的代码,我提升了权限。该程序在 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);
}
本机方法:
[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);
解决方案
推荐阅读
- python - 0到25班的Caesar算法解密的推广
- angular - 如何修复“错误 TS2345:类型的参数”不能分配给“Params$Resources$Scripts$Run”类型的参数
- python - 当数据发布到 django api 时,发生 ConnectionResetError: [Errno 54]
- android - 应用程序不兼容 64 位,但不包含本机代码
- android - Android:使用文本和自定义视图切换
- reactjs - React 组件 API 响应后如何调用 ToastsStore.success 或 ToastsStore.error?
- c# - 有没有办法计算机可以对两个不同的数字进行相同的表示?
- java - string.split() 方法的输出
- python - 循环输出不会产生单独的行
- r - 有没有办法让这个 R 代码更有效率?