2010-11-15 25 views
8

Estoy buscando una API/función a la que pueda llamar para determinar si el software se está ejecutando en Citrix, Terminal Services o una PC independiente. De manera óptima, que funcionaría así:API para determinar si la aplicación se ejecuta en Citrix o Servicios de Terminal Server

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

yo preferiría algo que funcionó a partir de una llamada a la API en lugar de mirar algo en el registro como estamos teniendo más y más clientes que están de bloqueo hacia abajo el registro .

Gracias.

+2

He encontrado esto ... SystemInformation.TerminalServerSession que devuelve un valor booleano, por lo que responde a la pregunta TS. No estoy seguro si devuelve bool para Citrix. Todavía investigando. –

+0

Lo encontré verdadero para Citrix y Windows 2008 Server TS ThinApp. –

Respuesta

6

Según: http://forums.citrix.com/message.jspa?messageID=1363711 puede verificar la variable de entorno SESSIONNAME.

Otra forma más sencilla es leer la variable de entorno del sistema "SESSIONNAME". Si existe y comienza con "ICA", entonces se está ejecutando dentro de una sesión de Citrix. Si comienza con "RDP", entonces se está ejecutando dentro de una sesión RDP.

he comprobado con mi PC y localmente me sale:

C:\>echo %SESSIONNAME% 
Console 

Mientras remotamente llegué

C:\>echo %SESSIONNAME% 
RDP-tcp1 

por lo que parece que podría ser una ruta fácil para ir, de lo contrario, suena como verificar valores de registro o si existen ciertos archivos DLL será la mejor opción.

3

Siguiendo @ respuesta de Josh, el código se vería así:

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

no he totalmente probado todavía, pero parece que va a hacer lo que quiera. Las PC y los servidores de terminales informan correctamente.

Si alguien tiene una forma de probar esto en una caja de Citrix, sería muy apreciado.

+0

Funciona para mí. En mi servidor citrix '? Environ (" SessionName ")' devuelve 'ICA-tcp # 56'. – mischab1

+3

Tenga en cuenta que en el modo Windows 2003 TS RemoteApp esta variable env.est está ausente – user545829

11

Hay una función API que le permite determinar si una sesión de usuario específica se muestra en la consola (localmente) o mediante uno de los protocolos remotos Citrix ICA (hoy llamado HDX) o Microsoft RDP.

Llame al WTSQuerySessionInformation con el tercer parámetro establecido en WTSClientProtocolType. La función devuelve:

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

Es interesante que el valor de retorno de 1 no se documenta como WTS_PROTOCOL_TYPE_ICA en MSDN (segundo enlace arriba) más, pero como "Este valor se retiene para fines heredados".

Actualización:

XenDesktop sesiones no pueden ser detectados con WTSQuerySessionInformation (devuelve 0, lo que significa consola).Si desea una solución universal:

  • Llame WTSQuerySessionInformation. Si eso devuelve 1 o 2 (ICA o RDP), ha terminado.
  • Si WTSQuerySessionInformation retornos 0 (consola), carga de forma dinámica wfapi.dll y obtener la dirección de WFGetActiveProtocol
  • Call 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 (Console) o 1 (ICA)

he descrito el proceso en detalle here junto con una C++ ejemplo de código y una herramienta de trabajo compilado que devuelve el tipo de protocolo de interacción remota de la sesión actual.

+0

¿Cree que sería seguro asumir que si esa función devuelve CUALQUIER número mayor que 0, la aplicación no se está ejecutando en una PC? es decir. Tiene que estar ejecutándose en algún tipo de servidor. Estoy pensando en 5 años en el futuro ... en cualquier caso, un no cero siempre debería indicar algo más que una PC, ¿no? –

+0

Sí, creo que sería seguro asumir que cualquier cosa> 0 es ... NO LOCAL. Tenga en cuenta la diferencia en la redacción. Puede funcionar perfectamente en una PC, pero con el tema actual "VDI" también conocido como escritorios virtuales servidos a través de algún protocolo de comunicación remota (piense 2008 R2 SP1 - RemoteFX) la probabilidad aumenta constantemente de que las PC se conviertan pronto en servidores de terminal de 1 sesión. –

+0

Si la aplicación se ejecuta en Citrix XenApp, entonces WTSClientProtocolType volverá 1. Sin embargo, si la aplicación se ejecuta en Citrix XenDesktop, entonces WTSClientProtocolType devolverá 0. Todavía estoy buscando una manera de detectarlo que doesn Implica enumerar los dispositivos y buscar controladores virtuales conocidos. – DHW

2

Basado en la respuesta revisada de Helge Klein (arriba) Pensé en publicar el código de VBA para que esto suceda para ayudar a los futuros usuarios de VBA a acceder a esta página. Helge ya tiene el código C++ en su propio sitio. Si le resulta útil, por favor repita la respuesta de 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 

He probado esto en XenApp y XenDesktop.

Cuestiones relacionadas