Как предотвратить завершение бездействующего терминального сеанса (RDP) из 1С

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При настройке автоматических действий в 1С (например, запуск обработок по расписанию через планировщик в терминальной сессии) часто возникает проблема: ограничение бездействующих сеансов на сервере. Даже если 1С активно выполняет вычисления, формирует отчеты или обменивается данными с SQL-сервером, операционная система Windows может посчитать сеанс бездействующим и принудительно его завершить через установленное время (например, через 1 час). Рассмотрим, почему это происходит и как мы можем «обмануть» счетчик бездействия, используя возможности 1С и системные инструменты.

Почему стандартные методы не помогают

Для начала проанализируем ситуацию: почему обычный вызов SendKeys или программное движение мыши часто игнорируются сервером? Дело в том, что в современных версиях Windows Server счетчик Idle Time привязан не к нагрузке на процессор или активности диска, а к поступлению данных через входной канал RDP-клиента. Когда событие (нажатие клавиши или движение мыши) генерируется внутри самого сеанса программно, оно помечается специальным флагом LLMHF_INJECTED. Служба терминалов видит, что это не «физическое» действие пользователя, пришедшее от клиента, а программная эмуляция на стороне сервера, и игнорирует его при расчете времени простоя.

Особенно остро эта проблема стоит в режиме RemoteApp. Поскольку полноценный рабочий стол отсутствует, Windows оптимизирует ресурсы еще жестче, и «усыпить» или закрыть такой сеанс системе проще.

Способ 1: Использование PowerShell и системных клавиш

Разберем один из самых простых, но часто действенных способов — запуск фонового скрипта PowerShell, который будет имитировать нажатие клавиши, вызывающей ответную реакцию драйвера (например, SCROLLLOCK). Хотя прямой вызов из 1С может блокироваться, запуск внешнего процесса в том же интерактивном контексте иногда позволяет «пробить» защиту сервера.

Мы можем реализовать это через команду системы. Рассмотрим пример кода, который создает временный скрипт и запускает его:


// Пример для 1С 7.7 или 8.x через КомандаСистемы
ТекстСкрипта = "
$w = New-Object -ComObject WScript.Shell
while($true) {
  $w.SendKeys('{SCROLLLOCK}')
  Start-Sleep -Seconds 60
}";
// Сохраняем текст в файл .ps1 и запускаем:
КомандаСистемы("powershell -WindowStyle Hidden -Command " + ТекстСкрипта);

В данном случае мы используем Scroll Lock, так как это наименее «вредная» клавиша, которая не мешает работе алгоритмов 1С, но при этом вызывает изменение состояния клавиатуры, что фиксируется системой.

Способ 2: Использование утилиты AutoIt

Как отмечалось в обсуждении, AutoIt3 — это мощный инструмент для автоматизации, который работает с системными событиями на более низком уровне, чем стандартный WScript.Shell. Мы можем скомпилировать небольшой .exe файл, который будет периодически «шевелить» курсор мыши на 1 пиксель или нажимать невидимую клавишу.

Рассмотрим алгоритм работы с таким помощником:

  1. Создаем скрипт AutoIt, который раз в 10 минут меняет координаты мыши: MouseMove(MouseGetPos(0) + 1, MouseGetPos(1) + 1), а затем возвращает их обратно.
  2. Компилируем его в исполняемый файл.
  3. В 1С при начале работы системы запускаем этот файл через ЗапуститьПриложение().

Преимущество AutoIt в том, что его события часто воспринимаются системой как более «легитимные», чем впрыск через COM-объекты.

Способ 3: Трюк с мультимедийным потоком

Проанализируем интересную особенность RDP: сеанс считается активным, если через виртуальные каналы передается мультимедийный поток. Это сделано для того, чтобы пользователи могли смотреть видео, не боясь отключения сессии. Мы можем использовать это в своих целях.

Попробуем запустить в скрытом режиме проигрывание зацикленного «пустого» видеофайла или аудиофайла без звука. Для этого можно использовать стандартный Windows Media Player или VLC, запущенный с параметрами командной строки. Постоянное обновление картинки (даже если окно скрыто или имеет размер 1x1 пиксель) заставляет протокол RDP постоянно передавать данные, что сбрасывает счетчик бездействия на сервере.

Способ 4: Использование WinAPI SetThreadExecutionState

Для продвинутых разработчиков существует возможность вызвать функцию Windows API SetThreadExecutionState. Эта функция сообщает системе, что текущее приложение выполняет важную работу и компьютер (или сессия) не должны переходить в спящий режим или режим ожидания.

Выясним, какие флаги нам понадобятся:

Вызвать эту функцию из 1С 7.7 напрямую сложно, но мы можем использовать PowerShell или внешнюю компоненту для выполнения этого вызова в контексте текущего процесса 1С.

Способ 5: Перевод сессии в консольный режим (tscon)

Если задача выполняется «роботом» и нам не важно визуальное отображение в данный момент, мы можем программно переключить текущую RDP-сессию в консольный режим. Выполним команду tscon. Это «отцепит» сессию от протокола RDP и привяжет её к локальной консоли сервера.

Разберем по шагам:

  1. Определяем ID текущей сессии с помощью команды query session.
  2. Выполняем команду: tscon [ID_СЕССИИ] /dest:console.

В консольном режиме ограничения терминального простоя не действуют, так как Windows считает, что пользователь работает физически за монитором сервера. 1С продолжит выполнение кода без риска быть закрытой по таймеру.

Рекомендации для RemoteApp

Если вы работаете в режиме RemoteApp, обратите внимание на фокус окна. Рекомендуется периодически вызывать метод Активизировать() для основной формы или открывать/закрывать небольшое модальное окно с таймером. Это провоцирует перерисовку интерфейса и передачу графических пакетов по сети, что также может помочь удержать соединение активным.

Важное замечание: Любые манипуляции с обходом политик безопасности должны быть согласованы с системным администратором. Однако, если техническая необходимость диктует свои условия, вышеописанные методы (особенно использование tscon или мультимедийного трафика) являются наиболее надежными способами обеспечить непрерывную работу 1С в терминальной среде.

← На главную