Стоит ли писать в техподдержку 1С при обнаружении ошибок в БСП и как исправить баги в подсистеме «Работа с файлами» самостоятельно?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При внедрении или обновлении Библиотеки стандартных подсистем (БСП) разработчики часто сталкиваются с неожиданным поведением стандартных механизмов. Особенно богата на сюрпризы подсистема «Работа с файлами». При попытке добавить реквизит типа «Присоединенный файл» на форму может возникнуть каскад ошибок: от некорректного динамического создания элементов формы до аварийного завершения сеанса из-за неверного индексирования.

В этой статье мы подробно разберем практические примеры критических багов в БСП, найдем причины их возникновения, рассмотрим готовые программные исправления и выясним, как эффективнее всего взаимодействовать с техподдержкой «1С» по вопросам ошибок в программном коде.

Стоит ли писать в техподдержку (ТП) «1С» по поводу багов в коде БСП?

Прежде чем переходить к разбору кода, ответим на организационный вопрос: есть ли смысл тратить время на составление баг-репортов? Опыт практикующих 1С-разработчиков указывает на следующие особенности работы каналов поддержки:

  1. Обычная техподдержка (v8@1c.ru): Малоэффективна для отправки чистого кода. Специалисты первой линии поддержки ориентированы на конечных пользователей. От вас потребуют «пошаговый сценарий воспроизведения» на демонстрационной базе. Если вы просто пришлете ошибочную строку кода и готовое исправление, ТП может ответить стандартным шаблоном: «Не удалось воспроизвести ошибку, опишите шаги...». Это связано с тем, что ошибки часто проявляются только в специфических кастомных конфигурациях при динамическом создании элементов.
  2. Партнерский форум 1С (partners.v8.1c.ru): Это наиболее эффективный канал. В специализированных ветках по разработке БСП присутствуют непосредственно авторы библиотеки. Они отлично понимают язык кода, быстро фиксируют баги и вносят их в бэклог. Для публикации там достаточно предоставить кусок кода с ошибкой и предложить готовый вариант исправления.
  3. Реальность исправления: Даже если баг официально зарегистрируют на Bugboard, исправление может выйти только через несколько месяцев (в одном из следующих релизов БСП). Поэтому лучшая стратегия для разработчика — исправить ошибку самостоятельно «здесь и сейчас», используя механизм расширений, а параллельно отправить баг-репорт на партнерский форум.

Давайте подробно проанализируем и исправим наиболее критичные ошибки подсистемы работы с файлами.

Ошибка №1: Неверное обращение по строковому индексу в области предпросмотра

Рассмотрим ситуацию, когда при обновлении области предпросмотра присоединенного файла система аварийно завершает работу. Выясним причину проблемы. В процедуре обновления реквизита хранения разработчики БСП предусмотрели приведение типов, однако в сопутствующей процедуре этого сделано не было.

Посмотрим на исходный код процедуры ОбновитьРеквизитХраненияПрисоединенногоФайла:


Процедура ОбновитьРеквизитХраненияПрисоединенногоФайла(Форма, Знач НомерЭлемента, Файл)
    
    Если ТипЗнч(НомерЭлемента) = Тип("Строка") Тогда 
        НомерЭлемента = Число(НомерЭлемента); // Здесь тип успешно преобразован в Число
    КонецЕсли;
    
    ПутьКДанным = Форма.ПараметрыРаботыСФайлами[НомерЭлемента].ПутьКРеквизитуРазмещения;
    ЧастиПутиКДанным = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(ПутьКДанным, ".", Истина, Истина);
    
    Если ЧастиПутиКДанным.Количество() > 0 Тогда
        
        УровеньРасположенияРеквизита = ЧастиПутиКДанным.Количество();
        Если УровеньРасположенияРеквизита = 1 Тогда
            Форма[ЧастиПутиКДанным[0]] = Файл;
        ИначеЕсли УровеньРасположенияРеквизита = 2 Тогда
            Форма[ЧастиПутиКДанным[0]][ЧастиПутиКДанным[1]] = Файл;
        Иначе
            Возврат;
        КонецЕсли;
        
        // Передача переменной НомерЭлемента в следующую процедуру
        ОбновитьОбластьПредпросмотра(Форма, НомерЭлемента, Файл);
        
        Форма.Модифицированность = Истина;
        
    КонецЕсли;
    
КонецПроцедуры

Казалось бы, переменная НомерЭлемента уже преобразована к числу. Однако при определенных сценариях вызова смежных процедур или при обновлении формы напрямую в процедуру ОбновитьОбластьПредпросмотра может передаваться строковое значение индекса. Разработчики БСП забыли добавить валидацию типа во второй процедуре:


Процедура ОбновитьОбластьПредпросмотра(Форма, НомерЭлемента, Файл)
    
    // ОШИБКА: Если НомерЭлемента придет как Строка, обращение к соответствию вызовет падение
    // ИмяРеквизита = Форма.ПараметрыРаботыСФайлами[НомерЭлемента].ПутьКДаннымИзображения;
    
    // ИСПРАВЛЕНИЕ: Принудительно преобразуем индекс в Число
    ИмяРеквизита = Форма.ПараметрыРаботыСФайлами[Число(НомерЭлемента)].ПутьКДаннымИзображения;
    
    ЭлементКартинки = Форма.Элементы.Найти("ПолеКартинкиПрисоединенногоФайла" + НомерЭлемента);
    ЭлементЗаголовка = Форма.Элементы.Найти("ЗаголовокПрисоединенногоФайла" + НомерЭлемента);
    
    // Продолжение алгоритма отрисовки...
КонецПроцедуры

Решение: Принудительное приведение индекса коллекции к числу с помощью функции Число() непосредственно перед обращением к параметрам работы с файлами гарантирует стабильность интерфейса.

Ошибка №2: Критический баг ограничения «Только один файл»

Проанализируем крайне неприятную логическую ошибку, из-за которой алгоритм проверки количества файлов ведет себя некорректно. Система должна контролировать ограничение на добавление файлов, если взведен флаг ТолькоОдинФайл.

Взглянем на исходный код БСП, проверяющий возможность загрузки нового файла:


ИначеЕсли СтрНачинаетсяС(ИмяКоманды, "ЗагрузитьФайл") Тогда
        
    ИмяКоманды = СтрЗаменить(ИмяКоманды, "ЗагрузитьФайл", "");
    ФайлыВладельца = РаботаСФайламиСлужебныйВызовСервера.КоличествоПрисоединенныхФайлов(ВладелецПрисоединенныхФайлов, Истина);
    
    Если СтрНачинаетсяС(ИмяКоманды, "ТолькоОдинФайл")
        // ОШИБКА: Как это вообще должно работать?
        И ФайлыВладельца.Количество > 0 Тогда 

Выясним, в чем кроется подвох. Функция КоличествоПрисоединенныхФайлов возвращает не число, а объект типа Структура со следующими свойствами:

В платформе «1С:Предприятие» у любого объекта типа Структура есть системное свойство Количество() (или свойство Количество в некоторых контекстах), которое возвращает количество элементов (ключей) в самой структуре. Поскольку структура возвращает 2 ключа, выражение ФайлыВладельца.Количество всегда возвращает число 2!

В результате условие 2 > 0 всегда возвращает Истина. Алгоритм считает, что файлы у владельца есть всегда, даже когда присоединенных файлов на самом деле нет! Это полностью ломает логику добавления единственного файла.

Решение: Заменим обращение к свойству коллекции на обращение к конкретному ключу структуры:


Если СтрНачинаетсяС(ИмяКоманды, "ТолькоОдинФайл")
    // ИСПРАВЛЕНИЕ: Обращаемся к правильному свойству структуры, содержащему реальное число файлов
    И ФайлыВладельца.КоличествоФайлов > 0 Тогда

Ошибка №3: Нарушение правил генерации имен динамических команд

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

При добавлении команды загрузки файла в коде БСП была написана следующая строка:


// ОШИБКА: Неверно составлено имя команды
// ЗагрузитьФайл = Форма.Команды.Добавить("УправлениеПрисоединеннымиФайламиЗагрузитьФайл_" + ТолькоОдинФайлТекст + НомерЭлемента);

// ИСПРАВЛЕНИЕ: Символ подчеркивания должен разделять логические части имени команды
ЗагрузитьФайл = Форма.Команны.Добавить("УправлениеПрисоединеннымиФайламиЗагрузитьФайл" + ТолькоОдинФайлТекст + "_" + НомерЭлемента);

Из-за того, что символ подчеркивания "_" стоял не на своем месте, последующие процедуры парсинга имени команды (которые ожидают строго определенный формат имени кнопки при обработке нажатия) не могли корректно определить, к какому именно элементу формы относится данное событие.

Ошибка №4: Проблемы отображения кнопок контекстного меню

При программном выводе элементов управления файлами на форму разработчики БСП некорректно закомментировали или продублировали участки кода, отвечающие за генерацию команд контекстного меню для сканирования и создания файлов по шаблону.

Рассмотрим, как должен выглядеть исправленный участок кода создания команд:


Если Не ДобавляемыйЭлемент.ТолькоОдинФайл Тогда
            
    СоздатьПоШаблону = Форма.Команды.Добавить("УправлениеПрисоединеннымиФайламиСоздатьПоШаблону_" + НомерЭлемента);
    СоздатьПоШаблону.Заголовок = НСтр("ru = 'Создать по шаблону...'");
    ЗаполнитьЗначенияСвойств(СоздатьПоШаблону, СвойстваКомандыФормы);

    Если ДобавляемыйЭлемент.ПоказыватьКоманднуюПанель Тогда
        ДобавитьКнопкуНаФорму(Форма, "УправлениеПрисоединеннымиФайламиСоздатьПоШаблону" + НомерЭлемента,
            ГруппаПодменю, СоздатьПоШаблону.Имя);
        
        // Исправлено: Добавляем кнопку в контекстное меню управляемой формы
        ДобавитьКнопкуНаФорму(Форма, "УправлениеПрисоединеннымиФайламиСоздатьПоШаблонуИзКонтекстногоМеню" + НомерЭлемента,
            ГруппаДобавленияКонтекстногоМеню, СоздатьПоШаблону.Имя);
    КонецЕсли;

    Сканировать = Форма.Команды.Добавить("УправлениеПрисоединеннымиФайламиСканировать_" + НомерЭлемента);
    Сканировать.Заголовок = НСтр("ru = '" + ?(ОбщегоНазначения.ЭтоМобильныйКлиент(), "Сфотографировать", "Сканировать")+ "...'");
    ЗаполнитьЗначенияСвойств(Сканировать, СвойстваКомандыФормы);

    Если ДобавляемыйЭлемент.ПоказыватьКоманднуюПанель Тогда
        ДобавитьКнопкуНаФорму(Форма, "УправлениеПрисоединеннымиФайламиСканировать" + НомерЭлемента,
            ГруппаПодменю, Сканировать.Имя);
        
        // Исправлено: Добавляем кнопку сканирования в контекстное меню
        ДобавитьКнопкуНаФорму(Форма, "УправлениеПрисоединеннымиФайламиСканироватьИзКонтекстногоМеню" + НомерЭлемента,
            ГруппаДобавленияКонтекстногоМеню, Сканировать.Имя);
    КонецЕсли;
                
КонецЕсли;

Этот код гарантирует, что контекстное меню элемента управления присоединенными файлами будет содержать все необходимые команды («Создать по шаблону», «Сканировать»/«Сфотографировать») в зависимости от типа используемого клиента (тонкий клиент или мобильное приложение).

Рекомендации по интеграции исправлений

Для того чтобы не потерять внесенные изменения при последующем обновлении БСП до новых релизов, настоятельно рекомендуем придерживаться следующих правил:

← На главную