При работе в устаревшей, но все еще популярной программной среде 1С:Предприятие 7.7 программисты и системные администраторы часто сталкиваются со специфическими сбоями операционной системы. Один из самых неприятных и трудноуловимых багов — это падение платформы 1cv7.exe с ошибкой APPCRASH в системной библиотеке ntdll.dll непосредственно в момент завершения сеанса работы пользователя.
Особенно критичной эта проблема становится в терминальной среде (Windows Server 2008 R2 и новее) или при запуске 1С во встроенных виртуальных машинах под управлением Windows 7 x64. Вместо корректного закрытия процесс 1С зависает в памяти «призраком», не давая выполнить монопольный запуск базы данных другим пользователям. Причиной такого поведения часто является некорректная выгрузка из адресного пространства внешних компонент, в частности — популярной библиотеки расширения интерфейса FormEx. Для принудительного освобождения базы перед монопольным входом можно использовать класс 1С++ для завершения работы пользователей.
В этой статье мы подробно разберем природу этого сбоя и рассмотрим несколько эффективных способов его устранения.
Прежде чем переходить к устранению проблемы, давайте выясним её техническую причину. Ошибка обращения к памяти (Access Violation, код исключения 0xc0000005) в модуле ntdll.dll происходит из-за того, что при закрытии главного окна программы операционная система пытается принудительно очистить оперативную память и выгрузить динамические библиотеки (DLL). Если внешняя компонента перехватывала системные события Windows (сабклассинг окон), но не успела корректно снять свои обработчики событий или освободить занятые дескрипторы до завершения работы основного процесса 1cv7.exe, операционная система завершает программу аварийно.
Давайте по шагам разберем проверенные способы решения этой проблемы.
Как показывает практика практикующих разработчиков, в большинстве случаев проблема кроется в использовании устаревших версий компоненты FormEx.dll (например, версий до 2.0.5.100). В старых релизах присутствовал внутренний баг, связанный с несвоевременным освобождением буфера внешних событий при уничтожении оконной процедуры 1С.
Для исправления ситуации выполним следующие действия:
ПриНачалеРаботыСистемы) с помощью специального метода:
Если ЗагрузитьВнешнююКомпоненту("FormEx.dll") = 1 Тогда
Сервис = СоздатьОбъект("Сервис");
Сообщить("Версия FormEx: " + Сервис.Версия(""));
КонецЕсли;
FormEx. Наиболее стабильными для операционных систем Windows 7 x64 и Windows Server 2008 R2 являются сборки **релиза 131** и **релиза 136**. Они содержат важные доработки механизмов очистки памяти при выгрузке DLL.FormEx.dll в каталоге базы данных (или каталоге исполняемых файлов 1С) на новый. Перед этим обязательно убедимся, что все пользователи вышли из базы данных, а зависшие процессы 1cv7.exe принудительно завершены через диспетчер задач.В реальных рабочих базах данных 1С 7.7 компонента FormEx.dll редко работает в одиночку. Обычно она используется совместно с мощным расширением 1CPP.dll. Неверный порядок их загрузки в память — гарантированный источник сбоев ntdll.dll и BkEnd.dll при закрытии программы.
Проанализируем правильную последовательность инициализации библиотек в глобальном модуле конфигурации. Нам необходимо придерживаться жесткого правила: **компонента FormEx должна загружаться строго ДО загрузки 1CPP**.
Рассмотрим правильный пример написания стартового кода:
Процедура ПриНачалеРаботыСистемы()
// 1. Сначала загружаем FormEx
Если ЗагрузитьВнешнююКомпоненту("FormEx.dll") = 0 Тогда
Предупреждение("Не удалось загрузить компоненту FormEx!");
СтатусВозврата(0);
Возврат;
КонецЕсли;
// 2. Только после этого загружаем 1CPP
Если ЗагрузитьВнешнююКомпоненту("1cpp.dll") = 0 Тогда
Предупреждение("Не удалось загрузить компоненту 1С++!");
СтатусВозврата(0);
Возврат;
КонецЕсли;
КонецПроцедуры
При таком порядке выгрузка библиотек операционной системой при закрытии приложения будет происходить в обратном порядке, что предотвратит конфликт перекрестных ссылок в памяти.
Иногда падение 1С при закрытии провоцируют сторонние утилиты, использующие глобальные хуки Windows. Классический пример — популярная программа удаленного доступа **TeamViewer**. Функция под названием **QuickConnect** пытается встроить собственную кнопку быстрого подключения в заголовки всех активных окон операционной системы.
При закрытии 1С 7.7 перехватчик оконных сообщений FormEx сталкивается с перехватчиком TeamViewer, что приводит к краху потока в ntdll.dll. Чтобы решить эту проблему без удаления TeamViewer, выполним настройку:
1cv7.exe в список исключений.Если в вашей конфигурации используется большой «зоопарк» внешних компонент (FormEx, 1CPP, DialMail, утилиты работы со сканерами штрихкодов и торговым оборудованием), стандартный метод платформы ЗагрузитьВнешнююКомпоненту() может не справляться с управлением их жизненным циклом.
Для решения этой проблемы системные администраторы используют специализированный инструмент — динамический загрузчик vkloader.dll. Он берет на себя функции корректного распределения памяти и принудительной пошаговой выгрузки всех библиотек при закрытии родительского процесса.
Схема подключения выглядит следующим образом:
vkloader.dll.Посмотрим на пример реализации такого механизма:
Если ЗагрузитьВнешнююКомпоненту("vkloader.dll") = 1 Тогда
Загрузчик = СоздатьОбъект("ЗагрузчикВнешнихКомпонент");
// Загружаем FormEx через обертку загрузчика
Загрузчик.ЗагрузитьВК("FormEx.dll");
// Загружаем остальные библиотеки
Загрузчик.ЗагрузитьВК("1cpp.dll");
КонецЕсли;
Использование vkloader позволяет практически полностью нивелировать системные ошибки выгрузки адресного пространства на серверах под управлением Windows Server 2008 R2 / 2012.
Современные версии Windows обладают повышенными механизмами безопасности работы с памятью. Система предотвращения выполнения данных (DEP) может блокировать корректную выгрузку старого кода 1С 7.7, считая его потенциально опасным.
Для устранения конфликтов на уровне ОС выполним настройки:
1cv7.exe (или 1cv7s.exe).ntdll.dll в более мягкий режим совместимости.Мы подробно проанализировали причины краха 1С 7.7 при использовании компоненты FormEx на современных операционных системах. Последовательное применение предложенных шагов — в первую очередь обновление самой библиотеки до актуальной стабильной сборки (релиз 136) и настройка параметров DEP — позволит вам навсегда избавиться от зависших процессов в терминальных сессиях и обеспечит стабильную работу пользователей. Для оперативного сброса зависших сессий на сервере терминалов можно применить утилиту для самостоятельного завершения терминальных сеансов.