---
name: bsp-external-components
description: "Use this skill when the agent needs to connect a Native API or COM external component on the client or the server, install or update an external component delivered via the configuration, upload a component from a ZIP file, query component metadata (identifier, version, name), or override the set of dependent tables for OData export/import. Do not use for platform-level COM automation (unrelated to BSP), for direct file upload to the external components catalog, or for HTTP integration via web services."
metadata:
  scope: bsp-3.1.11
  version: "3.1.11"
  layer: L3
  related_subsystems:
    - ВнешниеКомпоненты
    - ИнтерфейсOData
  related_skills:
    - bsp-fundamentals
    - bsp-base-common
    - bsp-longs-and-jobs
---

# ВнешниеКомпоненты и ИнтерфейсOData (StandardSubsystems 3.1.11)

Скил по подсистемам **ВнешниеКомпоненты** (Native API и COM-компоненты, устанавливаемые/подключаемые на клиенте и сервере) и **ИнтерфейсOData** (стандартный REST-интерфейс прикладной конфигурации для интеграции через протокол OData). Внутри — устойчивые точки входа: подключение, установка, загрузка из файла, получение информации о компоненте, и одна переопределяемая процедура OData.

> **COM-интеграция вне БСП.** Прямой вызов COM-объектов (`Новый COMОбъект(...)`, работа с `COMSafeArray`, `ПолучитьCOMОбъект`) — это **платформенный** механизм 1С, БСП его **не оборачивает**. Скил покрывает только тот COM-сценарий, который **сама** подсистема `ВнешниеКомпоненты` использует для обратной совместимости с компонентами 1С 7.7 (`ПодключитьКомпонентуИзРеестраWindows`).

## When to use

- Нужно подключить внешнюю компоненту (Native API или COM) на клиенте с асинхронным оповещением — `ВнешниеКомпонентыКлиент.ПодключитьКомпоненту`.
- Нужно подключить компоненту **на сервере** (фоновые задания, серверная обработка) — `ВнешниеКомпонентыСервер.ПодключитьКомпоненту`.
- Нужно предложить пользователю установить/обновить компоненту с портала ИТС — `ВнешниеКомпонентыКлиент.УстановитьКомпоненту`.
- Нужно загрузить файл компоненты (`.zip`) в справочник внешних компонент — `ВнешниеКомпонентыКлиент.ЗагрузитьКомпонентуИзФайла`.
- Нужно узнать, существует ли компонента с указанным идентификатором/версией, и в каком состоянии (найдена / отключена администратором) — `ВнешниеКомпонентыСервер.ИнформацияОКомпоненте` или клиент-серверный аналог `ВнешниеКомпонентыВызовСервера.ИнформацияОКомпоненте`.
- Нужно переопределить состав таблиц, выгружаемых/загружаемых через стандартный интерфейс OData — `ИнтерфейсODataПереопределяемый.ПриЗаполненииЗависимыхТаблицДляВыгрузкиЗагрузкиOData`.

## Не использовать, если

- Нужно автоматизировать **произвольный** COM-объект Windows (Excel, Word, любой OLE-сервер) — это **платформенный** механизм `Новый COMОбъект`, не БСП.
- Нужно подключиться к другой 1С-базе через COM-соединение — это `V83.COMConnector`, тоже платформенный; скил `bsp-data-exchange` может быть полезен по обвязке.
- Нужно настроить права/роли на стандартный интерфейс OData на уровне конфигуратора — это административная задача, не покрывается скилом.
- Нужно загружать/выгружать данные через OData вручную из прикладного кода — стандартный интерфейс OData **сам** формирует модель по метаданным; прикладной код вызывает только переопределение зависимых таблиц.

## Core concepts

### Где живут модули

Подсистема `ВнешниеКомпоненты` состоит из **четырёх** «видимых» общих модулей и **пяти** служебных:

| Модуль | Контекст | Назначение |
|---|---|---|
| `ВнешниеКомпонентыСервер` | Сервер | Серверное подключение компонент, информация о компоненте, обновление |
| `ВнешниеКомпонентыКлиент` | Клиент | Асинхронное подключение, установка, загрузка из файла (с диалогами пользователя) |
| `ВнешниеКомпонентыВызовСервера` | Сервер (вызов с клиента) | Серверный вызов без контекста формы — лёгкий, для клиентского кода |
| `ВнешниеКомпонентыКлиентЛокализация` | Клиент | Локализация: поиск компонент на портале, обновление с портала |
| `ВнешниеКомпонентыСлужебный` | Сервер | ⚠️ Служебный: проверки подключения, сохранённая информация, данные компонент |
| `ВнешниеКомпонентыСлужебныйКлиент` | Клиент | ⚠️ Служебный: фактическая реализация подключения/установки |
| `ВнешниеКомпонентыСлужебныйВызовСервера` | Сервер (вызов) | ⚠️ Служебный: тонкая обвязка |
| `ВнешниеКомпонентыВМоделиСервисаСлужебный` | Сервер | ⚠️ Служебный: разрешены только одобренные администратором общие компоненты |
| `ВнешниеКомпонентыВМоделиСервисаСлужебныйКлиент` | Клиент | ⚠️ Служебный: клиентская часть для модели сервиса |

> **Правило для клиент/сервер.** Клиентские методы — **асинхронные**, через `ОписаниеОповещения`. Серверные — **синхронные**, возвращают `Структура` с ключом `Подключено` (Булево) и `ПодключаемыйМодуль` (`ОбъектВнешнейКомпоненты`).

Подсистема `ИнтерфейсOData` состоит преимущественно из **служебных** модулей:

| Модуль | Контекст | Назначение |
|---|---|---|
| `ИнтерфейсODataПереопределяемый` | Сервер | **Единственный стабильный хук** для прикладного кода — переопределение зависимых таблиц |
| `ИнтерфейсODataСлужебный` | Сервер | ⚠️ Служебный: формирование модели по метаданным, события выгрузки/загрузки |
| `ИнтерфейсODataСлужебныйПовтИсп` | Сервер (повт.) | ⚠️ Служебный: кэш описания модели и ссылочных типов |

> ⚠️ **Прямого стабильного API для OData из прикладного кода почти нет.** Прикладной разработчик либо переопределяет `ИнтерфейсODataПереопределяемый.ПриЗаполненииЗависимыхТаблицДляВыгрузкиЗагрузкиOData`, либо настраивает стандартный интерфейс через Конфигуратор (роль `РольИнтерфейсаOData`).

### Жизненный цикл внешней компоненты

1. **Установка** на клиенте (`УстановитьКомпоненту`) — с портала ИТС или из конфигурации (общий макет типа `ДвоичныеДанные` с ZIP-архивом компоненты). Тонкий/веб-клиент показывает диалог с предложением установить.
2. **Подключение** — `ПодключитьКомпоненту` (клиент) или `ПодключитьКомпоненту` (сервер). Возвращает `ОбъектВнешнейКомпоненты`, у которого вызываются методы самой компоненты.
3. **Использование** — разработчик вызывает методы подключённого объекта (API конкретной компоненты: сканер, терминал СДР, ККТ и т. п.).
4. **Выгрузка** — при завершении сеанса платформа сама выгружает компоненту; явно вызывать отключение обычно не нужно.

### Хранилище компонент

В конфигурации с подсистемой присутствует **справочник `ВнешниеКомпоненты`**, в котором хранятся ZIP-архивы компонент с полями `Идентификатор`, `Версия`, `ДатаВерсии`, `Наименование`. Состояния: «Найдена в общем хранилище» (компонента нередактируемая) и «Найдена в информационной базе» (редактируемая администратором области).

### OData: что под капотом

Стандартный интерфейс OData — это **REST-точка входа** в конфигурацию, автоматически формируемая платформой по составу объектов метаданных. БСП добавляет к ней: модель метаданных (через `ИнтерфейсODataСлужебныйПовтИсп.ОписаниеМоделиДанныхКонфигурации`) и механизм переопределения зависимых таблиц. Прикладной код **не обходит** OData через HTTP вручную — он только дополняет модель и регистрирует свои регистры/справочники как «зависимые» (чтобы при выгрузке одного объекта автоматически подтягивались связанные).

## Key methods

| Метод | Сигнатура | Сервер/Клиент | Назначение | Пример вызова |
|---|---|---|---|---|
| `ВнешниеКомпонентыСервер.ПараметрыПодключения` | `ПараметрыПодключения()` → `Структура` (поля: `ИдентификаторыСозданияОбъектов`, `Изолированно`, `ПолноеИмяМакета`) | Сервер | Конструктор параметров для `ВнешниеКомпонентыСервер.ПодключитьКомпоненту`. `Изолированно = Истина` загружает компоненту в отдельный процесс ОС | `Параметры = ВнешниеКомпонентыСервер.ПараметрыПодключения(); Параметры.Изолированно = Истина;` |
| `ВнешниеКомпонентыСервер.ПодключитьКомпоненту` | `ПодключитьКомпоненту(Знач Идентификатор, Версия = Неопределено, ПараметрыПодключения = Неопределено)` → `Структура` (`Подключено`, `ПодключаемыйМодуль`, `ОписаниеОшибки`) | Сервер | Синхронное подключение компоненты на сервере. **В модели сервиса** — только общие компоненты, одобренные администратором | `Результат = ВнешниеКомпонентыСервер.ПодключитьКомпоненту("InputDevice", "8.1.7.10");` |
| `ВнешниеКомпонентыСервер.ИнформацияОКомпоненте` | `ИнформацияОКомпоненте(Знач Идентификатор, Знач Версия = Неопределено)` → `Структура` (`Существует`, `ДоступноРедактирование`, `Идентификатор`, `Версия`, `Наименование`, `ОписаниеОшибки`) | Сервер | Запрос метаданных компоненты: есть ли она, доступна ли на редактирование | `Инфо = ВнешниеКомпонентыСервер.ИнформацияОКомпоненте("InputDevice"); Если Инфо.Существует Тогда … КонецЕсли;` |
| `ВнешниеКомпонентыВызовСервера.ИнформацияОКомпоненте` | `ИнформацияОКомпоненте(Знач Идентификатор, Знач Версия = Неопределено)` | Сервер (вызов) | То же с клиента без контекста формы | `Инфо = ВнешниеКомпонентыВызовСервера.ИнформацияОКомпоненте(Идентификатор);` |
| `ВнешниеКомпонентыКлиент.ПараметрыПодключения` | `ПараметрыПодключения()` → `Структура` (поля: `Кэшировать`, `ПредложитьУстановить`, `ПредложитьЗагрузить`, `ТекстПояснения`, `ИдентификаторыСозданияОбъектов`, `Изолированно`, `ОбновлятьАвтоматически`) | Клиент | Конструктор параметров для клиентского `ПодключитьКомпоненту`. `ТекстПояснения` — строка, объясняющая пользователю, зачем нужна компонента | `Параметры = ВнешниеКомпонентыКлиент.ПараметрыПодключения(); Параметры.ТекстПояснения = НСтр("ru = 'Для сканера требуется компонента.'");` |
| `ВнешниеКомпонентыКлиент.ПодключитьКомпоненту` | `ПодключитьКомпоненту(Оповещение, Идентификатор, Версия = Неопределено, ПараметрыПодключения = Неопределено)` | Клиент | **Асинхронное** подключение на клиенте. В `ОбработкаОповещения(Результат, …)` `Результат.Подключено` и `Результат.ПодключаемыйМодуль` | `ВнешниеКомпонентыКлиент.ПодключитьКомпоненту(Оповещение, "InputDevice", , Параметры);` |
| `ВнешниеКомпонентыКлиент.УстановитьКомпоненту` | `УстановитьКомпоненту(Оповещение, Идентификатор, Версия = Неопределено, ПараметрыУстановки = Неопределено)` | Клиент | Асинхронная установка с портала ИТС или из макета. `Результат.Установлено` (Булево) приходит в оповещение | `ВнешниеКомпонентыКлиент.УстановитьКомпоненту(Оповещение, "InputDevice");` |
| `ВнешниеКомпонентыКлиент.ЗагрузитьКомпонентуИзФайла` | `ЗагрузитьКомпонентуИзФайла(Оповещение, ПараметрыЗагрузки = Неопределено)` | Клиент | Асинхронная загрузка `.zip` в справочник `ВнешниеКомпоненты`. Используется администратором | `ВнешниеКомпонентыКлиент.ЗагрузитьКомпонентуИзФайла(Оповещение, Параметры);` |
| `ИнтерфейсODataПереопределяемый.ПриЗаполненииЗависимыхТаблицДляВыгрузкиЗагрузкиOData` | `ПриЗаполненииЗависимыхТаблицДляВыгрузкиЗагрузкиOData(Таблицы)` | Сервер (переопределение) | **Переопределяемый** метод: реализуется в одноимённом модуле прикладной конфигурации, добавляет свои объекты в список зависимых таблиц OData | *реализуется в* `ИнтерфейсODataПереопределяемый` прикладной конфигурации |
| `ИнтерфейсODataСлужебный.ОбъектМетаданныхПоТипуСсылки` ⚠️ | `ОбъектМетаданныхПоТипуСсылки(Знач ТипСсылки)` | Сервер | ⚠️ **Служебный API**: разрешает `Тип` ссылки в объект метаданных. Использовать только когда стабильного аналога нет | `Мета = ИнтерфейсODataСлужебный.ОбъектМетаданныхПоТипуСсылки(ТипЗнч(Ссылка));` |

## Patterns

### 1. Подключение компоненты на клиенте с пояснением пользователю

```bsl
&НаКлиенте
Процедура ПодключитьСканер(Команда)

    Оповещение = Новый ОписаниеОповещения("ПодключитьСканерЗавершение", ЭтотОбъект);

    Параметры = ВнешниеКомпонентыКлиент.ПараметрыПодключения();
    Параметры.ТекстПояснения =
        НСтр("ru = 'Для работы со сканером требуется внешняя компонента 1С:Сканеры штрихкода (NativeApi).'");

    ВнешниеКомпонентыКлиент.ПодключитьКомпоненту(Оповещение, "InputDevice", , Параметры);

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

&НаКлиенте
Процедура ПодключитьСканерЗавершение(Результат, ДополнительныеПараметры) Экспорт

    Если Результат.Подключено Тогда
        // ПодключаемыйМодуль — ОбъектВнешнейКомпоненты, у него уже можно дёргать методы
        // конкретной компоненты (например, «Подключить», «Отключить», «ВернутьШтрихкод»)
        ПодключаемыйМодуль = Результат.ПодключаемыйМодуль;
    ИначеЕсли НЕ ПустаяСтрока(Результат.ОписаниеОшибки) Тогда
        ПоказатьПредупреждение(, Результат.ОписаниеОшибки);
    КонецЕсли;

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

Клиентский метод **всегда асинхронный** — результат приходит в `ОписаниеОповещения`, а не возвращается значением. В тонком/веб-клиенте БСП сама показывает диалоги «Установить компоненту?», «Загрузить с портала?» — за это отвечает флаг `ПредложитьУстановить` / `ПредложитьЗагрузить` в параметрах.

### 2. Подключение компоненты на сервере для фоновой обработки

```bsl
// Серверный вызов (например, из обработки, выполняемой в фоне)
Результат = ВнешниеКомпонентыСервер.ПодключитьКомпоненту(
    "InputDevice", // Идентификатор
    ,              // Версия — последняя доступная
    );             // ПараметрыПодключения — по умолчанию

Если Результат.Подключено Тогда
    // ПодключаемыйМодуль доступен до конца серверного вызова
    Попытка
        ПодключаемыйМодуль.Подключить(«COM», 0);
    Исключение
        // Записать в журнал регистрации
    КонецПопытки;
КонецЕсли;
```

Серверный вызов **синхронный** — результат сразу в переменной. Используется, когда компонента нужна в коде, исполняемом вне клиентского сеанса (фоновые задания, регламент, обработка по расписанию).

### 3. Установка компоненты, если её нет

```bsl
&НаКлиенте
Процедура УстановитьСканерПриНеобходимости()

    ОповещениеОЗавершении = Новый ОписаниеОповещения("УстановкаЗавершение", ЭтотОбъект);

    ПараметрыУстановки = ВнешниеКомпонентыКлиент.ПараметрыУстановки();
    ПараметрыУстановки.ТекстПояснения = НСтр("ru = 'Требуется установить компоненту сканера.'");
    ПараметрыУстановки.ПредложитьЗагрузить = Истина;

    ВнешниеКомпонентыКлиент.УстановитьКомпоненту(ОповещениеОЗавершении,
        "InputDevice", , ПараметрыУстановки);

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

&НаКлиенте
Процедура УстановкаЗавершение(Результат, ДопПараметры) Экспорт
    Если НЕ Результат.Установлено
            И НЕ ПустаяСтрока(Результат.ОписаниеОшибки) Тогда
        ПоказатьПредупреждение(, Результат.ОписаниеОшибки);
    КонецЕсли;
КонецПроцедуры
```

### 4. Переопределение зависимых таблиц OData

```bsl
// В модуле ИнтерфейсODataПереопределяемый прикладной конфигурации
Процедура ПриЗаполненииЗависимыхТаблицДляВыгрузкиЗагрузкиOData(Таблицы) Экспорт

    // Добавить свой регистр сведений в список таблиц,
    // которые автоматически подтягиваются при выгрузке основного объекта
    Таблицы.Добавить("РегистрСведений.СостоянияЗаказов");

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

Этот метод — **единственный стабильный хук** между прикладным кодом и стандартным интерфейсом OData. Реализуется в одноимённом модуле прикладной конфигурации.

## Anti-patterns

### ❌ Вызывать `Новый COMОбъект` напрямую для компонент 1С

```bsl
// ❌ COM-объект создан мимо подсистемы — не пройдёт проверки безопасности,
//    не обновится автоматически, не будет работать в модели сервиса
Компонента = Новый COMОбъект("InputDevice.BarcodeScanner");
```

```bsl
// ✅ Через подсистему — БСП сама разрешает, кэширует и обновляет
Оповещение = Новый ОписаниеОповещения("ПодключитьЗавершение", ЭтотОбъект);
ВнешниеКомпонентыКлиент.ПодключитьКомпоненту(Оповещение, "InputDevice");
```

### ❌ Ждать результат от клиентского `ПодключитьКомпоненту` как от функции

```bsl
// ❌ ОШИБКА: метод возвращает «Неопределено», результат приходит в оповещение
Результат = ВнешниеКомпонентыКлиент.ПодключитьКомпоненту( , "InputDevice");
```

```bsl
// ✅ Клиентский вариант — всегда асинхронный
Оповещение = Новый ОписаниеОповещения("Завершение", ЭтотОбъект);
ВнешниеКомпонентыКлиент.ПодключитьКомпоненту(Оповещение, "InputDevice");
```

### ❌ Использовать `ВнешниеКомпонентыСлужебный` напрямую из прикладного кода

```bsl
// ❌ Служебный модуль: обратная совместимость не гарантируется
Данные = ВнешниеКомпонентыСлужебный.ДанныеВнешнихКомпонент("ДляОбновления");
```

```bsl
// ✅ Стабильный API: тот же результат через серверный модуль
Таблица = ВнешниеКомпонентыСервер.ИспользуемыеКомпоненты("ДляОбновления");
```

Служебные модули предназначены для **внутренних нужд БСП**; в прикладном коде они могут быть переименованы или изменены без предупреждения.

### ❌ Дёргать методы `ИнтерфейсODataСлужебный` для построения своей модели

```bsl
// ❌ Служебный модуль: модель пересобирается при обновлении
Модель = ИнтерфейсODataСлужебныйПовтИсп.ОписаниеМоделиДанныхКонфигурации();
```

```bsl
// ✅ Стабильная точка расширения — переопределение
//    (реализуется в модуле ИнтерфейсODataПереопределяемый прикладной конфигурации)
Процедура ПриЗаполненииЗависимыхТаблицДляВыгрузкиЗагрузкиOData(Таблицы) Экспорт
    Таблицы.Добавить("РегистрСведений.СвоиДанные");
КонецПроцедуры
```

### ❌ Передавать `ПолноеИмяМакета` через `ВнешниеКомпонентыКлиент.ПараметрыПодключения`

```bsl
// ❌ Клиентский конструктор не содержит поле «ПолноеИмяМакета» —
//    это поле есть только в серверном ВнешниеКомпонентыСервер.ПараметрыПодключения()
Параметры = ВнешниеКомпонентыКлиент.ПараметрыПодключения();
Параметры.ПолноеИмяМакета = "ОбщийМакет.КомпонентаСканера"; // поле отсутствует
```

```bsl
// ✅ Для серверного подключения с макетом — серверный конструктор
Параметры = ВнешниеКомпонентыСервер.ПараметрыПодключения();
Параметры.ПолноеИмяМакета = "ОбщийМакет.КомпонентаСканера";
```

## How to explore deeper

### Где смотреть в конфигурации

- Общий модуль `ВнешниеКомпонентыСервер` — серверное API подключения/получения информации.
- Общий модуль `ВнешниеКомпонентыКлиент` — клиентское API (асинхронное, с диалогами).
- Общий модуль `ВнешниеКомпонентыВызовСервера` — лёгкая клиент-серверная обвязка (для вызовов с клиента без контекста формы).
- Общий модуль `ВнешниеКомпонентыКлиентЛокализация` — локализация поиска и обновления на портале 1С.
- Общий модуль `ИнтерфейсODataПереопределяемый` — единственная стабильная точка расширения OData.
- Справочник `ВнешниеКомпоненты` — хранилище ZIP-архивов.
- Подписки на события `ВнешниеКомпонентыСлужебный*` — служебные модули, к которым БСП подписывается на события приложения.

### Grep-шаблон

```text
# Найти стабильное API в модулях ВнешниеКомпоненты*
^(Функция|Процедура) [А-Я][А-Яа-яA-Za-z_]+\(.*\) Экспорт

# Найти только серверный блок стабильного API
^#Область ПрограммныйИнтерфейс

# Найти вызовы подсистемы из прикладного кода (для понимания идиоматичного стиля)
ВнешниеКомпоненты(Клиент|Сервер|ВызовСервера)\.[А-Я][А-Яа-яA-Za-z_]+
```
