8

我正在寻找可以调用的 API/函数,以确定软件是否在 Citrix、终端服务或独立 PC 上运行。理想情况下,它会像这样工作:

Select Case APIWhatSystem.Type.ToString
   Case "Citrix"
      bCitrix = True
   Case "TS"
      bTerminalServices = True
   Case "PC"
      bPC = True
End Select

我更喜欢通过 API 调用工作的东西,而不是查看注册表中的东西,因为我们有越来越多的客户锁定注册表。

谢谢。

4

4 回答 4

15

有一个 API 函数可让您确定特定用户会话是显示在控制台上(本地)还是通过远程协议 Citrix ICA(现在称为 HDX)或 Microsoft RDP 之一。

调用WTSQuerySessionInformation并将第三个参数设置为WTSClientProtocolType。函数返回:

  • 0 用于控制台会话
  • 1 用于 ICA 会话
  • 2 用于 RDP 会话

有趣的是,返回值 1 不再记录为WTS_PROTOCOL_TYPE_ICAMSDN (上面的第二个链接),而是“此值保留用于遗留目的。”。

更新:

无法检测XenDesktopWTSQuerySessionInformation会话(它返回 0,表示控制台)。如果你想要一个通用的解决方案:

  • 打电话WTSQuerySessionInformation。如果返回 1 或 2(ICA 或 RDP),您就完成了。
  • 如果WTSQuerySessionInformation返回0(Console),动态加载wfapi.dll并获取地址WFGetActiveProtocol
  • 调用WFGetActiveProtocol参数为WF_CURRENT_SESSION,定义为 ((DWORD)-1)
  • 的返回值WFGetActiveProtocol是会话类型。它应该是 0(控制台)或 1(ICA)

我已经在这里详细描述了这个过程以及一个 C++ 代码示例和一个返回当前会话的远程协议类型的工作编译工具。

于 2010-11-15T21:28:38.603 回答
9

根据:http : //forums.citrix.com/message.jspa?messageID=1363711 您可以检查 SESSIONNAME 环境变量。

另一种更简单的方法是读取系统环境变量“SESSIONNAME”。如果它存在并以“ICA”开头,那么您正在 Citrix 会话中运行。如果它以“RDP”开头,那么您正在 RDP 会话中运行。

我用我的电脑对其进行了测试,并在本地得到:

C:\>echo %SESSIONNAME%
Console

虽然远程我得到了

C:\>echo %SESSIONNAME%
RDP-tcp1

所以看起来这可能是一条简单的路线,否则听起来像是检查注册表值或者是否存在某些 dll 将是下一个最好的事情。

于 2010-11-15T16:12:20.253 回答
2

在@Josh 的回答之后,代码如下所示:

Select Case Environment.GetEnvironmentVariable("SessionName").ToUpper.SubString(0,3))
   Case "ICA" 
      bCitrix = True
   Case "RDP"
      bTerminalServer = True
   Case "CON" 
      bPC = True
End Select

我还没有完全测试它,但看起来它会做我想要的。PC 和终端服务器报告正确。

如果有人有办法在 Citrix 机器上对此进行测试,将不胜感激!

于 2010-11-15T21:19:11.307 回答
2

根据 Helge Klein 的修订答案(上图),我想我会发布 VBA 代码以实现这一点,以帮助未来的 VBA 用户访问此页面。Helge 在他自己的网站上已经有了 C++ 代码。如果您觉得这有帮助,请支持 Helge Klein 的回答。

Option Explicit

Private Const WTS_CURRENT_SERVER_HANDLE = 0&
Private Const WTS_CURRENT_SESSION As Long = -1

Private Enum WTS_INFO_CLASS
    WTSInitialProgram
    WTSApplicationName
    WTSWorkingDirectory
    WTSOEMId
    WTSSessionId
    WTSUserName
    WTSWinStationName
    WTSDomainName
    WTSConnectState
    WTSClientBuildNumber
    WTSClientName
    WTSClientDirectory
    WTSClientProductId
    WTSClientHardwareId
    WTSClientAddress
    WTSClientDisplay
    WTSClientProtocolType
    WTSIdleTime
    WTSLogonTime
    WTSIncomingBytes
    WTSOutgoingBytes
    WTSIncomingFrames
    WTSOutgoingFrames
    WTSClientInfo
    WTSSessionInfo
    WTSSessionInfoEx
    WTSConfigInfo
    WTSValidationInfo
    WTSSessionAddressV4
    WTSIsRemoteSession
End Enum

Private Declare Function WTSQuerySessionInformation _
    Lib "wtsapi32.dll" Alias "WTSQuerySessionInformationA" ( _
    ByVal hServer As Long, ByVal SessionId As Long, _
    ByVal WtsInfoClass As WTS_INFO_CLASS, _
    ByRef ppBuffer As LongPtr, _
    ByRef pBytesReturned As LongPtr _
    ) As Long

Private Declare Function WFGetActiveProtocol _
    Lib "wfapi.dll" ( _
    ByVal SessionId As Long _
    ) As Long

Private Declare Sub WTSFreeMemory Lib "wtsapi32.dll" ( _
    ByVal pMemory As Long)

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
    Destination As Any, Source As Any, ByVal length As Long)

Public Function SessionType() As String
    Dim ResultCode As Long
    Dim p As LongPtr
    Dim ppBuffer As LongPtr
    Dim pBytesReturned As Long
    Dim ClientProtocolType As Integer
    ResultCode = WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSClientProtocolType, ppBuffer, pBytesReturned)

    If ResultCode = 0 Then
        p = ppBuffer
        CopyMemory ClientProtocolType, ByVal p, pBytesReturned
        WTSFreeMemory ppBuffer
    End If

    Select Case ClientProtocolType
      Case 0:
        On Error Resume Next
        ResultCode = WFGetActiveProtocol(WTS_CURRENT_SESSION)
        If Err.Number = 53 Then
          SessionType = "Console"
        ElseIf Err.Number = 0 Then
          If ResultCode = 1 Then
            SessionType = "Citrix"
          Else
            SessionType = "Console"
          End If
        End If
        Err.Clear
        On Error GoTo 0
      Case 1:
        SessionType = "Citrix"
      Case 2:
        SessionType = "RDP"
      Case Else
        SessionType = "Other (" & ClientProtocolType & ")"
    End Select
End Function

我已经在 XenApp 和 XenDesktop 上对此进行了测试。

于 2014-08-08T15:27:17.330 回答