В процессе интеграции 1С со сторонним программным обеспечением программисты часто сталкиваются с ситуацией, когда внешнее приложение (например, криптопровайдер или специализированный драйвер) открывает собственное диалоговое окно поверх 1С. Типичный пример — запрос пароля к контейнеру закрытого ключа ЭЦП. Поскольку 1С работает в рамках своего процесса, стандартных методов встроенного языка для управления «чужими» окнами не всегда достаточно. Рассмотрим подробно, как решить задачу поиска, активации и программного управления внешним окном.
Когда мы работаем через COM-объекты сторонних библиотек, управление передается коду этой библиотеки. Если в коде заложен вызов модального окна Windows, выполнение кода 1С «замирает» до тех пор, пока пользователь не произведет действия в этом окне. Для полной автоматизации нам необходимо:
Enter).AutoIt — это мощный бесплатный язык автоматизации Windows, который отлично подходит для решения подобных задач. Как мы видим из обсуждения, именно этот вариант стал финальным решением проблемы. Его можно использовать как самостоятельную утилиту или как COM-объект, зарегистрировав библиотеку AutoItX3.dll в системе.
Проанализируем пример использования AutoIt через COM-интерфейс в коде 1С. Это позволяет искать окна не только по их заголовку, но и по тексту внутри них, что делает поиск крайне надежным.
// Создаем объект AutoIt
Попытка
Автит = Новый COMОбъект("AutoItX3.Control");
Исключение
Сообщить("Библиотека AutoIt не зарегистрирована в системе!");
Возврат;
КонецПопытки;
// Ждем появления окна с заголовком "Ввод пароля" в течение 10 секунд
Таймаут = 10;
Если Автит.WinWait("Ввод пароля", "", Таймаут) Тогда
// Активируем окно
Автит.WinActivate("Ввод пароля");
// Пауза для корректной активации
Автит.Sleep(500);
// Вводим пароль (второй параметр 0 означает обычный режим отправки)
Автит.Send("МойСекретныйПароль123", 0);
// Нажимаем Enter
Автит.Send("{ENTER}", 0);
Иначе
Сообщить("Окно ввода пароля не появилось.");
КонецЕсли;
Разберем более легкий способ, который не требует установки стороннего ПО, так как компонент WScript.Shell присутствует в любой современной версии Windows. Метод AppActivate позволяет переключать фокус на приложение по части его заголовка.
Рассмотрим пошагово алгоритм активации окна через WSH:
Шелл = Новый COMОбъект("WScript.Shell");
// Пытаемся активировать окно. Метод возвращает Истина, если окно найдено.
ЗаголовокОкна = "КриптоПро CSP";
РезультатАктивации = Шелл.AppActivate(ЗаголовокОкна);
Если РезультатАктивации Тогда
// Если окно активно, отправляем клавиши
// ~ - это эквивалент клавиши Enter в синтаксисе SendKeys
Шелл.SendKeys("ПарольОтКлюча~");
Иначе
Сообщить("Не удалось найти окно с заголовком: " + ЗаголовокОкна);
КонецЕсли;
Выясним причину, почему вообще возникает необходимость в поиске окон. Часто это происходит из-за использования COM-интерфейсов, которые по умолчанию настроены на интерактивное взаимодействие. В случае с КриптоПро, как было предложено в обсуждении, гораздо эффективнее использовать утилиты командной строки, такие как cryptcp.
Работа через командную строку позволяет передать пароль в качестве аргумента запуска, что полностью исключает появление диалоговых окон. Проанализируем пример формирования команды:
// Пример формирования строки запуска внешней утилиты
ПутьКУтилите = "C:\Program Files\Crypto Pro\CSP\cryptcp.exe";
Команда = """" + ПутьКУтилите + """ -sign -pin 123456 ПутьКФайлу.txt";
// Запускаем через КомандаСистемы или ЗапуститьПриложение
ЗапуститьПриложение(Команда, , Истина);
Если вы используете современную библиотеку CAdESCOM для работы с ЭЦП, стоит проверить настройки самого объекта. Во многих методах подписи существует свойство KeyPassword. Если установить его программно в коде 1С перед вызовом метода подписи, криптопровайдер поймет, что пароль уже предоставлен, и не будет инициализировать графическое окно #32770 (стандартный класс диалоговых окон Windows).
При реализации управления внешними окнами необходимо учитывать следующие технические моменты:
SendKeys, AppActivate, AutoIt), будут работать только в клиентском сеансе. Если ваш код выполняется на сервере в фоновом задании, «рабочего стола» и графических окон просто не существует, и код выдаст ошибку или вернет False.Подводя итог, можно сказать, что использование AutoIt является наиболее гибким и стабильным решением для управления внешними окнами, так как этот инструмент специально спроектирован для взаимодействия с Windows API и корректно обрабатывает сложные случаи поиска объектов интерфейса.