Почему при автоматической выгрузке из 1С 8.3 периодически формируется некорректный DBF-файл и как это исправить?

Программист 1С v8.3 (Обычные формы) Торговля и дистрибуция
← На главную

При организации автоматического обмена данными между мобильными агентами и учетной системой 1С часто используется схема с промежуточной выгрузкой данных в формат DBF через внешнее COM-соединение (V83.COMConnector). В такой связке периодически возникает плавающая ошибка: часть выгруженных файлов оказывается с нарушенной структурой (меняются имена полей, типы колонок или их состав), хотя при ручном перезапуске процедуры файл формируется абсолютно корректно.

Разберем причины возникновения такого поведения платформы 1С:Предприятие 8.3 и рассмотрим надежные варианты решения проблемы.

Анализ причин сбоя структуры файлов DBF

Проанализируем технические факторы, которые приводят к возникновению «битых» файлов в автоматическом режиме:

  1. Кэширование модулей в процессах COM-соединений. При вызове процедур через V83.COMConnector операционная система и служба COM+ используют пул процессов (например, dllhost.exe). Байт-код скомпилированных модулей 1С сохраняется в оперативной памяти процесса. Если в конфигурацию вносились правки структуры DBF, активные COM-процессы могут продолжать исполнять старый код из памяти, формируя файл по устаревшему алгоритму.
  2. Последствия динамического обновления («обновления демоном»). Применение изменений в рабочей базе без монопольного обновления и перезапуска кластера серверов 1С приводит к рассинхронизации серверных кэшей метаданных. Различные рабочие процессы rphost и серверные контексты начинают выполнять разные версии одного и того же модуля.
  3. Состояние гонки (Race Condition) при параллельных сеансах. Если несколько агентов одновременно отправляют заявки, может запуститься несколько параллельных COM-сессий. Если в коде используется предварительная проверка существования файла по прямому пути, один процесс может создать и очистить файл, а второй процесс в этот же момент переписать его структуру или начать добавление записей.
  4. Особенности работы объекта XBase. Объект XBase выполняет запись напрямую на диск без механизмов транзакционности. При прерывании соединения или наложении блокировок заголовок DBF может остаться в поврежденном состоянии, а имена колонок длиннее 10 символов могут быть усечены платформой.

Шаг 1. Переход на атомарное создание файлов через временный каталог

Посмотрим на типовую ошибку: создание или очистка DBF-файла напрямую в целевой папке обмена. Чтобы полностью исключить повреждение структуры из-за конфликтов параллельного доступа и блокировок файловой системы, применим схему атомарного сохранения.

Сначала файл создается во временном каталоге с гарантированно уникальным именем, заполняется, закрывается объектом XBase, и только после этого перемещается в рабочую директорию одной операцией ПереместитьФайл().


Процедура ВыгрузитьЗаявкуВDBF(ПутьКПапкеОбмена, НомерДокумента, ДанныеТовары, Шапка) Экспорт

    // Получаем уникальное имя во временном каталоге
    ВременныйФайл = ПолучитьИмяВременногоФайла("dbf");
    
    ДБФ = Новый XBase;
    Если Константы.КодировкаДБФ.Получить() = Перечисления.КодировкиДБФ.ANSI Тогда
        ДБФ.Кодировка = КодировкаXBase.ANSI;
    Иначе
        ДБФ.Кодировка = КодировкаXBase.OEM;
    КонецЕсли;

    // Формируем жесткую структуру полей (имена не более 10 символов)
    ДБФ.Поля.Добавить("IDBUYER",  "S", 100);
    ДБФ.Поля.Добавить("IDFIRM",   "S", 100);
    ДБФ.Поля.Добавить("IDADDR",   "S", 200);
    ДБФ.Поля.Добавить("DELIVD",   "D");
    ДБФ.Поля.Добавить("DELIVS",   "S", 10);
    ДБФ.Поля.Добавить("DELIVPO",  "S", 10);
    ДБФ.Поля.Добавить("PRIM",     "S", 200);
    ДБФ.Поля.Добавить("IDGOODS",  "S", 100);
    ДБФ.Поля.Добавить("QUANT",    "N", 10, 2);
    ДБФ.Поля.Добавить("PRICE",    "N", 10, 2);
    ДБФ.Поля.Добавить("NOMZAK",   "S", 30);
    ДБФ.Поля.Добавить("DATEZAK",  "D");
    ДБФ.Поля.Добавить("SELLUNIT", "S", 100);
    ДБФ.Поля.Добавить("DELIVERY", "S", 1);
    ДБФ.Поля.Добавить("IDMEN",    "S", 100);
    ДБФ.Поля.Добавить("MTNOMKPK", "S", 100);

    ДБФ.СоздатьФайл(ВременныйФайл);

    // Заполнение строк таблицы
    Для Каждого Стр Из ДанныеТовары Цикл
        ДБФ.Добавить();
        ДБФ.IDBUYER  = Шапка.КлиентКод;
        ДБФ.IDFIRM   = Шапка.ФирмаКод;
        ДБФ.IDADDR   = Шапка.Адрес;
        ДБФ.DELIVD   = Шапка.ДатаДоставки;
        ДБФ.PRIM     = Шапка.Примечание;
        ДБФ.IDGOODS  = Стр.ТоварКод;
        ДБФ.QUANT    = Число(Стр.Количество);
        ДБФ.PRICE    = Число(Стр.Цена);
        ДБФ.NOMZAK   = НомерДокумента;
        ДБФ.DATEZAK  = ТекущаяДата();
        ДБФ.SELLUNIT = Стр.ЕдиницаКод;
        ДБФ.DELIVERY = ?(Шапка.Самовывоз, "1", "0");
        ДБФ.IDMEN    = Шапка.МенеджерКод;
        ДБФ.MTNOMKPK = Шапка.УникальныйИдентификатор;
        ДБФ.Записать();
    КонецЦикла;

    // Обязательно освобождаем файловый дескриптор
    ДБФ.ЗакрытьФайл();

    // Перемещение готового файла в целевую папку
    ИтоговыйКаталог = ПутьКПапкеОбмена + "zak\" + Шапка.МенеджерКод + "\";
    СоздатьКаталог(ИтоговыйКаталог);
    
    ЦелевойФайл = ИтоговыйКаталог + "Z" + НомерДокумента + ".dbf";
    
    // Если файл уже существует, удаляем его перед перемещением
    Если НайтиФайлы(ЦелевойФайл).Количество() > 0 Тогда
        УдалитьФайлы(ЦелевойФайл);
    КонецЕсли;

    ПереместитьФайл(ВременныйФайл, ЦелевойФайл);

КонецПроцедуры

Шаг 2. Очистка кэша и перезапуск служб

Для гарантированного устранения проблем со старыми версиями модулей выполним регламентные действия по очистке кэша платформы:

  1. Завершение процессов COM-коннектора: через диспетчер задач Windows или оснастку «Службы компонентов» (Component Services) завершим все экземпляры процессов dllhost.exe.
  2. Очистка кэша сервера 1С: остановим службу 1C:Enterprise 8.3 Server Agent (ragent) и очистим содержимое каталогов серверного кэша (каталоги вида snccntx* внутри директории srvinfo).
  3. Очистка пользовательского кэша: удалим содержимое папок %LOCALAPPDATA%\1C\1cv8 и %APPDATA%\1C\1cv8 для учетной записи, под которой запускаются фоновые задания и COM-сессии.
  4. Отказ от динамических обновлений: применим правило выполнять обновление рабочей базы исключительно через монопольный доступ с последующим перезапуском службы сервера 1С.

Шаг 3. Логирование параметров сеанса

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


Процедура ЗафиксироватьСобытиеОбмена(ИмяФайла, КоличествоКолонок)
    ТекстЛога = Новый ЗаписьТекста(
        "C:\Logs\exchange_dbf.log", 
        КодировкаТекста.UTF8, 
        Символы.ПС, 
        Истина
    );
    
    СтрокаЛога = Строка(ТекущаяДата()) + " | Пользователь: " + ИмяПользователя() 
        + " | Сеанс: " + НомерСеансаИнформационнойБазы() 
        + " | Файл: " + ИмяФайла 
        + " | Колонок: " + Строка(КоличествоКолонок);
        
    ТекстЛога.ЗаписатьСтроку(СтрокаЛога);
    ТекстЛога.Закрыть();
КонецПроцедуры

Такой аудит помогает быстро выявить, не обращается ли к каталогу обмена сторонний фоновый скрипт или забытая тестовая копия информационной базы.

← На главную