Плагины для Revit

Как написать плагин для Revit: пошаговый маршрут от SDK до отладки

Первый плагин — это не «магия Autodesk», а обычная .NET-сборка, которую Revit загружает по манифесту. Ниже — минимальный рабочий маршрут: что установить, какие файлы создать, где Revit ищет сборку и почему половина первых запусков заканчивается молчанием в ленте.

Олег Сахаров·

Что именно загружает Revit

Плагин для Revit — это библиотека классов .NET, которая ссылается на RevitAPI.dll и RevitAPIUI.dll. Сам Revit не ищет вашу сборку по имени: он читает .addin-манифест — XML-файл, в котором записано, где лежит DLL и какой класс реализует команду. Нет манифеста — нет кнопки, даже если код идеально компилируется.

Отсюда два независимых слоя, которые нужно проверить по отдельности. Сначала сборка: правильная версия .NET, правильные ссылки на API, отсутствие копий RevitAPI.dll рядом с плагином. Затем регистрация: манифест в правильной папке, корректный GUID, существующий класс и публичный конструктор без параметров. Большинство «плагин не появился» — это второй слой, а не код.

Что понадобится

  • Установленный Revit нужной версии — API ставится вместе с продуктом, отдельный SDK не обязателен.
  • Visual Studio 2022 или Rider с поддержкой .NET Framework 4.8 и .NET 8.
  • Целевая платформа под версию Revit: 2022–2024 — .NET Framework 4.8, 2025 и новее — .NET 8. Сборка под 4.8 не загрузится в Revit 2025+, и наоборот.
  • Понимание, что модель меняется только внутри транзакции, а читать её можно коллекторами и фильтрами.

Если вы собираете один плагин на несколько версий, держите общий код в отдельной библиотеке без ссылок на Revit API, а тонкий слой команд — по проекту на версию. Так расчётная логика тестируется обычными unit-тестами, а различия API локализованы. Подробнее о матрице версий — в материале «Версии Revit и .NET».

Шаг 1. Манифест .addin

Revit читает манифесты из двух мест: пользовательского %APPDATA%\Autodesk\Revit\Addins\<версия> и машинного %PROGRAMDATA%\Autodesk\Revit\Addins\<версия>. Для разработки удобнее пользовательская папка: она не требует прав администратора.

<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
  <AddIn Type="Command">
    <Name>Проверка помещений</Name>
    <Assembly>C:\Dev\RoomCheck\bin\Debug\RoomCheck.dll</Assembly>
    <AddInId>6F1C2B4A-9E7D-4A31-8C55-2B0F1D7E9A10</AddInId>
    <FullClassName>RoomCheck.CheckRoomsCommand</FullClassName>
    <VendorId>ROOMCHECK</VendorId>
    <VendorDescription>Внутренний инструмент проверки помещений</VendorDescription>
  </AddIn>
</RevitAddIns>

AddInId — GUID плагина, а не проекта. Он должен быть уникальным и не меняться между сборками: по нему Revit различает команды и хранит настройки. FullClassName указывается вместе с пространством имён; опечатка здесь даёт пустую ленту без сообщения об ошибке.

Шаг 2. Команда: минимум кода

Точка входа команды — класс, реализующий IExternalCommand. Атрибут транзакции обязателен: без него Revit не даст менять модель предсказуемым образом.

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;

namespace RoomCheck;

[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public sealed class CheckRoomsCommand : IExternalCommand
{
    public Result Execute(
        ExternalCommandData commandData,
        ref string message,
        ElementSet elements)
    {
        var doc = commandData.Application.ActiveUIDocument?.Document;
        if (doc is null)
        {
            message = "Откройте документ Revit.";
            return Result.Failed;
        }

        var rooms = new FilteredElementCollector(doc)
            .OfCategory(BuiltInCategory.OST_Rooms)
            .WhereElementIsNotElementType()
            .ToElements();

        TaskDialog.Show("Проверка помещений", $"Найдено помещений: {rooms.Count}");
        return Result.Succeeded;
    }
}

Это чтение: транзакция не нужна, модель не меняется. Как только вы добавляете doc.Create или запись параметра, оберните изменения в using (var tx = new Transaction(doc, "…")) с tx.Start() и tx.Commit(), а при ошибке — tx.RollBack().

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

Шаг 3. Сборка и ссылки на API

Добавьте ссылки на RevitAPI.dll и RevitAPIUI.dll из папки установленного Revit и обязательно включите Copy Local = false. Если эти DLL окажутся рядом с плагином, вы получите конфликт версий и непредсказуемое поведение: Revit уже загрузил свою копию.

Путь к API зависит от версии, поэтому в проекте удобно держать свойство RevitVersion и подставлять его в HintPath. Одна сборка «на все версии» невозможна: разные целевые runtime и разные наборы API.

Шаг 4. Запуск и отладка

  1. Проверьте манифест: папка версии, путь к DLL, GUID, полное имя класса. После правки манифеста Revit нужно перезапустить.
  2. Для отладки укажите в свойствах проекта внешнюю программу C:\Program Files\Autodesk\Revit <год>\Revit.exe и запускайте из Visual Studio — точки останова сработают в вашем коде.
  3. Если команда не появилась, сначала смотрите журнал Revit (файл journal в папке Journals) и только потом код: там фиксируется, какой манифест не загрузился.
  4. Проверяйте на копии модели. Ошибочная транзакция в рабочем файле — это не «неудобно», а потерянные часы и, возможно, данные.

Типовые ошибки первого плагина

  • Класс не найден. Пространство имён в манифесте не совпадает с кодом, класс не публичный или сборка собрана под другую версию .NET.
  • Команда есть, но падает. Запись в модель без транзакции, обращение к документу из фонового потока или работа с элементом, который уже удалён.
  • «Файл уже используется». Рядом с плагином лежит копия RevitAPI.dll. Уберите Copy Local и пересоберите.
  • Работает у вас, не работает у коллеги. Разные версии Revit или разные папки манифестов. Проверяйте матрицу версий, а не «попросите перезапустить».

Как в этот маршрут встраивается AI

AI-агент не отменяет шаги выше, но снимает большую часть рутины: генерирует каркас команды, подсказывает нужный API, пишет тесты для расчётной части и объясняет ошибку компиляции. Работает это только при двух условиях: у агента есть контекст (версия Revit, структура проекта, правила именования) и у вас есть проверка результата.

Практический приём — дробить задачу. Вместо «напиши плагин для проверки помещений» дайте последовательность: «собери список помещений без имени», «добавь фильтр по уровню», «покажи отчёт в TaskDialog», «заверни запись параметра в транзакцию». Каждый шаг проверяем, каждый коммитим. Именно так устроен практический контур в RevitAiTools: агент работает по готовым контрактам и образцам, а не изобретает архитектуру заново.

Чек-лист перед словом «готово»

  • Манифест лежит в папке нужной версии, GUID стабилен.
  • Copy Local выключен для RevitAPI.dll и RevitAPIUI.dll.
  • Все изменения модели — в транзакции, с откатом при ошибке.
  • Проверено на копии реальной модели, а не только на пустом файле.
  • Есть понятное сообщение об ошибке вместо молчаливого отказа.
  • Инструкция по установке занимает один экран и не требует объяснений автора.

Дальше начинается инженерия: тесты, журналирование, поддержка нескольких версий и выпуск обновлений. Об этом — в маршруте «от задачи до релиза» и в материалах о MCP, если вы хотите управлять тем же инструментом из AI-клиента.

Перейти к практике

Первоначальный платёж открывает приватный GitHub-репозиторий RevitAiTools, обучающий курс и сообщество. Условия, состав доступа и актуальная цена — на главной странице.

Посмотреть условия доступа
Как написать плагин для Revit: пошаговый маршрут от SDK до отладки