При разработке в среде 1С:Предприятие часто возникает необходимость взаимодействия с операционной системой: запуск пакетных файлов (BAT), скриптов или сторонних утилит. Однако стандартные методы, такие как ЗапуститьПриложение() или КомандаСистемы(), особенно при установленном флаге ожидания завершения, часто приводят к неприятному побочному эффекту — после закрытия внешнего окна фокус ввода не возвращается в 1С автоматически. Вместо этого активным становится другое открытое приложение (например, браузер или проводник), что мешает комфортной работе пользователя.
В этой статье мы подробно разберем, почему это происходит, и изучим несколько эффективных способов программного возврата фокуса в основное окно 1С.
Когда 1С вызывает ЗапуститьПриложение с параметром Истина (ожидание завершения), основной поток программы приостанавливается. Операционная система Windows передает управление новому процессу (например, cmd.exe). После закрытия консольного окна Windows должна решить, какому приложению передать фокус. Из-за особенностей обработки очереди сообщений в 1С и механизмов Windows (Foreground Lock), система не всегда считает 1С приоритетным кандидатом на получение фокуса. Проанализируем способы обхода этого поведения.
Один из самых простых и эффективных способов избежать потери фокуса — запустить внешнее приложение так, чтобы его окно вообще не появлялось на переднем плане. Если окно консоли не создается как активное, фокус с высокой вероятностью останется у 1С. Для этого мы будем использовать COM-объект WScript.Shell.
Рассмотрим пример кода для обычного приложения:
// Создаем объект для работы с системной оболочкой
Шелл = Новый COMОбъект("WScript.Shell");
// Формируем путь к файлу
ПутьКФайлу = "C:\Scripts\my_script.bat";
// Параметры метода Run:
// 1. Командная строка
// 2. Стиль окна: 0 - скрытое окно, 1 - обычное
// 3. Ожидать завершения: Истина
Шелл.Run(ПутьКФайлу, 0, Истина);
// После выполнения фокус должен остаться в 1С
Использование параметра 0 позволяет выполнить скрипт полностью в фоновом режиме. Это исключает "прыжок" фокуса на консоль и обратно.
Если скрыть окно невозможно (например, пользователю нужно видеть процесс выполнения), мы можем принудительно вернуть фокус в 1С сразу после завершения внешней программы, используя метод AppActivate того же объекта WScript.Shell.
Разберем, как это реализовать по шагам:
Шелл = Новый COMОбъект("WScript.Shell");
// Запускаем приложение в обычном режиме (стиль окна 1)
Шелл.Run("C:\Scripts\process_data.bat", 1, Истина);
// Пытаемся вернуть фокус, используя заголовок окна 1С.
// В параметре нужно указать начало строки заголовка вашего окна 1С.
ЗаголовокОкна = "1С:Предприятие";
Шелл.AppActivate(ЗаголовокОкна);
Важно помнить, что AppActivate ищет окно, заголовок которого начинается с указанной строки. Если у вас открыто несколько сеансов 1С, метод может переключиться на другой сеанс. Чтобы этого избежать, можно использовать уникальный заголовок, установив его через УстановитьЗаголовокСистемы().
Для наиболее надежного управления окнами в Windows используются функции из библиотеки user32.dll. Метод SetForegroundWindow позволяет принудительно вывести окно на передний план. В 1С 8.3 (особенно в обычном приложении) это можно реализовать через внешние компоненты или дополнительные библиотеки, поддерживающие вызов функций по указателю (например, dynwrapx.dll).
Проанализируем логику работы через WinAPI:
SetForegroundWindow(HWND).ShowWindow(HWND, 9) (где 9 — это константа SW_RESTORE), чтобы гарантированно развернуть окно.Хотя этот метод требует наличия внешней компоненты, он является "золотым стандартом" в системном программировании Windows, так как работает в обход многих ограничений высокоуровневых скриптов.
Иногда проблему можно решить, изменив логику самого запускаемого файла. Если вы используете внутри батника другие команды, попробуйте запускать их с ключом /b. Посмотрим на пример содержимого .bat файла:
@echo off
start /b "" "C:\Program Files\SomeApp\util.exe" -param
exit
Ключ /b позволяет запустить приложение без создания нового окна консоли. В сочетании с командой exit это минимизирует время удержания фокуса операционной системой за пределами 1С.
В некоторых случаях в обычном приложении срабатывает "обходной маневр". Если после выполнения внешней команды вызвать любое модальное действие, платформа заставляет Windows пересмотреть активное окно. Выясним, как это выглядит на практике:
ЗапуститьПриложение("my.bat", , Истина);
// Вызываем пустое предупреждение с таймаутом в 1 секунду
ПоказатьПредупреждение(, "Возврат управления...", 1);
Хотя этот метод может вызвать кратковременное мерцание, он заставляет графическую подсистему 1С запросить фокус у ОС заново. Однако мы рекомендуем использовать этот способ только в крайнем случае, отдавая предпочтение WScript.Shell.
Мы рассмотрели основные причины и способы решения проблемы потери фокуса. Подведем итог: наиболее корректным и современным способом является использование COM-объекта WScript.Shell с параметром скрытого окна (0). Если же интерактивность необходима, используйте метод AppActivate. Эти инструменты позволяют сделать работу пользователя в 1С бесшовной и профессиональной.