【问题标题】:Get Windows User of Impersonated Process获取模拟进程的 Windows 用户
【发布时间】:2014-08-13 15:24:25
【问题描述】:

我正在使用 C# 应用程序中的 CreateProcessWithLogonW 方法在另一个用户下创建一个新进程,该应用程序用作启动器。在模拟过程中(也是用 C# 编写的),我需要获取登录到 Windows 的原始用户的用户名(而不是被模拟用户的用户名)。这不是一个 ASP 应用程序。我怎样才能做到这一点?

【问题讨论】:

    标签: c# impersonation


    【解决方案1】:

    您可以使用 P/Invoke 获取当前登录用户的列表。请记住,在 Windows 中,一次可以有超过 1 个人登录机器。您必须枚举列表并选择合适的用户。

    P/Invoke for NetWkstaUserEnum function

    [DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError=true)]
        static extern int NetWkstaUserEnum(
           string servername,
           int level,
           out IntPtr bufptr,
           int prefmaxlen,
           out int entriesread,
           out int totalentries,
           ref int resume_handle);
    

    【讨论】:

    • 谢谢,但是我该如何选择合适的用户呢?
    • 如果是服务器,可能有多个用户登录。如果只是一个工作站,那么可能只有1个,最好运行一下看看结果。
    【解决方案2】:

    我最终在以下帮助程序类中使用了“GetWindowsSessionUsername”方法,该方法从进程 ID 获取会话 ID,从会话 ID 获取用户名。

    internal class WtsUtils
    {
        /// <summary>
        /// Contains values that indicate the type of session information to retrieve in a call to the <see cref="WTSQuerySessionInformation"/> function.
        /// </summary>
        private enum WtsInfoClass
        {
            /// <summary>A null-terminated string that contains the name of the initial program that Remote Desktop Services runs when the user logs on.</summary>
            WtsInitialProgram,
            /// <summary>A null-terminated string that contains the published name of the application that the session is running.</summary>
            WtsApplicationName,
    
            /// <summary>A null-terminated string that contains the default directory used when launching the initial program.</summary>
            WtsWorkingDirectory,
    
            /// <summary>This value is not used.</summary>
            WtsOemId,
    
            /// <summary>A <B>ULONG</B> value that contains the session identifier.</summary>
           WtsSessionId,
    
            /// <summary>A null-terminated string that contains the name of the user associated with the session.</summary>
           WtsUserName,
    
            /// <summary>A null-terminated string that contains the name of the Remote Desktop Services session.</summary>
            /// <remarks>
            /// <B>Note</B>  Despite its name, specifying this type does not return the window station name.
            /// Rather, it returns the name of the Remote Desktop Services session.
            /// Each Remote Desktop Services session is associated with an interactive window station.
            /// Because the only supported window station name for an interactive window station is "WinSta0",
            /// each session is associated with its own "WinSta0" window station. For more information, see <see href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms687096(v=vs.85).aspx">Window Stations</see>.
            /// </remarks>
            WtsWinStationName,
    
            /// <summary>A null-terminated string that contains the name of the domain to which the logged-on user belongs.</summary>
            WtsDomainName,
    
            /// <summary>The session's current connection state. For more information, see WTS_CONNECTSTATE_CLASS.</summary>
            WtsConnectState,
    
            /// <summary>A <B>ULONG</B> value that contains the build number of the client.</summary>
            WtsClientBuildNumber,
    
            /// <summary>A null-terminated string that contains the name of the client.</summary>
            WtsClientName,
    
            /// <summary>A null-terminated string that contains the directory in which the client is installed.</summary>
            WtsClientDirectory,
    
            /// <summary>A <B>USHORT</B> client-specific product identifier.</summary>
            WtsClientProductId,
    
            /// <summary>
            /// A <B>ULONG</B> value that contains a client-specific hardware identifier. This option is reserved for future use.
            /// <see cref="WTSQuerySessionInformation" /> will always return a value of 0.
            /// </summary>
            WtsClientHardwareId,
    
            /// <summary>The network type and network address of the client. For more information, see WTS_CLIENT_ADDRESS.</summary>
            /// <remarks>
            /// The IP address is offset by two bytes from the start of the <B>Address</B> member of the WTS_CLIENT_ADDRESS structure.
            /// </remarks>
            WtsClientAddress,
    
            /// <summary>Information about the display resolution of the client. For more information, see WTS_CLIENT_DISPLAY.</summary>
            WtsClientDisplay,
    
            /// <summary>
            /// A USHORT value that specifies information about the protocol type for the session. This is one of the following values:<BR />
            /// 0 - The console session.<BR />
            /// 1 - This value is retained for legacy purposes.<BR />
            /// 2 - The RDP protocol.<BR />
            /// </summary>
            WtsClientProtocolType,
    
            /// <summary>
            /// This value returns <B>FALSE</B>. If you call Marshal.GetLastError to get extended error information, <B>GetLastError</B> returns <B>ERROR_NOT_SUPPORTED</B>.
            /// </summary>
            /// <remarks><B>Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP:</B>  This value is not used.</remarks>
            WtsIdleTime,
    
            /// <summary>
            /// This value returns <B>FALSE</B>. If you call GetLastError to get extended error information, <B>GetLastError</B> returns <B>ERROR_NOT_SUPPORTED</B>.
            /// </summary>
            /// <remarks><B>Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP:</B>  This value is not used.</remarks>
            WtsLogonTime,
    
            /// <summary>
            /// This value returns <B>FALSE</B>. If you call Marshal.GetLastError to get extended error information, <B>GetLastError</B> returns <B>ERROR_NOT_SUPPORTED</B>.
            /// </summary>
            /// <remarks><B>Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP:</B>  This value is not used.</remarks>
            WtsIncomingBytes,
    
            /// <summary>
            /// This value returns <B>FALSE</B>. If you call Marshal.GetLastError to get extended error information, <B>GetLastError</B> returns <B>ERROR_NOT_SUPPORTED</B>.
            /// </summary>
            /// <remarks><B>Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP:</B>  This value is not used.</remarks>
            WtsOutgoingBytes,
    
            /// <summary>
            /// This value returns <B>FALSE</B>. If you call Marshal.GetLastError to get extended error information, <B>GetLastError</B> returns <B>ERROR_NOT_SUPPORTED</B>.
            /// </summary>
            /// <remarks><B>Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP:</B>  This value is not used.</remarks>
            WtsIncomingFrames,
    
            /// <summary>
            /// This value returns <B>FALSE</B>. If you call Marshal.GetLastError to get extended error information, <B>GetLastError</B> returns <B>ERROR_NOT_SUPPORTED</B>.
            /// </summary>
            /// <remarks><B>Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP:</B>  This value is not used.</remarks>
            WtsOutgoingFrames,
    
            /// <summary>Information about a Remote Desktop Connection (RDC) client. For more information, see WTSCLIENT.</summary>
            /// <remarks>
            /// <B>Windows Vista, Windows Server 2003, and Windows XP:</B>  This value is not supported.
            /// This value is supported beginning with Windows Server 2008 and Windows Vista with SP1.
            /// </remarks>
            WtsClientInfo,
    
            /// <summary>Information about a client session on an RD Session Host server. For more information, see WTSINFO.</summary>
            /// <remarks>
            /// <B>Windows Vista, Windows Server 2003, and Windows XP:</B>  This value is not supported.
            /// This value is supported beginning with Windows Server 2008 and Windows Vista with SP1.
            /// </remarks>
            WtsSessionInfo
        }
    
        [DllImport("kernel32.dll")]
        private static extern bool ProcessIdToSessionId(uint dwProcessId, out uint sessionId);
    
        [DllImport("Wtsapi32.dll")]
        private static extern bool WTSQuerySessionInformation(IntPtr hServer, int sessionId, WtsInfoClass wtsInfoClass, out IntPtr ppBuffer, out int bytesReturned);
    
        [DllImport("Wtsapi32.dll")]
        private static extern void WTSFreeMemory(IntPtr pointer);
    
        public static string GetWindowsSessionUsername()
        {
            uint sessionId;
            ProcessIdToSessionId((uint)Process.GetCurrentProcess().Id, out sessionId);
    
            return GetUsernameBySessionId((int)sessionId);
        }
    
        private static string GetUsernameBySessionId(int sessionId)
        {
            IntPtr buffer;
            int strLen;
            string username = "SYSTEM";
            if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WtsInfoClass.WtsUserName, out buffer, out strLen) && strLen > 1)
            {
                username = Marshal.PtrToStringAnsi(buffer);
                WTSFreeMemory(buffer);
            }
            return username;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-06
      • 2014-10-16
      • 2012-04-12
      • 2017-10-15
      • 2013-04-19
      • 2014-12-25
      • 2014-05-01
      • 1970-01-01
      相关资源
      最近更新 更多