Действующие лица

web.sta – web-приложение, целевой браузер Inter­net Explo­rer версии 9 и 11
Text­Sys­tem – stan­da­lo­ne приложение, написанное на Java/Swing
Inter­me­dia­teLay­er – Cli­ent-Ser­ver приложение, которое представляет собой связующее звено между web.sta и TextSystem. 

web.sta может вызвать Text­Sys­tem через Inter­me­dia­teLay­er. Для этого Inter­me­dia­teLay­er создаёт http ser­ver и web-приложение web.sta отправляет GET или POST запросы на local­host. Там Inter­me­dia­teLay­er обрабатывает параметры запроса и стартует Text­Sys­tem. Обратной связи не требуется, поэтому схема взаимодействия проста и достаточно надёжна.

Citrix

В окружении Citrix мы не можем создать несколько слушающих сокетов на одном IP адресе и порте. Тут или надо менять порт, или же менять IP адрес. Но Citrix предоставляет специальный механизм для обхода этого ограничения, без изменения алгоритма работы программы. Этот механизм называется “Vir­tu­al IP Loo­p­back”. Администратору достаточно указать необходимые приложения в панели конфигурирования Citrix и приложение, которое использует local­host для сокетных соединений, будет получать не 127.0.0.1, а IP адрес вида 127.0.0.<SID+1>, где SID это идентификатор сессии пользователя Windows.

Проблема

Всё это прекрасно работало под IE9 (да и с другими браузерами тоже) на WindowsServer2008 R2. А потом клиентам захотелось чего-то нового и появился WindowsServer2012 R2 c IE11. И вся система перестала работать. Независимо от настроек Citrix IE11 всегда, при указании local­host, пытается установить соединение на 127.0.0.1, а там никто не слушает. После небольшого исследования мы пришли к выводу, что это баг именно в IE11.

Rou­tingSer­vice

Если виртуализация для local­host не работает из коробки Citrix для IE11, то давайте напишем её сами! Для этих целей мы решили написать win­dows ser­vice, который будет простейшим web сервером, слушать на 127.0.0.1 и перенаправлять запросы на нужные инстансы Inter­me­dia­teLay­er, основываясь на номере сессии пользователя. Простого решения получить SID мы не нашли, но в переменных окружения мы сразу обнаружили SES­SI­ONNA­ME. В IE через ActiveX мы получаем переменную окружения, передаем её в качестве параметра в http запрос, в Rou­tingSer­vice по имени сессии мы через wtsapi32.lib получаем номер сессии. А затем перенаправляем http запрос и соответственно возвращаем ответ.

Что-то пошло не так

Начали тестировать и внедрять наш сервис. Но не всё оказалось так радужно, как хотелось бы. Как оказалось имя сессии может меняться, правда мы так и не поняли в каких условиях это происходит, а разбираться ещё и с этим, как всегда не хватало времени. Но часто случалось, что имя сессии изменилось, а IE11 знает только первоначальное значение переменной окружения. И упорно передаёт это значение на RoutingService. 

А что там в реестре?

Надо найти другой способ получать ses­si­onna­me. Поискали информацию о сессиях в реестре и вот что нашли: в HKEY_CURRENT_USER\Volatile Envi­ron­ment можно получить список сессий текущего пользователя.

Если сессия пользователя одна – то вообще всё прекрасно, прочитали и используем. А если сессий одного пользователя много, то надо как-то определить, в какой же мы сессии находимся. Ничего лучше, чем сопоставить путь к папке временных файлов, мы не придумали.

Вот пример:

В IE получаем текущий путь к TEMP, используя ActiveX Scripting.FileSystemObject. Таким образом нам удалось получить имя нашей сессии. Но это не всё. Значения ключей под Vola­ti­le Envi­ron­ment – это, собственно, SID и есть. То есть мы можем сразу в Java­Script получить необходимый IP адрес и оправить запрос на него.

Будем упрощать? 

В итоге мы можем получить SID и устанавливать соединение напрямую, без использования Rou­tingSer­vice. Но решение всё равно не выглядит красивым. Изучение интернета показало, что проблема есть, но решение этой проблемы нигде не описывается. А сам Micro­soft молчит. 

Так что, возможно, кому-то наш опыт будет полезен в решении этой специфичной проблемы.