【问题标题】:Detect source of remote desktop connection检测远程桌面连接的来源
【发布时间】:2010-03-17 10:10:20
【问题描述】:

This question 告诉我如何检测远程桌面会话。

有人知道是否有可能找出远程连接的初始化位置吗?

【问题讨论】:

    标签: c# windows delphi remote-desktop terminal-services


    【解决方案1】:

    @Vegar,您可以使用WTSEnumerateSessionsWTSQuerySessionInformation 函数来检索此信息。

    查看link 以获取使用Jedi Api Headers 的示例。

    检查此代码。

    program ProjectTsInfo;
    
    {$APPTYPE CONSOLE}
    
    Uses
      Windows,
      JwaWinType,
      JwaWtsApi32,
      JwaWinsock2,
      SysUtils,
      TypInfo;
    
    
    type
      PWtsSessionInfoAArray = ^TWtsSessionInfoAArray;
      TWtsSessionInfoAArray = array[0..ANYSIZE_ARRAY-1] of WTS_SESSION_INFOA;
    
    //Get the info for all clients connected
    procedure GetAll_TSClientsInfo;
    var
      SessionInfoAArray: PWtsSessionInfoAArray;
      ClientAddr       : PWtsClientAddress;
      ClientName       : PAnsiChar;
      //ClientInfo       : PWTSCLIENT;
      RetBytes         : Cardinal;
      IPAddr           : String;
      i                : integer;
      pCount           : Cardinal;
      SessionId        : Cardinal;
    begin
    
      if WtsEnumerateSessions(WTS_CURRENT_SERVER, 0, 1, PWTS_SESSION_INFO(SessionInfoAArray),  pCount) then
      begin
    
        for i := 0 to pCount - 1 do
        begin
          SessionId:=SessionInfoAArray^[i].SessionId;
          WTSQuerySessionInformation(WTS_CURRENT_SERVER, SessionId, WTSClientAddress, Pointer(ClientAddr), RetBytes);
          WTSQuerySessionInformation(WTS_CURRENT_SERVER, SessionId, WTSClientName, Pointer(ClientName), RetBytes);
          //WTSQuerySessionInformation(WTS_CURRENT_SERVER, SessionId, WTSClientInfo, Pointer(ClientInfo), RetBytes);  //This value is supported for Windows Server 2008 and Windows Vista with SP1.
    
         try
          case ClientAddr^.AddressFamily of
            AF_INET:
              IPAddr:= Format('%d.%d.%d.%d', [
                ClientAddr^.Address[2],
                ClientAddr^.Address[3],
                ClientAddr^.Address[4],
                ClientAddr^.Address[5]
                ]);
            else
            IPAddr:= '<unknow>';
          end;
    
          WriteLn(Format('Session Id  : %d ', [SessionId]));
          WriteLn(Format('Client Name : %s ', [ClientName]));
          WriteLn(Format('Station Name: %s ', [SessionInfoAArray^[i].pWinStationName]));
          WriteLn(Format('State       : %s ', [GetEnumName(TypeInfo(WTS_CONNECTSTATE_CLASS),integer(SessionInfoAArray^[i].State))]));
          WriteLn(Format('IP          : %s ', [IPAddr]));
    
          //supported for Windows Server 2008 and Windows Vista with SP1.
          {
          WriteLn(Format('ClientName      : %s ', [ClientInfo^.ClientName]));
          WriteLn(Format('Domain          : %s ', [ClientInfo^.Domain]));
          WriteLn(Format('UserName        : %s ', [ClientInfo^.UserName]));
          WriteLn(Format('WorkDirectory   : %s ', [ClientInfo^.WorkDirectory]));
          WriteLn(Format('InitialProgram  : %s ', [ClientInfo^.InitialProgram]));
          WriteLn(Format('EncryptionLevel : %d ', [ClientInfo^.EncryptionLevel]));
          WriteLn(Format('HRes            : %d ', [ClientInfo^.HRes]));
          WriteLn(Format('VRes            : %d ', [ClientInfo^.VRes]));
          WriteLn(Format('ColorDepth      : %d ', [ClientInfo^.ColorDepth]));
          WriteLn(Format('ClientDirectory : %s ', [ClientInfo^.ClientDirectory]));
          }
          Writeln('');
    
       finally
          WTSFreeMemory(ClientAddr);
          WTSFreeMemory(ClientName);
       end;
        end;
      end;
    
      WtsFreeMemory(SessionInfoAArray);
    end;
    
    //Get the ip address of the actual connected client
    function GetIpActualClient : string;
    var
      ClientAddr       : PWtsClientAddress;
      RetBytes         : Cardinal;
      IPAddr           : String;
      SessionId        : Cardinal;
    begin
          SessionId:=WTS_CURRENT_SESSION;
          WTSQuerySessionInformation(WTS_CURRENT_SERVER, SessionId, WTSClientAddress, Pointer(ClientAddr), RetBytes);
          try
            case ClientAddr^.AddressFamily of
              AF_INET:
                IPAddr:= Format('%d.%d.%d.%d', [
                  ClientAddr^.Address[2],
                  ClientAddr^.Address[3],
                  ClientAddr^.Address[4],
                  ClientAddr^.Address[5]
                  ]);
              else
              IPAddr:= '<unknow>';
            end;
          Result:=IPAddr;
          finally
           WTSFreeMemory(ClientAddr);
          end;
    end;
    
    begin
      Writeln('IP Actual client '+GetIpActualClient);
      Writeln('-----------------------------------');
    
      GetAll_TSClientsInfo;
      Readln;
    end.
    

    更新

    正如@Remko 所说,具有 WTSClientAddress 类型的 WTSQuerySessionInformation 函数可以返回客户端的本地 IP。如果你想获得真实的 ip,你可以使用位于 JwaWinSta 单元中的 WinStationGetRemoteIPAddress 帮助函数。

    Var
    Port    : Word;
    IpAddr  : WideString;
    Begin
    WinStationGetRemoteIPAddress(WTS_CURRENT_SERVER,WTS_CURRENT_SESSION,IpAddr,Port);
    End;
    

    【讨论】:

    • 还有必要用WTSEnumerateSessions吗?我认为使用 wts_Current_Session 作为会话 ID 就足够了。
    • 要获得自己的会话,请使用 ProcessIdToSessionId
    • @Rob 你是对的,WTSEnumerateSessions 功能是获取所有会话的信息,我发布了一个使用 wts_Current_Session 和 WTSEnumerateSessions 的示例。 ;)
    • 我现在正在尝试 WinStationGetRemoteIPaddress( )。我在家里用 RDC 连接我的办公室电脑。当我调用这个方法时,它返回的是我的路由器的 IP 地址,而不是我的本地机器。顺便说一句,netstat 在这种情况下返回 WORKGROUP。不太有用...
    • @Vegar:是的,当然可以,您使用 external ip 进行连接,在大多数情况下,该 ip 是您的路由器或调制解调器拥有的 ip。 WinStationGetRemoteIPAddress 返回终端服务器报告的 IP 地址,它将匹配服务器上 netstat 的输出。
    【解决方案2】:

    对我来说,这很有效,它获取了连接机器的名称。

    Environment.GetEnvironmentVariable("CLIENTNAME")
    

    【讨论】:

      【解决方案3】:

      因为它在 Windows 中,所以使用 netstat 检查您连接到哪些机器以及在哪些端口上,然后解析出使用远程桌面使用的端口的那台的地址。

      【讨论】:

      • 而且由于远程桌面总是使用端口 3389,这将起作用。谢谢!
      • 这只有在你有一个远程连接时才有效,否则你看不到哪些会话连接到哪台远程机器。
      • netstat 的输出是否受当前语言环境影响?这会使字符串解析 much 更加复杂。更喜欢 API 解决方案,而不是依赖外部程序和可变输出格式的解决方案。
      • 是的,我同意这是一个糟糕的解决方案,但它的速度很快。
      • 远程桌面并不总是使用端口 3389,这可以是用户定义的,如果没有使用 vpn,通常是为了安全
      【解决方案4】:

      WTSQuerySessionInformation 在客户端报告时返回客户端 IP,这可能是其本地 IP 地址的(一个)。如果您想知道连接的真实 IP 地址和端口,您可以使用带有信息类 WinStationRemoteAddress 的 WinStationQueryInformationW。 您将需要 Jedi Apilib 的我的单位 JwaWinsta。

      我也在同一个单元中提供了一个简单的包装器:

      function WinStationGetRemoteIPAddress(hServer: HANDLE; SessionId: DWORD;
        var RemoteIPAddress: WideString; var Port: WORD): Boolean;
      

      【讨论】:

      • +1 @Remko 你是对的,WTSClientAddress 可以报告本地 ip 而不是真实 ip。我更新我的答案。 p.s:非常感谢您在 Jedi Api Headers 中所做的出色工作。 ;)
      【解决方案5】:

      尝试运行qwinsta

      【讨论】:

        【解决方案6】:

        如果您想获取远程会话 ID 并获取通过 Citrix 连接的 IP 地址,您可以使用以下内容。这旨在在用户通过 citrix 会话连接到服务器时运行,并为它连接的 IP 地址显示/创建一个字符串。

        // Prints out ICA or RDP session ID of current user & gets ICA session clientAddress variable
        
        using System;
        using Microsoft.Win32;
        
        namespace ViaRegedit
        {
            class Program03
            {
                static void Main(string[] args)
                {
                    // Obtain an instance of RegistryKey for the CurrentUser registry 
                    RegistryKey rkCurrentUser = Registry.CurrentUser;
                    // Obtain the test key (read-only) and display it.
                    RegistryKey rkTest = rkCurrentUser.OpenSubKey("Remote");
        
                    foreach (string valueName in rkTest.GetSubKeyNames())
                    {
                        //Getting path to RDP/Citrix session ID
                        string RDPICApath = "";
                        if (rkTest.OpenSubKey(valueName) != null && rkTest.OpenSubKey(valueName) != null) { RDPICApath = rkTest.OpenSubKey(valueName).ToString(); }
                        Console.WriteLine("Getting CurrentUser ICA-RDP path from string = " + RDPICApath);
        
                        //Split RDPICApath to get session number
                        string RDPICAnumber = RDPICApath.Substring(RDPICApath.LastIndexOf('\\') + 1);
                        Console.WriteLine("Current User RDPICAnumber = " + RDPICAnumber);
        
                        //Getting reg local machine info for Citrix based on RDP/Citrix session ID "RDPICAnumber"
                        string regLocal = @"SOFTWARE\Citrix\Ica\Session\" + RDPICAnumber + @"\Connection";
                        RegistryKey localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
                        RegistryKey citrixKey = localKey.OpenSubKey(regLocal);
                        Console.WriteLine("Registry " + citrixKey + " Does Exist - going to get ClientAddress");
                        //getting clietAddress var from citrixKey 
                        string clientAddress = "";
                        if (citrixKey != null && citrixKey.GetValue("clientAddress") != null)
                            {clientAddress = citrixKey.GetValue("clientAddress").ToString();}
                            Console.WriteLine("Getting current user clientAddress from string = " + clientAddress); 
                    }
                    rkTest.Close();
                    rkCurrentUser.Close();
                    Console.ReadLine();
                }
            }
        
        }
        

        【讨论】:

          猜你喜欢
          • 2010-11-01
          • 2012-07-22
          • 1970-01-01
          • 2015-02-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多