首页 > 解决方案 > 标准用户在 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);

标签: c#adminwindows-server-2012-r2reboot

解决方案


推荐阅读