【问题标题】:API for Determining if App is Running on Citrix or Terminal Services [closed]用于确定应用程序是否在 Citrix 或终端服务上运行的 API [关闭]
【发布时间】:2010-11-15 15:57:16
【问题描述】:

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

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

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

谢谢。

【问题讨论】:

  • 我发现了这个... SystemInformation.TerminalServerSession 它返回布尔值,因此可以回答 TS 问题。我不确定它是否为 Citrix 返回 bool。仍在调查中。
  • 我发现 Citrix 和 Windows 2008 Server TS ThinApp 确实如此。
  • Citrix SDK 在其WFAPI SDK 中提及WFQuerySessionInformation,例如citrix.com/content/dam/citrix/en_us/documents/downloads/sdk/…

标签: vb.net api citrix terminal-services


【解决方案1】:

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

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

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

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

更新:

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

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

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

【讨论】:

  • 如果该函数返回任何大于 0 的数字,您认为是否可以安全地假设应用程序未在 PC 上运行? IE。它必须在某种服务器上运行。我在想未来 5 年......无论哪种方式,非零都应该总是表示 PC 以外的东西,对吧?
  • 是的,我认为如果可以安全地假设任何 > 0 是......不是本地的。请注意措辞上的差异。它可以很好地在 PC 上运行,但随着今天的热门话题“VDI”又名虚拟桌面通过某种远程协议提供服务(想想 2008 R2 SP1 - RemoteFX),PC 很快成为单会话终端服务器的可能性稳步增加。
  • 如果应用程序在 Citrix XenApp 下运行,则 WTSClientProtocolType 将返回 1。但是,如果应用程序在 Citrix XenDesktop 下运行,则 WTSClientProtocolType 将返回 0。我仍在寻找检测方法它不涉及枚举设备和寻找已知的虚拟驱动程序。
  • @DHW:XenApp 和 XenDesktop 与操作系统的交互方式根本不同。而 XenApp 正式告诉操作系统它使用远程协议 XenDesktop 重定向控制台会话。因此,用户会话不是 WTS 会话,并且 WTSQuerySessionInformation 没有帮助。您应该问另一个关于 XenDesktop 的问题。
  • @DHW:我刚刚检查了安装了 XenDesktop 5.6 VDA 的 Windows 7 x64 机器。 Wfapi.dll 和 Wfapi64.dll 位于 VDA 安装目录的子目录“ICAService”中。它也应该在路径中,以便您可以在控制台上使用“where wfapi.dll”找到它。
【解决方案2】:

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

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

我用我的电脑测试了它,我在本地得到了:

C:\>echo %SESSIONNAME%
Console

虽然我得到了远程

C:\>echo %SESSIONNAME%
RDP-tcp1

所以这似乎是一条简单的路线,否则听起来像是检查注册表值或是否存在某些 dll 将是下一个最好的选择。

【讨论】:

    【解决方案3】:

    按照@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 机器上对此进行测试,我们将不胜感激!

    【讨论】:

    • 为我工作。在我的 citrix 服务器上,?environ("SessionName") 返回 ICA-tcp#56
    • 注意,在 Windows 2008 TS RemoteApp 模式下这个 env.variable 是不存在的
    • 我刚刚在我的基础架构上运行了它,我得到了 SESSIONNAME=Console,所以它似乎不再是一种可靠的方法了。
    【解决方案4】:

    根据 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 上对此进行了测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-04
      • 2012-02-20
      • 1970-01-01
      • 1970-01-01
      • 2014-06-08
      • 1970-01-01
      • 2010-09-15
      相关资源
      最近更新 更多