Переход на операционную систему Windows 10 часто преподносит неприятные сюрпризы разработчикам и администраторам систем, поддерживающим конфигурации на платформе 1С:Предприятие 7.7. Одной из наиболее острых и труднодиагностируемых проблем является внезапный вылет программы при попытке установить OLE-соединение (например, при подключении к базе 1С 8.х) в сессиях, где загружена популярная внешняя компонента FormEx. При этом сама форма, из которой инициируется OLE-соединение, может вообще не использовать функции раскраски или другие возможности расширения интерфейса.
В этой статье мы подробно разберем, почему возникает этот конфликт на уровне операционной системы, рассмотрим по шагам методы его устранения и проанализируем альтернативные варианты раскраски табличных частей и списков, которые помогут вернуть стабильность вашей системе.
Для начала проанализируем ситуацию изнутри. Компонента FormEx расширяет стандартный интерфейс платформы 1С 7.7 (включая раскраску таблиц, работу с деревом групп, перехват событий мыши и клавиатуры) за счет низкоуровневых механизмов Windows. К ним относятся так называемый сабклассинг (subclassing — перехват оконных сообщений) и установка глобальных системных хуков (hooks). Компонента фактически «встраивается» в процесс обработки графического интерфейса операционной системы.
Когда 1С 7.7 инициирует OLE/COM-соединение с другой базой (например, через объект V83.COMConnector или V83.Application), операционная система Windows 10 создает новые потоки выполнения внутри адресного пространства процесса 1С 7.7 и активирует собственные механизмы управления памятью и потоками. В Windows 10, по сравнению с Windows 7, политики безопасности и защиты памяти стали значительно строже.
В момент инициализации COM-объекта глобальные хуки FormEx пытаются перехватить сообщения, циркулирующие в новых системных потоках. Происходит конфликт адресации в защищенных сегментах памяти. Операционная система расценивает действия внешней компоненты как попытку несанкционированного доступа к памяти стороннего потока, генерирует ошибку типа Access Violation (или ошибку в модуле ntdll.dll) и принудительно аварийно завершает работу процесса 1cv7.exe или 1cv7s.exe.
Примечательно, что вылет происходит даже в том случае, если на текущей форме визуальные функции раскраски не применяются. Компонента загружена в память в начале сессии, и ее перехватчики активны по умолчанию.
Наиболее частым и эффективным системным решением этой проблемы является добавление исполняемых файлов платформы 1С в список исключений механизма DEP (Data Execution Prevention). Этот инструмент безопасности Windows блокирует запуск кода из сегментов памяти, помеченных как «только для данных», что часто происходит при работе низкоуровневых перехватчиков FormEx.
Выполним настройку DEP по шагам:
C:\Program Files (x86)\1Cv77\bin\1cv7.exe или 1cv7s.exe).1cv8.exe), если инициализируется полноценное OLE-приложение.После добавления исполняемых файлов 1С в исключения DEP, Windows 10 перестанет принудительно «убивать» процесс при попытках хуков FormEx обратиться к памяти COM-соединения.
Если по соображениям корпоративной безопасности отключить DEP в операционной системе невозможно, мы можем решить проблему программным путем внутри самой конфигурации 1С 7.7.
Рассмотрим вариант с временной выгрузкой компоненты на время работы OLE-сессии. Если обмен данными с «восьмеркой» происходит в рамках регламентной процедуры или по нажатию кнопки в специальной обработке, мы можем выгрузить FormEx перед подключением и загрузить обратно после его завершения. Разберем этот пример на коде:
// Создаем объект Сервис для управления компонентой
Попытка
Сервис = СоздатьОбъект("Сервис");
Исключение
// Компонента не загружена
КонецПопытки;
// Перед вызовом OLE выгружаем библиотеку
Если ПустоеЗначение(Сервис) = 0 Тогда
Сервис.ВыгрузитьВнешнююКомпоненту("formex.dll");
КонецЕсли;
// Выполняем подключение к 1С 8 через OLE
Попытка
V8Connector = СоздатьОбъект("V83.COMConnector");
// Выполняем необходимые операции обмена данными
// ...
Исключение
Предупреждение("Не удалось установить OLE-соединение: " + ОписаниеОшибки());
КонецПопытки;
// После завершения OLE-сессии загружаем компоненту обратно для работы интерфейса
ЗагрузитьВнешнююКомпоненту("formex.dll");
Также разработчики компоненты FormEx добавили специализированный метод, позволяющий снизить нагрузку на графическую систему и уменьшить вероятность конфликтов при работе с OLE. Мы можем использовать метод ОтключитьОбновлениеПриРаскраске(1). Посмотрим, как применить его при старте системы:
Процедура ПриНачалеРаботыСистемы()
ЗагрузитьВнешнююКомпоненту("formex.dll");
Попытка
Сервис = СоздатьОбъект("Сервис");
// Отключаем паразитные обновления интерфейса во время отрисовки таблиц
Сервис.ОтключитьОбновлениеПриРаскраске(1);
Исключение
Сообщить("Ошибка инициализации расширенных функций интерфейса!");
КонецПопытки;
КонецПроцедуры
Многие старые конфигурации используют устаревшие методы раскраски таблиц через вызов Сервис.ВключитьРаскраскуТаблиц(). Этот метод создает колоссальное количество вызовов графических функций Windows, что увеличивает риск падения. В актуальных версиях FormEx реализован гораздо более безопасный и быстрый механизм — Новый план раскраски. Он обрабатывается ядром компоненты более нативно и не конфликтует с внешними библиотеками.
Переведем раскраску на новый план по шагам:
Сервис = СоздатьОбъект("Сервис");
Сервис.ИспользоватьПланРаскраски(1);
FormEx_ПланРаскраски. Физически эту колонку можно сделать невидимой или сдвинуть в самый конец таблицы.
// Функция, вызываемая в строках таблицы значений
Функция ПолучитьЦветСтроки()
ЦветТекста = "000000"; // Черный
ЦветФона = "FFFFFF"; // Белый
Если СтатусДокумента = 1 Тогда
ЦветФона = "R200G255B200"; // Светло-зеленый для проведенных
ИначеЕсли СтатусДокумента = 2 Тогда
ЦветФона = "R255G200B200"; // Светло-красный для помеченных на удаление
КонецЕсли;
Возврат "(BRUSH[" + ЦветФона + "])(FONT[" + ЦветТекста + "])";
EndFunction
Этот способ позволяет избавиться от постоянного обновления свойств ячеек «на лету» силами операционной системы, так как отрисовка жестко привязана к содержимому служебной колонки таблицы, снижая вероятность системных сбоев.
В некоторых случаях нестабильность OLE в Windows 10 связана с обновленными версиями системных библиотек OLE-интерфейсов самой ОС. Существует проверенное практикой административное решение: поместить старые, стабильные версии системных DLL непосредственно в каталог исполняемых файлов 1С 7.7 (в папку Bin, где находится файл 1cv7.exe).
Вы можете попробовать скопировать из чистой и стабильной сборки Windows XP (или Windows 7) следующие библиотеки:
mfc42.dllole32.dlloleaut32.dllolepro32.dllПоместите эти файлы в каталог ..._путь_к_1С_\Bin\. При запуске платформа 1С 7.7 в первую очередь начнет использовать библиотеки локальной папки, а не системные файлы Windows 10, что в ряде конфигураций полностью устраняет проблемы совместимости при OLE-соединениях.
Если победить вылеты при совместной работе FormEx и OLE на конкретном сервере или клиентской машине не удается, имеет смысл рассмотреть надежную архитектурную альтернативу, которая не использует опасные механизмы перехвата сообщений Windows.
Лучшим решением в данном случае выступает использование компоненты 1С++ (1cpp.dll) и ее класса ТабличноеПоле.
1С++ — это мощный инструмент расширения возможностей 1С 7.7, который работает на уровне создания собственных элементов управления (ActiveX), а не дорисовывания существующих. Класс ТабличноеПоле полностью заменяет стандартную Таблицу Значений на форме диалога.
Рассмотрим преимущества использования ТабличногоПоля из 1С++:
Для реализации раскраски через 1С++ на форме создается пустой элемент «Текст» с определенным идентификатором, который при открытии формы программно заменяется на полноценное табличное поле, данные в которое поставляются через объект ПоставщикДанных.
Если вашей задачей является вывод раскрашенного отчета или интерактивной таблицы непосредственно на форму без использования внешних компонент перехвата, можно применить стандартный объект платформы 1С 7.7 — Табличный документ (Таблица):
Таб = СоздатьОбъект("Таблица");
// Заполнение ячеек...
Область = Таб.Область(Строка, Колонка);
Область.ЦветФона(128, 255, 128); // Установка цвета RGB напрямую
Область.ЦветТекста(0, 0, 0);
Такой подход гарантирует 100% стабильность на любых версиях операционных систем, так как задействует исключительно штатные, задокументированные механизмы платформы 1С.
Для расширения возможностей работы со штатной таблицей (например, для быстрой отрисовки тысяч строк, мгновенного экспорта в Excel и продвинутого управления отображением) рекомендуется использовать стабильную библиотеку Йоксель (SpreadSheet.dll). Она работает с табличными документами на уровне манипуляции форматами файлов и их рендеринга, абсолютно не вмешиваясь в сетевые или оконные потоки Windows 10, что полностью исключает падение системы при OLE-обмене.