首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在.NET中检索已登录/已连接用户的列表?

如何在.NET中检索已登录/已连接用户的列表?
EN

Stack Overflow用户
提问于 2008-09-25 11:02:37
回答 4查看 49.5K关注 0票数 32

以下是场景:

您有一台Windows服务器,用户可以通过RDP远程连接到该服务器。您希望您的程序(作为服务运行)知道当前连接的是谁。这可能包括也可能不包括交互式控制台会话。

请注意,这是而不是,它与检索当前交互用户的方式不同。

我猜是不是有某种API访问终端服务来获取此信息?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2008-09-25 11:42:52

以下是我对这个问题的看法:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace EnumerateRDUsers
{
  class Program
  {
    [DllImport("wtsapi32.dll")]
    static extern IntPtr WTSOpenServer([MarshalAs(UnmanagedType.LPStr)] string pServerName);

    [DllImport("wtsapi32.dll")]
    static extern void WTSCloseServer(IntPtr hServer);

    [DllImport("wtsapi32.dll")]
    static extern Int32 WTSEnumerateSessions(
        IntPtr hServer,
        [MarshalAs(UnmanagedType.U4)] Int32 Reserved,
        [MarshalAs(UnmanagedType.U4)] Int32 Version,
        ref IntPtr ppSessionInfo,
        [MarshalAs(UnmanagedType.U4)] ref Int32 pCount);

    [DllImport("wtsapi32.dll")]
    static extern void WTSFreeMemory(IntPtr pMemory);

    [DllImport("wtsapi32.dll")]
    static extern bool WTSQuerySessionInformation(
        IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass, out IntPtr ppBuffer, out uint pBytesReturned);

    [StructLayout(LayoutKind.Sequential)]
    private struct WTS_SESSION_INFO
    {
      public Int32 SessionID;

      [MarshalAs(UnmanagedType.LPStr)]
      public string pWinStationName;

      public WTS_CONNECTSTATE_CLASS State;
    }

    public enum WTS_INFO_CLASS
    {
      WTSInitialProgram,
      WTSApplicationName,
      WTSWorkingDirectory,
      WTSOEMId,
      WTSSessionId,
      WTSUserName,
      WTSWinStationName,
      WTSDomainName,
      WTSConnectState,
      WTSClientBuildNumber,
      WTSClientName,
      WTSClientDirectory,
      WTSClientProductId,
      WTSClientHardwareId,
      WTSClientAddress,
      WTSClientDisplay,
      WTSClientProtocolType
    }

    public enum WTS_CONNECTSTATE_CLASS
    {
      WTSActive,
      WTSConnected,
      WTSConnectQuery,
      WTSShadow,
      WTSDisconnected,
      WTSIdle,
      WTSListen,
      WTSReset,
      WTSDown,
      WTSInit
    }

    static void Main(string[] args)
    {
      ListUsers(Environment.MachineName);
    }

    public static void ListUsers(string serverName)
    {
      IntPtr serverHandle = IntPtr.Zero;
      List<string> resultList = new List<string>();
      serverHandle = WTSOpenServer(serverName);

      try
      {
        IntPtr sessionInfoPtr = IntPtr.Zero;
        IntPtr userPtr = IntPtr.Zero;
        IntPtr domainPtr = IntPtr.Zero;
        Int32 sessionCount = 0;
        Int32 retVal = WTSEnumerateSessions(serverHandle, 0, 1, ref sessionInfoPtr, ref sessionCount);
        Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));
        IntPtr currentSession = sessionInfoPtr;
        uint bytes = 0;

        if (retVal != 0)
        {
          for (int i = 0; i < sessionCount; i++)
          {
            WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)currentSession, typeof(WTS_SESSION_INFO));
            currentSession += dataSize;

            WTSQuerySessionInformation(serverHandle, si.SessionID, WTS_INFO_CLASS.WTSUserName, out userPtr, out bytes);
            WTSQuerySessionInformation(serverHandle, si.SessionID, WTS_INFO_CLASS.WTSDomainName, out domainPtr, out bytes);

            Console.WriteLine("Domain and User: " + Marshal.PtrToStringAnsi(domainPtr) + "\\" + Marshal.PtrToStringAnsi(userPtr));

            WTSFreeMemory(userPtr); 
            WTSFreeMemory(domainPtr);
          }

          WTSFreeMemory(sessionInfoPtr);
        }
      }
      finally
      {
        WTSCloseServer(serverHandle);
      }

    }

  }
}
票数 37
EN

Stack Overflow用户

发布于 2009-05-01 01:56:05

如果您不想自己处理P/Invoke,另一种选择是使用Cassia库:

代码语言:javascript
复制
using System;
using System.Security.Principal;
using Cassia;

namespace CassiaSample
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            ITerminalServicesManager manager = new TerminalServicesManager();
            using (ITerminalServer server = manager.GetRemoteServer("your-server-name"))
            {
                server.Open();
                foreach (ITerminalServicesSession session in server.GetSessions())
                {
                    NTAccount account = session.UserAccount;
                    if (account != null)
                    {
                        Console.WriteLine(account);
                    }
                }
            }
        }
    }
}
票数 20
EN

Stack Overflow用户

发布于 2008-09-25 11:17:43

好的,对我自己的问题有一个解决方案。

您可以使用WMI检索正在运行的进程的列表。您还可以查看这些进程的所有者。如果您查看"explorer.exe“的所有者(并删除重复项),您最终应该会得到一个登录用户的列表。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/132620

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档