2010-11-15 9 views
8

Sto cercando una funzione/API che posso chiamare per determinare se il software è in esecuzione su Citrix, Servizi terminal o un PC stand-alone. In modo ottimale, che avrebbe funzionato o meno così:API per determinare se l'app è in esecuzione su Citrix o Servizi terminal

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

Io preferirei qualcosa che ha funzionato da una chiamata API in contrapposizione a guardare qualcosa nel Registro di sistema, come stiamo avendo più i clienti che stanno bloccando il registro .

Grazie.

+2

Ho trovato questo ... SystemInformation.TerminalServerSession che restituisce il valore booleano, in modo che risponda alla domanda TS. Non sono sicuro che restituisca bool per Citrix. Ancora indagando –

+0

L'ho trovato vero per Citrix e Windows 2008 Server TS ThinApp. –

risposta

6

Secondo: http://forums.citrix.com/message.jspa?messageID=1363711 è possibile controllare la variabile d'ambiente NOMESESSIONE.

Un altro modo più semplice è leggere la variabile di ambiente di sistema "SESSIONNAME". Se esiste e inizia con "ICA", allora stai eseguendo una sessione Citrix. Se inizia con "RDP", allora stai correndo all'interno di una sessione RDP.

ho provato con il mio PC e localmente ottengo:

C:\>echo %SESSIONNAME% 
Console 

Mentre remoto ho ricevuto

C:\>echo %SESSIONNAME% 
RDP-tcp1 

Così sembra che potrebbe essere un percorso facile per andare, altrimenti suona come il controllo per i valori di Registro di sistema o in presenza di determinate DLL sarà la prossima cosa migliore.

3

seguito @ risposta di Josh, il codice sarebbe simile a questa:

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

non l'ho completamente testato fuori ancora, ma sembra che sarà fare quello che voglio. Report di PC e Terminal Server correttamente.

Se qualcuno ha un modo per testarlo su un box Citrix, sarebbe molto apprezzato!

+0

Funziona per me. Sul mio server citrix '? Environ (" SessionName ")' restituisce 'ICA-tcp # 56'. – mischab1

+3

Si noti che nella modalità RemoteApp di Windows 2008 questa vv.variabile è assente – user545829

11

C'è una funzione API che consente di determinare se una sessione utente specifica viene visualizzata sulla console (localmente) o tramite uno i protocolli remoti Citrix ICA (oggi chiamato HDX) o Microsoft RDP.

Chiama il WTSQuerySessionInformation con il 3 ° parametro impostato su WTSClientProtocolType. La funzione restituisce:

  • 0 per le sessioni di console
  • 1 per sessioni ICA
  • 2 per le sessioni RDP

È interessante notare che il valore di ritorno di 1 non è documentato come WTS_PROTOCOL_TYPE_ICA su MSDN (secondo link sopra) altro ancora, ma come "Questo valore viene mantenuto per scopi legacy".

Aggiornamento:

XenDesktop sessioni non possono essere rilevati con WTSQuerySessionInformation (restituisce 0, il che significa Console).Se si desidera una soluzione universale:

  • Chiama WTSQuerySessionInformation. Se restituisce 1 o 2 (ICA o RDP), hai finito.
  • Se WTSQuerySessionInformation restituisce 0 (Console), caricare dinamicamente wfapi.dll e ottenere l'indirizzo di WFGetActiveProtocol
  • chiamata WFGetActiveProtocol con un parametro di WF_CURRENT_SESSION, che è definita come ((DWORD) -1)
  • Il valore restituito WFGetActiveProtocol è il tipo di sessione. Dovrebbe essere 0 (Console) o 1 (ICA)

ho descritto il processo in dettaglio here oltre ad esempio di codice C++ e uno strumento di lavoro compilato che restituisce tipo di protocollo comunicazione remota della sessione corrente.

+0

Pensate che sarebbe sicuro assumere se quella funzione restituisce QUALSIASI numero maggiore di 0, l'app non è in esecuzione su un PC? vale a dire. Deve essere in esecuzione su qualche tipo di server. Sto pensando come 5 anni nel futuro ... in entrambi i casi un non-zero dovrebbe sempre indicare qualcosa di diverso da un PC, giusto? –

+0

Sì, penso che sarebbe giusto presumere che qualsiasi cosa> 0 sia ... NON LOCALE. Si prega di notare la differenza nella formulazione. Può funzionare molto bene su un PC, ma con il tema "VDI" di oggi, ovvero i desktop virtuali serviti su alcuni protocolli remoti (si pensi a R2 SP1 2008 - RemoteFX), aumenta la probabilità che i PC diventino presto server terminal 1 sessione. –

+0

Se l'applicazione è in esecuzione in Citrix XenApp, quindi WTSClientProtocolType tornerà 1. Se, tuttavia, l'applicazione è in esecuzione con Citrix XenDesktop, quindi WTSClientProtocolType restituirà 0. Sto ancora cercando un modo per rilevare in modo che doesn comportare l'enumerazione dei dispositivi e la ricerca di driver virtuali noti. – DHW

2

Sulla base della risposta modificata di Helge Klein (sopra) ho pensato di pubblicare il codice VBA per rendere questo possibile aiutare i futuri utenti VBA a colpire questa pagina. Helge ha già il codice C++ sul proprio sito. Se lo trovi utile, per favore rispondi alla risposta di 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 

L'ho provato su XenApp e XenDesktop.