API para Determinar si la Aplicación se está Ejecutando en Citrix o Terminal Services

Estoy en busca de un API/función que puede llamar para determinar si se está ejecutando el software de Citrix, Terminal de Servicios, o en un puesto de PC. De manera óptima, sería trabajar algo como esto:

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

Yo preferiría algo que funcionaba a partir de una llamada a la API en vez de buscar algo en el registro que vamos a tener más y más los clientes que están cerrando el registro.

Gracias.

He encontrado esto… SystemInformation.TerminalServerSession que devuelve el valor Booleano, por lo que las respuestas que el TS pregunta. No estoy seguro de si devuelve bool para Citrix. Sigue investigando.
He encontrado es cierto para Citrix y Windows 2008 Server de TS ThinApp.

OriginalEl autor John Cruz | 2010-11-15

4 respuestas

  1. 7

    De acuerdo a: http://forums.citrix.com/message.jspa?messageID=1363711 puede comprobar el SESSIONNAME variable de entorno.

    Otra manera más sencilla es leer la variable de entorno del sistema “SESSIONNAME”. Si existe y se inicia con “ICA”, a continuación, ejecuta dentro de una sesión de Citrix. Si comienza con “RDP”, a continuación, ejecuta dentro de una sesión RDP.

    He probado con mi PC y, a nivel local puedo conseguir:

    C:\>echo %SESSIONNAME%
    Console

    Mientras remotamente tengo

    C:\>echo %SESSIONNAME%
    RDP-tcp1

    Por lo que parece que podría ser un camino fácil para ir, de lo contrario suena como la comprobación de valores del registro o si ciertos archivos dll existe será la mejor cosa siguiente.

    OriginalEl autor Josh Weatherly

  2. 12

    No es una función de la API que permite determinar si una determinada sesión de usuario se muestran en la consola (a nivel local) o a través de uno de los protocolos de comunicación remota Citrix ICA (hoy en día llamado HDX) o Microsoft RDP.

    Llamada WTSQuerySessionInformation con el 3er set de parámetros a WTSClientProtocolType. La función devuelve:

    • 0 para las sesiones de la consola
    • 1 de sesiones ICA
    • 2 para sesiones RDP

    Curiosamente, el valor de retorno de 1 no está documentado como WTS_PROTOCOL_TYPE_ICA en MSDN (segundo enlace de arriba), sino como “Este valor se mantiene por legado fines.”.

    Actualización:

    XenDesktop sesiones no puede ser detectado con WTSQuerySessionInformation (devuelve 0, el significado de la Consola). Si desea una solución universal:

    • Llamada WTSQuerySessionInformation. Si devuelve 1 o 2 (ICA y RDP), que se realizan.
    • Si WTSQuerySessionInformation devuelve 0 (Consola), cargar dinámicamente wfapi.dll y obtener la dirección de WFGetActiveProtocol
    • Llamada WFGetActiveProtocol con un parámetro de WF_CURRENT_SESSION, que se define como ((DWORD)-1)
    • El valor de retorno de WFGetActiveProtocol es el tipo de sesión. Debe ser 0 (Consola) o 1 (ICA)

    He descrito en detalle el proceso aquí junto con un código C++ de la muestra y un trabajo compilado herramienta que devuelve el actual período de sesiones de la remoting tipo de protocolo.

    ¿Crees que sería seguro asumir que si la función devuelve CUALQUIER número mayor que 0, la aplicación no se está ejecutando en un PC? es decir. Eso tiene que estar en ejecución en algún tipo de servidor. Estoy pensando en como 5 años en el futuro… de cualquier manera no-cero siempre debe indicar algo distinto de un PC, ¿verdad?
    Sí, yo creo que si sería seguro asumir que cualquier cosa > 0 … NO LOCAL. Por favor, tenga en cuenta la diferencia en la redacción. Puede muy bien ejecutar en un PC, pero hoy, con el tema “VDI” aka escritorios virtuales, servido sobre algunos remoting (protocolo de pensar 2008 R2 SP1 – RemoteFX) la probabilidad aumenta de manera constante de la Pc a convertirse en 1-sesión de servidores de terminal server pronto.
    Si la aplicación se ejecuta en el servidor Citrix XenApp, entonces WTSClientProtocolType devolverá 1. Sin embargo, si la aplicación se está ejecutando bajo Citrix XenDesktop, entonces WTSClientProtocolType devolverá 0. Todavía estoy buscando una manera de detectar que no se trata de enumerar los dispositivos y buscando conocido controladores virtuales.
    XenApp y XenDesktop son fundamentalmente diferentes en la forma en que la interfaz con el sistema operativo. Mientras que XenApp oficialmente le dice al sistema operativo que utiliza un protocolo de comunicación remota XenDesktop redirige a la sesión de consola. La sesión del usuario, por tanto, no es un WTS sesión y WTSQuerySessionInformation no ayuda. Usted debe preguntar a otra pregunta con respecto a XenDesktop.
    Acabo de comprobar en un Windows 7 de 64 bits de la máquina con el XenDesktop 5.6 VDA instalado. Wfapi.dll y Wfapi64.dll se encuentran en el subdirectorio “ICAService” de la VDA directorio de instalación. También debe estar en la ruta, por lo que se puede encontrar en la consola con “donde wfapi.dll”.

    OriginalEl autor Helge Klein

  3. 3

    Seguir a @Josh respuesta, el código sería este:

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

    Yo aún no has probado aún, pero parece que va a hacer lo que yo quiero. PCs y Servidores de Terminal server informes correctamente.

    Si alguien tiene una manera de probar esto en un cuadro de Citrix, sería muy apreciada!

    A mí me funciona. En mi servidor citrix ?environ("SessionName") devuelve ICA-tcp#56.
    Aviso, que en Windows 2008 RemoteApp de TS modo de env.variable está ausente

    OriginalEl autor John Cruz

  4. 2

    Basado en Helge Klein revisado de respuesta (arriba) y yo pensé que había puesto el código VBA para hacer que esto suceda para ayudar a los futuros VBA usuarios de golpear a esta página. Helge ya tiene el código de C++ en su propio sitio. Si usted encuentre útil esta información, por favor upvote Helge Klein respuesta.

    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

    He probado esto en XenApp y XenDesktop.

    OriginalEl autor DHW

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *