Почему расширение 1С не перехватывает серверную процедуру ПриСозданииНаСервере?

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

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

Представим, что перед нами стоит задача модифицировать форму выбора списка партнеров, чтобы всегда отображать в ней дополнительную информацию по контрагентам, например, ИНН и КПП. Для этого нам необходимо установить параметр ЗапросСИнформациейПоКонтрагенту = Истина в процедуре ПартнерыФормаВыбораСпискаПриСозданииНаСервере. Мы заимствуем эту процедуру в расширение, используем директиву &Вместо, но наши изменения не применяются, и выполняется стандартный код конфигурации.

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

1. Корректное использование директив контекста вызова

Первым и самым критичным моментом, который часто является причиной подобных проблем, является некорректное указание директивы контекста вызова. В 1С:Предприятии процедуры и функции могут выполняться на клиенте (в браузере или тонком клиенте) или на сервере (на сервере 1С или в файловой базе). Для указания контекста используются директивы &НаКлиенте, &НаСервере, &НаСервереБезКонтекста.

  1. Анализ проблемы: Обработчик события ПриСозданииНаСервере, как следует из его названия, является серверным событием. Это означает, что процедура, которая его обрабатывает, должна выполняться исключительно на сервере. В первоначальном коде расширения была допущена ошибка: перед серверной процедурой Расш1_ПартнерыФормаВыбораСпискаПриСозданииНаСервере была указана директива &НаКлиенте.

    
    &НаКлиенте
    &Вместо("ПартнерыФормаВыбораСпискаПриСозданииНаСервере")
    Процедура Расш1_ПартнерыФормаВыбораСпискаПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка) Экспорт
        // ... ваш код ...
    КонецПроцедуры
    

    Это является грубой ошибкой. Система 1С, видя директиву &НаКлиенте, будет пытаться выполнить этот код на клиенте, но поскольку событие ПриСозданииНаСервере происходит на сервере, она просто проигнорирует наш перехват или вызовет ошибки, которые могут быть неочевидны.

  2. Правильное решение: Для серверных процедур всегда используйте директиву &НаСервере. Исправим код следующим образом:

    
    &НаСервере
    &Вместо("ПартнерыФормаВыбораСпискаПриСозданииНаСервере")
    Процедура Расш1_ПартнерыФормаВыбораСпискаПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка) Экспорт
        // ... ваш код ...
    КонецПроцедуры
    

    Это гарантирует, что система 1С будет правильно интерпретировать контекст выполнения процедуры и применять наш перехват.

2. Очистка кэша 1С

Даже после исправления директивы контекста вызова, иногда изменения могут не вступать в силу немедленно. Это очень распространенная проблема в 1С, связанная с кэшированием конфигурации и метаданных. Система 1С активно использует кэш для ускорения работы, но иногда он может содержать устаревшие данные.

Давайте рассмотрим, как правильно очистить кэш:

  1. Зачем это нужно: После изменений в расширении (или в самой конфигурации) 1С может продолжать использовать старые версии форм, модулей или метаданных из кэша. Очистка кэша заставляет платформу заново скомпилировать и загрузить все данные.

  2. Способы очистки кэша:

    1. Ручное удаление папок: Закройте все сеансы 1С. Перейдите в системные папки пользователя (обычно C:\Users\ВашПользователь\AppData\Roaming\1C\1Cv8 и C:\Users\ВашПользователь\AppData\Local\1C\1cv8). В этих папках найдите каталоги, названия которых состоят из длинных наборов символов (GUID), и удалите их. В этих каталогах хранится кэш ваших информационных баз.

    2. Удаление базы из списка: В окне запуска 1С удалите вашу информационную базу из списка и затем добавьте ее заново. При этом кэш для этой базы будет очищен.

    3. Использование параметра запуска: В окне запуска 1С, выбрав вашу информационную базу, нажмите кнопку "Изменить". На одном из шагов мастера в поле "Дополнительные параметры запуска" можно указать /ClearCache. После первого запуска с этим параметром кэш будет очищен, и параметр можно будет удалить.

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

3. Правильный способ заимствования и перехвата процедуры

Механизм заимствования процедур в расширениях через контекстное меню является наиболее надежным способом, так как платформа сама формирует необходимую структуру. Давайте проанализируем этот процесс.

  1. Как заимствовать процедуру: Откройте конфигуратор, найдите в модуле формы Справочник.Партнеры.ФормаВыбораСписка процедуру ПартнерыФормаВыбораСпискаПриСозданииНаСервере. Нажмите правой кнопкой мыши на процедуре и выберите пункт меню "Расширение" -> "Добавить в расширение". Вам будет предложено выбрать тип расширяющего метода: "Перед", "После" или "Вместо". Для полного перехвата выбираем "Вместо".

  2. Структура процедуры &Вместо: При выборе "Вместо" платформа создает процедуру в расширении, которая полностью замещает оригинальную. Если вы хотите частично изменить поведение типовой процедуры, а затем вернуть управление ей, используйте функцию ПродолжитьВызов(). Она позволяет вызвать оригинальный код расширяемого метода изнутри перехваченной процедуры расширения.

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

    
    &НаСервере
    &Вместо("ПартнерыФормаВыбораСпискаПриСозданииНаСервере")
    Процедура Расш1_ПартнерыФормаВыбораСпискаПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка) Экспорт
        // Здесь мы можем внести наши изменения до выполнения стандартного кода
        ЗапросСИнформациейПоКонтрагенту = Истина;
    
        // Вызываем оригинальную процедуру.
        // Если нужно передать измененные параметры, их можно передать в ПродолжитьВызов().
        ПродолжитьВызов(Форма, Отказ, СтандартнаяОбработка);
    
        // Здесь мы можем внести изменения после выполнения стандартного кода,
        // например, скорректировать уже установленные свойства формы
    КонецПроцедуры
    

    В нашем случае, поскольку мы хотим установить значение параметра ЗапросСИнформациейПоКонтрагенту, а затем позволить типовому коду использовать это значение, вызов ПродолжитьВызов() является оптимальным решением. Это позволяет избежать копирования всего большого типового кода процедуры в расширение, что значительно упрощает поддержку.

4. Использование `&ИзменениеИКонтроль` для точечных модификаций (Платформа 8.3.15+)

Начиная с версии платформы 8.3.15, появился более удобный и современный способ модификации типового кода — директива &ИзменениеИКонтроль. Этот подход особенно полезен, когда нужно внести небольшие изменения в середину большой процедуры, не копируя весь её текст.

  1. Преимущества &ИзменениеИКонтроль:

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

    2. Точечные изменения: Вы можете точно указать, какой фрагмент кода нужно удалить, а какой вставить, или просто добавить новый код в определенное место.

  2. Пример использования: Для нашей задачи по установке ЗапросСИнформациейПоКонтрагенту = Истина, использование &ИзменениеИКонтроль будет выглядеть так. Сначала заимствуем процедуру ПартнерыФормаВыбораСпискаПриСозданииНаСервере в расширение через контекстное меню, выбрав "Добавить в расширение" -> "Изменение и контроль". Затем находим нужную строку и модифицируем ее:

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

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

5. Отладка расширений

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

  1. Установка точек останова: Поставьте точку останова в начале вашей процедуры расширения, например, на строке &НаСервере. Если отладчик остановится на этой точке, значит, расширение применяется и ваш код выполняется. Если нет, проблема в применении самого расширения (неправильные флаги, кэш, конфликт).

  2. Проверка флагов расширения:

    1. Убедитесь, что расширение "Активно". В конфигураторе (или в режиме предприятия через "Функции для технического специалиста" -> "Расширения") проверьте, что напротив вашего расширения стоит флажок "Активно".

    2. Убедитесь, что флаг "Безопасный режим" снят, если ваше расширение выполняет потенциально "опасные" операции (например, доступ к файловой системе, внешним компонентам). В данном случае, хотя установка свойства формы и не является "опасной", снятие этого флага часто рекомендуется, чтобы исключить его как возможную причину проблем.

  3. Отладка серверного кода в файловой и клиент-серверной базах:

    1. Файловая база: В файловой базе отладка серверного кода обычно не вызывает проблем. Достаточно запустить режим отладки из конфигуратора.

    2. Клиент-серверная база: Если вы работаете с клиент-серверной базой, для отладки серверного кода необходимо, чтобы на сервере 1С:Предприятия был разрешен режим отладки. Это может потребовать настройки параметров службы сервера 1С:Предприятия (добавление ключа -debug в строку запуска агента сервера) и разрешения отладки в настройках информационной базы в конфигураторе.

  4. Использование Сообщить(): В крайнем случае, если отладчик по каким-то причинам недоступен, вы можете временно добавить в вашу процедуру расширения команду Сообщить("Код расширения выполняется!"). Если сообщение появится, значит, код достигается, и проблема в логике. Если нет, проблема в применении расширения.

6. Дополнительные рекомендации и проверка общих моментов

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

  1. Проверка имени расширения: Убедитесь, что имя процедуры в расширении (например, Расш1_ПартнерыФормаВыбораСпискаПриСозданииНаСервере) соответствует префиксу вашего расширения, если вы используете автоматическое присвоение имен.

  2. Ресоздание расширения: Иногда, при длительной работе с расширением и многократными изменениями, оно может "повредиться" или некорректно обновиться. Попробуйте удалить текущее расширение и создать его заново, заимствуя все необходимые объекты и процедуры с нуля. Это может решить скрытые проблемы.

  3. Модуль, куда добавлена процедура: Убедитесь, что вы добавляете процедуру перехвата именно в модуль формы, а не в общий модуль, если речь идет об обработчике события формы. Хотя в нашем случае заимствование через ПКМ по процедуре в модуле формы само по себе приводит к добавлению процедуры в модуль формы расширения, это стоит проверить.

  4. Конфликты с другими расширениями: Хотя вы упомянули, что это единственное расширение, в сложных системах стоит всегда помнить о возможности конфликтов. Если бы было несколько расширений, порядок их применения и тип перехвата могли бы влиять на результат (например, одно расширение использует &Вместо, а другое &После для одной и той же процедуры).

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

← На главную