Как получить список вошедших/подключенных пользователей в .NET?

Вот сценарий:

У вас есть сервер Windows, к которому пользователи удаленно подключаются через RDP. Вы хотите, чтобы ваша программа (которая работает как служба) знала, кто в данный момент подключен. Это может включать или не включать сеанс интерактивной консоли.

Обратите внимание, что это не то же самое, что просто получить текущего интерактивного пользователя.

Я предполагаю, что есть какой-то API-доступ к службам терминалов для получения этой информации?


person James    schedule 25.09.2008    source источник


Ответы (4)


Вот мой взгляд на проблему:

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);
      }

    }

  }
}
person Magnus Johansson    schedule 25.09.2008
comment
Привет, Магнус, я попробовал ваш код, но он просто вернул вошедшего в систему пользователя в текущую клиентскую систему в моей локальной сети. Есть ли способ получить всех вошедших в систему пользователей с системным именем клиента в локальной сети с помощью приведенного выше кода? - person M_Mogharrabi; 22.01.2013
comment
@M_Mogharrabi, извините, ваш вопрос не имеет для меня никакого смысла. Этот код предназначен для запуска на сервере, я не знаю, что вы имеете в виду под текущей клиентской системой. Не могли бы вы перефразировать? - person Magnus Johansson; 22.01.2013
comment
@Magnus, спасибо за ваш ответ, я хочу получить список пользователей, которые сейчас вошли в локальную сеть, и я подумал, что ваш код может это сделать (я не знал, что он должен работать на сервере). Поэтому я попробовал клиентской системе, но он только что вернул пользователя, который вошел в систему в этой клиентской системе. - person M_Mogharrabi; 26.01.2013
comment
Этот фрагмент кода предназначен для возврата вошедших в систему пользователей RD на определенном сервере. - person Magnus Johansson; 26.01.2013
comment
должно ли имя сервера быть \\servername или servername, потому что по какой-то причине он не может подключиться - person Si8; 04.04.2017


Хорошо, одно решение моего собственного вопроса.

Вы можете использовать WMI для получения списка запущенных процессов. Вы также можете посмотреть на владельцев этих процессов. Если вы посмотрите на владельцев «explorer.exe» (и удалите дубликаты), вы должны получить список вошедших в систему пользователей.

person James    schedule 25.09.2008
comment
Пример предложения Джеймса можно увидеть здесь: github.com/R-Smith/Splice-Admin/blob/master/Splice%20Admin/ Что интересно, R-Smith пошла еще дальше и проверяет, является ли это сервером, используя API служб удаленных рабочих столов. для получения информации о сеансе. - person Alberto Guerrero; 17.05.2020

person    schedule
comment
Это дает вам некоторую полезную информацию, но не имена пользователей. - person James; 25.09.2008
comment
Как мы это называем? - person Si8; 04.04.2017