Skip to main content

revit-command-and-application

Build Autodesk Revit add-in entry points with Nice3point.Revit.Toolkit base classes, not raw IExternalCommand/IExternalApplication interfaces. USE FOR: authoring an external command or application with a simplified Execute()/OnStartup() override, optional OnShutdown() override, ready context properties, and automatic dependency resolution. DO NOT USE FOR: dispatching API work from code that runs outside the Revit API context (use revit-external-events).

Jump to install

Source facts

Repository
Nice3point/revit-skills
Last source activity
July 23, 2026 at 20:33
Detected SKILL.md language
English
Stars
13
Forks
3

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
revit-command-and-application
description
Build Autodesk Revit add-in entry points with Nice3point.Revit.Toolkit base classes, not raw IExternalCommand/IExternalApplication interfaces. USE FOR: authoring an external command or application with a simplified Execute()/OnStartup() override, optional OnShutdown() override, ready context properties, and automatic dependency resolution. DO NOT USE FOR: dispatching API work from code that runs outside the Revit API context (use revit-external-events).
license
MIT
# Revit Command and Application Derive add-in entry points from the `Nice3point.Revit.Toolkit` base classes. They replace the raw interface boilerplate (the full `Execute(commandData, ref message, elements)` signature, manual assembly resolution) with a simplified override and ready-made context properties. ## When to use - Authoring an `IExternalCommand`, `IExternalApplication`, or `IExternalDBApplication` entry point. - Reviewing an entry point that reimplements the raw interface by hand. ## When not to use - Building the ribbon inside `OnStartup` — that is `revit-ribbon`. - Invoking the API from a modeless window or background thread — that is `revit-external-events`. ## Workflow ### Step 1: Derive an external command Override `Execute()`; reach the context through the inherited `Application`, not by unpacking `commandData`. ```csharp [Transaction(TransactionMode.Manual)] public class DeleteWallsCommand : ExternalCommand { public override void Execute() { var document = Application.ActiveUIDocument.Document; } } ``` `ExternalCommand` exposes high-level `Application`, `View`, `JournalData`, and `ElementSet` properties that IExternalCommand provides. `Result` defaults to `Succeeded`; set `Result` and `ErrorMessage` only when the command must return a canceled or failed outcome. ### Step 2: Derive an external application ```csharp public class Application : ExternalApplication { public override void OnStartup() { var panel = Application.CreatePanel("Commands", "RevitAddin"); panel.AddPushButton<DeleteWallsCommand>("Delete walls"); } } ``` Use `ExternalDBApplication` for a database-only application. Override `OnShutdown()` only when the application has session cleanup to perform; it is optional. The ribbon helpers (`CreatePanel`, `AddPushButton<T>`) come from `Nice3point.Revit.Extensions` — see `revit-ribbon`. ### Step 3: Use the async base classes for long-running work Derive from `AsyncExternalCommand` and override `ExecuteAsync()`, or from `AsyncExternalApplication` and override `OnStartupAsync()`/`OnShutdownAsync()`. The sealed base pumps the message loop on Revit's main thread; `await` keeps the UI responsive while the continuation still runs in the API context — no external event needed. ```csharp public class Application : AsyncExternalApplication { public override async Task OnStartupAsync() { var settings = await LoadSettingsAsync(); // long-running work; the UI stays responsive CreateRibbon(settings); } } ``` ### Step 4: Rely on automatic dependency resolution The base classes open an assembly-resolve scope automatically; add-in dependencies load from the add-in folder without a manual `AssemblyResolve` handler. For dependencies loaded outside an entry point, open a scope explicitly with `ResolveHelper.BeginAssemblyResolveScope`. ### Step 5: Verify Test the observable model behavior on the Revit thread. Leave the default successful result unless the command must cancel or fail. ## Validation - [ ] The entry point derives from a Toolkit base class, not a hand-written interface implementation. - [ ] Context comes from the inherited properties, not manual `commandData` unpacking. - [ ] An application overrides `OnShutdown()` only when it has session cleanup to perform. - [ ] Long-running UI work uses `AsyncExternalCommand`. - [ ] The command has the expected observable behavior in Revit. - [ ] `Result` and `ErrorMessage` are set only for a canceled or failed command. ## Common Pitfalls | Pitfall | Correct approach | |--------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | Implementing `Execute(commandData, ref message, elements)` by hand | Derive from `ExternalCommand` and override `Execute()`. | | Manual `AppDomain.AssemblyResolve` for add-in dependencies | The base classes resolve automatically; else open a `ResolveHelper.BeginAssemblyResolveScope`. | | Blocking the UI in a long command | Use `AsyncExternalCommand` and `ExecuteAsync()`. | | `ExternalCommand` not found | The `Nice3point.Revit.Toolkit` package is not referenced. |
View on GitHub