API для определения, работает ли приложение в Citrix или службах терминалов

Я ищу API/ функцию, которую я могу вызвать, чтобы определить, работает ли программное обеспечение на Citrix, Terminal Services или на автономном ПК. Оптимально, это будет работать примерно так:

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

Я предпочел бы что-то, что работает от вызова API, а не смотреть что-то в реестре, поскольку у нас все больше и больше клиентов, которые блокируют реестр.

Благодарю.

4 ответа

Решение

В соответствии с: http://forums.citrix.com/message.jspa?messageID=1363711 вы можете проверить переменную среды SESSIONNAME.

Другой более простой способ - прочитать системную переменную среды "SESSIONNAME". Если он существует и начинается с "ICA", то вы работаете в сеансе Citrix. Если он начинается с "RDP", то вы работаете в рамках сеанса RDP.

Я проверил это на своем ПК и локально получаю:

C:\>echo %SESSIONNAME%
Console

В то время как я получил удаленно

C:\>echo %SESSIONNAME%
RDP-tcp1

Таким образом, кажется, что это может быть простой путь, в противном случае это звучит как проверка значений реестра или, если существуют определенные dll, будет следующей лучшей вещью.

Существует функция API, которая позволяет определить, отображается ли конкретный пользовательский сеанс на консоли (локально) или с помощью одного из протоколов удаленного взаимодействия Citrix ICA (в настоящее время называемых HDX) или Microsoft RDP.

Вызовите WTSQuerySessionInformation с третьим параметром, для которого установлено значение WTSClientProtocolType. Функция возвращает:

  • 0 для консольных сессий
  • 1 для сессий ICA
  • 2 для сеансов RDP

Интересно, что возвращаемое значение 1 не задокументировано как WTS_PROTOCOL_TYPE_ICA в MSDN (вторая ссылка выше) больше, но как "Это значение сохраняется для устаревших целей".

Обновить:

Сессии XenDesktop не могут быть обнаружены с WTSQuerySessionInformation (возвращает 0, что означает консоль). Если вы хотите универсальное решение:

  • Вызов WTSQuerySessionInformation, Если это возвращает 1 или 2 (ICA или RDP), все готово.
  • Если WTSQuerySessionInformation возвращает 0 (консоль), динамически загружается wfapi.dll и получить адрес WFGetActiveProtocol
  • Вызов WFGetActiveProtocol с параметром WF_CURRENT_SESSION, который определяется как ((DWORD)-1)
  • Возвращаемое значение WFGetActiveProtocol тип сеанса Должно быть 0 (консоль) или 1 (ICA)

Я подробно описал этот процесс, а также пример кода на C++ и работающий скомпилированный инструмент, который возвращает тип протокола удаленного взаимодействия текущего сеанса.

После ответа @ Джоша код будет выглядеть так:

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

Я еще не полностью проверил это, но похоже, что он будет делать то, что я хочу. ПК и терминальные серверы отчитываются правильно.

Если у кого-то есть способ проверить это на коробке Citrix, это будет высоко ценится!

Основываясь на пересмотренном ответе Хельге Кляйн (выше), я решил опубликовать код VBA, чтобы помочь будущим пользователям VBA попасть на эту страницу. Хельге уже имеет код C++ на своем собственном сайте. Если вы найдете это полезным, пожалуйста, ответьте Хельге Кляйн.

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.

Другие вопросы по тегам