API per determinare se l’app è in esecuzione su Citrix o Servizi terminal

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, funzionerebbe qualcosa del genere:

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

Preferirei qualcosa che funzionasse da una chiamata API piuttosto che guardare qualcosa nel registro poiché stiamo avendo sempre più clienti che stanno bloccando il registro.

Grazie.

Secondo: http://forums.citrix.com/message.jspa?messageID=1363711 puoi controllare la variabile di ambiente SESSIONNAME.

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.

L’ho provato con il mio PC e localmente ottengo:

 C:\>echo %SESSIONNAME% Console 

Mentre remotamente ho ottenuto

 C:\>echo %SESSIONNAME% RDP-tcp1 

Quindi sembra che potrebbe essere una strada facile da percorrere, altrimenti sembra che controllare i valori del registro o se esistano alcune DLL saranno la cosa migliore.

Esiste una funzione API che consente di determinare se una sessione utente specifica viene visualizzata sulla console (in locale) o tramite uno i protocolli remoti Citrix ICA (oggi denominato HDX) o Microsoft RDP.

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

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

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

Aggiornare:

Le sessioni XenDesktop non possono essere rilevate con WTSQuerySessionInformation (restituisce 0, ovvero Console). Se vuoi una soluzione universale:

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

Ho descritto il processo in dettaglio qui insieme a un esempio di codice C ++ e uno strumento compilato funzionante che restituisce il tipo di protocollo remoto della sessione corrente.

Seguendo la risposta di @ Josh, il codice sarebbe simile a questo:

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

Non ho ancora completamente testato, ma sembra che farà quello che voglio. Report di PC e Terminal Server correttamente.

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

Sulla base della risposta modificata di Helge Klein (sopra) ho pensato di pubblicare il codice VBA per fare in modo che ciò accada per aiutare i futuri utenti di 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 

Ho provato questo su XenApp e XenDesktop.