DBTools.App
Purpose: Main application assembly containing all tools and bootstrapping logic.
Output: DBTools.dll
Target Frameworks: net48, net8.0-windows
Overview
DBTools.App is the main application assembly that compiles to DBTools.dll. It is loaded by DBTools.Loader and serves as the host for all tool implementations, the dependency injection container, ribbon composition, and Revit lifecycle management.
This project uses file linking to compile tool source code from src/Tools/ into the single DBTools.dll assembly. Individual tool projects exist primarily for IDE organization, isolated testing, and XAML designer support, but at runtime everything executes within this unified assembly.
Source:
src/DBTools.App/DBTools.App.csproj:1-13
Responsibilities
| Responsibility | Implementation |
|---|---|
| Application entry point | AddinEntry implements IExternalApplication |
| Runtime initialization | AppRuntimeFactory creates DiAppRuntime |
| DI container setup | DbtServiceBootstrapper.Build() registers all services |
| Tool discovery | DbtToolModuleCatalog.Discover() scans embedded YAML manifests |
| Ribbon composition | DbtRibbonComposer creates tab, panels, and buttons |
| Hook coordination | DbtHookHost dispatches view-activated and contextual ribbon events |
| Test API hosting | TestApiHost enables API calls from test harnesses |
| File-linked tool compilation | MSBuild items compile src/Tools/**/*.cs into this assembly |
Source:
src/DBTools.App/Addin/AddinEntry.cs:29-247
Key Components
AddinEntry (Application Entry Point)
The AddinEntry class is the inner application entry point, loaded by DBTools.Loader.AddinEntry after assembly resolution is configured.
public class AddinEntry : IExternalApplication
{
public static IRevitTask? RevitTask { get; private set; }
private static DbtHookHost? _hookHost;
private static DbtToolRegistry? _toolRegistry;
private static DbtRibbonComposer? _ribbonComposer;
public Result OnStartup(UIControlledApplication application) { ... }
public Result OnShutdown(UIControlledApplication application) { ... }
}
Source:
src/DBTools.App/Addin/AddinEntry.cs:29-43
Key Static Fields:
RevitTask- TheIRevitTaskfor marshaling work to Revit's UI thread_hookHost- Coordinates view-activated and contextual ribbon hooks_toolRegistry- Registry of discovered tool commands_ribbonComposer- Manages ribbon tab/panel creation
Source:
src/DBTools.App/Addin/AddinEntry.cs:33-36
Bootstrap System
AppRuntimeFactory
Factory class that creates the application runtime:
public static class AppRuntimeFactory
{
public static IAppRuntime Create() => new DiAppRuntime();
}
Source:
src/DBTools.App/Bootstrap/AppRuntimeFactory.cs:5-8
DiAppRuntime
The DI-based implementation of IAppRuntime that owns the service provider:
public sealed class DiAppRuntime : IAppRuntime
{
private readonly IServiceProvider _root;
public DiAppRuntime()
{
var root = DbtServiceBootstrapper.Build();
_root = root.Services;
_logger = _root.GetRequiredService<ILogger<DiAppRuntime>>();
_settings = _root.GetRequiredService<ISettingsProvider>();
}
public IAppRunScope CreateRunScope(UIApplication uiapp, RevitRunScopeProfile profile)
{
var scope = _root.GetRequiredService<IServiceScopeFactory>().CreateScope();
var rsFactory = scope.ServiceProvider.GetRequiredService<IRevitRunScopeFactory>();
var accessor = scope.ServiceProvider.GetRequiredService<IRevitRunScopeAccessor>();
var rs = rsFactory.CreateScope(uiapp, profile);
accessor.Current = rs;
return new DiRunScope(scope);
}
}
Source:
src/DBTools.App/Bootstrap/DiAppRuntime.cs:17-62
DbtServiceBootstrapper
The central DI container builder that registers all services:
public static class DbtServiceBootstrapper
{
public static DbtServiceRoot Build(Action<IServiceCollection>? configure = null)
{
// 1. Create logging host
// 2. Load configuration from settings.{YEAR}.json
// 3. Register core services
// 4. Discover and register tool modules
// 5. Start hosted services
}
}
Source:
src/DBTools.App/Bootstrap/DbtServiceBootstrapper.cs:163-248
Service Categories Registered:
- Logging -
IDbtLoggingHost,ILoggerFactory,ILogger<T> - Debug -
IDebugModeService(session-only) - Settings -
IOptionsMonitor<T>,IOptionsWriter,ISettingsProvider - Revit Scope -
IRevitRunScopeFactory,IRevitRunScopeAccessor,IRevitCallGate - Transactions -
ITransactionRunner,ITransactionGroupService - Execution -
ISafeExecutor,IAlertService - Hosted Services -
ILoggerWindowManager,HostedServiceCoordinator
Source:
src/DBTools.App/Bootstrap/DbtServiceBootstrapper.cs:376-437
DbtServiceRoot
Container holding all initialized services:
public sealed class DbtServiceRoot
{
public IServiceProvider Services { get; }
public IConfiguration Configuration { get; }
public IDbtLoggingHost LoggingHost { get; }
public DbtToolRegistry ToolRegistry { get; }
public IReadOnlyList<DbtToolModule> ToolModules { get; }
}
Source:
src/DBTools.App/Bootstrap/DbtServiceBootstrapper.cs:34-67
Ribbon Composition
DbtRibbonComposer
Composes the DB Tools ribbon from tool specifications:
public sealed class DbtRibbonComposer : IDisposable
{
public void Compose(DbtToolRegistry registry, Flags flags)
{
// 1. Create ribbon tab
// 2. Create panels in defined order
// 3. Build control plans for each tool
// 4. Execute plans in order (push buttons, split buttons, pulldowns, stacked)
// 5. Subscribe to settings changes
}
}
Source:
src/DBTools.App/Features/Ribbon/DbtRibbonComposer.cs:19-102
Control Types Supported:
| Control Kind | Description |
|---|---|
PushButton |
Standard button |
SplitButtonItem |
Primary + dropdown items |
PulldownButtonItem |
Dropdown menu |
StackedButtonItem |
2-3 buttons in vertical stack |
Source:
src/DBTools.App/Features/Ribbon/DbtRibbonComposer.cs:159-252
Panel Order:
- Settings
- Common
- Structural
- Testing
- Any additional panels (alphabetical)
Source:
src/DBTools.App/Features/Ribbon/DbtRibbonComposer.cs:109-121
RibbonDefinition
Defines ribbon constants (tab name, panel names, command names):
public static class RibbonDefinition
{
public const string TabName = SettingsConstants.Ribbon.TabName;
public static class Panels
{
public const string Settings = SettingsConstants.Ribbon.Panels.Settings;
public const string Structural = SettingsConstants.Ribbon.Panels.Structural;
public const string Testing = SettingsConstants.Ribbon.Panels.Testing;
public const string Common = SettingsConstants.Ribbon.Panels.Common;
}
}
Source:
src/DBTools.App/Features/Ribbon/RibbonDefinition.cs:5-21
Availability Predicates
Located in Tools/Availability/, these classes control when ribbon buttons are enabled.
DbtDocumentAvailability
Requires an active document to be open:
public sealed class DbtDocumentAvailability : IExternalCommandAvailability
{
public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
{
return applicationData?.ActiveUIDocument?.Document != null;
}
}
Source:
src/DBTools.App/Tools/Availability/DbtDocumentAvailability.cs:10-16
DbtSelectionAvailability
Base class requiring element selection, with optional category filtering:
public class DbtSelectionAvailability : IExternalCommandAvailability
{
protected virtual BuiltInCategory[]? RequiredCategories => null;
protected virtual bool IsElementMatch(Element element) => true;
public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
{
// Check for selection and optional category/element matching
}
}
Source:
src/DBTools.App/Tools/Availability/DbtSelectionAvailability.cs:13-52
DbtStructuralFramingSelectionAvailability
Requires structural framing selection:
public sealed class DbtStructuralFramingSelectionAvailability : DbtSelectionAvailability
{
protected override BuiltInCategory[]? RequiredCategories
=> new[] { BuiltInCategory.OST_StructuralFraming };
}
Source:
src/DBTools.App/Tools/Availability/DbtSelectionAvailability.cs:57-60
Hooks System
AppHookModule
The application-level hook module that registers view-activated handlers:
public sealed class AppHookModule : DbtToolModule
{
public override void RegisterServices(IServiceCollection services, DbtToolManifest manifest)
{
services.AddSingleton<ViewActivatedHookHandler, ViewActivatedHookHandler>();
}
public override void RegisterHooks(DbtToolRegistry registry, DbtToolManifest manifest)
{
registry.RegisterHook<IViewActivatedHookHandler, ViewActivatedHookHandler>();
}
}
Source:
src/DBTools.App/Features/Hooks/AppHookModule.cs:7-22
TestApiHost
Static host for test harness integration, providing API access outside Revit command context:
public static class TestApiHost
{
public static bool IsInitialized { get; private set; }
public static void Initialize(UIControlledApplication app)
{
// Create ExternalEvent handler
}
public static Task<object?> RunAsync(Func<object, Task<object?>> work)
{
// Queue work and raise ExternalEvent.
// Raise statuses:
// - Accepted/Pending: work remains queued and will be processed
// - other: work is removed and the returned task faults
}
}
ProcessQueue drains up to 50 queued items per ExternalEvent tick and re-raises the ExternalEvent when backlog remains, so throttling does not strand queued work.
Source:
src/DBTools.App/Addin/TestApiHost.cs:11
OnStartup Sequence
The complete startup flow with source references:
1. Set Revit year from VersionNumber (for per-instance log files)
> Source: AddinEntry.cs:55-66
2. Initialize AppRuntime via AppRuntimeFactory.Create()
> Source: AddinEntry.cs:72
3. Resolve ISafeExecutor, DbtToolRegistry, DbtHookHost
> Source: AddinEntry.cs:74-76
4. Validate theme (mandatory - fails startup if broken)
> Source: AddinEntry.cs:106-113
5. Detect RevitTest environment
> Source: AddinEntry.cs:116, 573-629
6. Register deferred UI startup handlers (ApplicationInitialized, Idling)
> Source: AddinEntry.cs:125-127
7. Execute startup task via ISafeExecutor.RunAsync:
a. Try binding global window owner (may be deferred)
b. Initialize DialogGuardianHook
c. Initialize RevitTaskService (if not RevitTest)
d. Attach DbtHookHost (if not RevitTest)
e. Initialize TestApiHost (if not RevitTest)
> Source: AddinEntry.cs:133-178
8. Create ribbon synchronously (Revit API requirement):
a. Get Flags settings
b. Create DbtRibbonComposer
c. Call Compose() with registry and flags
d. Publish warning changes
> Source: AddinEntry.cs:217-244
9. Return Result.Succeeded
> Source: AddinEntry.cs:246
Deferred UI Startup
Certain operations run after ApplicationInitialized/Idling to ensure Revit is fully ready:
private static Task RunDeferredUiStartupAsync(...)
{
return executor.RunAsync(async () =>
{
// 1. Ensure global window owner is bound
await EnsureGlobalWindowOwnerBoundAsync(logger);
// 2. Apply ribbon special effects (visual styling)
await RibbonSpecialEffects.ApplyAsync(logger);
// 3. Show logger window if debug mode enabled
loggerWindowManager.ShowIfDebugEnabled();
}, ...);
}
Source:
src/DBTools.App/Addin/AddinEntry.cs:421-479
OnShutdown Sequence
1. Wait for startup task completion (5s timeout)
> Source: AddinEntry.cs:265-274
2. Unregister deferred UI handlers
> Source: AddinEntry.cs:276
3. Detach DbtHookHost
> Source: AddinEntry.cs:278
4. Shutdown DialogGuardianHook
> Source: AddinEntry.cs:281
5. Shutdown TestApiHost
> Source: AddinEntry.cs:284
6. Dispose RevitTaskService
> Source: AddinEntry.cs:287
7. Dispose DbtRibbonComposer
> Source: AddinEntry.cs:292
8. Stop hosted services
> Source: AddinEntry.cs:303
9. Dispose logging host
> Source: AddinEntry.cs:306
Source:
src/DBTools.App/Addin/AddinEntry.cs:250-325
File Linking Strategy
DBTools.App compiles tool source code via MSBuild file linking. Source files remain in their respective src/Tools/ directories but are compiled into the single DBTools.dll assembly.
Source File Linking
<ItemGroup Label="Tool Source Files">
<Compile Include="..\Tools\**\*.cs"
Exclude="..\Tools\**\Tests\**\*.cs;..\Tools\**\obj\**\*.cs"
Link="Tools\%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
Source:
src/DBTools.App/DBTools.App.csproj:63-67
XAML File Linking
<ItemGroup Label="Tool XAML Files">
<Page Include="..\Tools\**\*.xaml"
Exclude="..\Tools\**\obj\**\*.xaml;..\Tools\**\Properties\DesignTimeResources.xaml"
Link="Tools\%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
Source:
src/DBTools.App/DBTools.App.csproj:69-73
Tool Assets (Embedded Icons)
<ItemGroup Label="Tool Embedded Assets">
<EmbeddedResource Include="..\Tools\**\Assets\*.png"
Link="Resources\Icons\%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
Source:
src/DBTools.App/DBTools.App.csproj:75-78
Tool Manifests (Embedded YAML)
<ItemGroup>
<EmbeddedResource Include="manifest.yml" LogicalName="DBTools.ToolManifests.DBTools.AppHooks.yml" />
<EmbeddedResource Include="..\Tools\**\manifest.yml"
LogicalName="DBTools.ToolManifests.%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
Source:
src/DBTools.App/DBTools.App.csproj:218-222
Why File Linking?
- Single assembly deployment - Reduces complexity and potential conflicts
- IDE organization - Tools can have separate projects for development
- Isolated testing - Test projects reference tool projects directly
- XAML designer support - Individual projects can have design-time resources
Tool Module Discovery
Tools are discovered via embedded YAML manifests during DbtServiceBootstrapper.Build():
var rootAssembly = typeof(DbtServiceBootstrapper).Assembly;
var discovery = DbtToolModuleCatalog.Discover(rootAssembly);
foreach (var entry in discovery.Entries)
{
var module = entry.Module;
module.RegisterSettings(services, configuration, entry.Manifest);
module.RegisterServices(services, entry.Manifest);
module.RegisterSettingsPacks(services, entry.Manifest);
module.RegisterHooks(registry, entry.Manifest);
RegisterRibbonToolsFromManifest(registry, rootAssembly, entry.Manifest);
}
Source:
src/DBTools.App/Bootstrap/DbtServiceBootstrapper.cs:194-237
Manifest Structure
Example tool manifest (manifest.yml):
id: DBTools.GM
assembly: DBTools
moduleType: DBTools.GM.GmToolModule
order: 0
sandboxWindows:
- id: DBTools.GM.Main
displayName: "Global Mapper"
windowType: "DBTools.GM.Shell.UI.Views.GmWindow"
tool:
ribbonTools:
- internalName: DBTools.GM
commandType: DBTools.GM.Features.GmCommand
availabilityType: DBTools.App.Tools.Availability.DbtDocumentAvailability
runProfile: InlineUi
displayText: "Global Mapper"
iconBaseKey: gm
tooltip: "Open Global Mapper"
controlKind: PushButton
order: 30
Source:
src/Tools/Common/GM/manifest.yml:1-27
Dependencies
Project References
| Project | Purpose |
|---|---|
DBTools.Core |
Core infrastructure and abstractions |
DBTools.Themes |
WPF theme resources |
Source:
src/DBTools.App/DBTools.App.csproj:57-59
NuGet Packages
| Package | Purpose |
|---|---|
Microsoft.Extensions.DependencyInjection |
DI container |
Microsoft.Extensions.Options.ConfigurationExtensions |
Options pattern |
Microsoft.Extensions.Configuration.* |
Configuration binding |
ricaun.Revit.UI |
Ribbon utilities |
ricaun.Revit.UI.Tasks |
RevitTask for async |
CommunityToolkit.Mvvm |
MVVM for tools |
JsonDiffPatch.Net |
JSON diff (tools) |
AutoMapper |
Object mapping (tools) |
HelixToolkit.Wpf.SharpDX |
3D visualization (tools) |
Source:
src/DBTools.App/DBTools.App.csproj:27-87
Revit API References
net48:
<Reference Include="RevitAPI">
<HintPath>$(REVIT2024_DIR)\RevitAPI.dll</HintPath>
<Private>false</Private>
</Reference>
Source:
src/DBTools.App/DBTools.App.csproj:114-134
net8.0-windows:
<Reference Include="RevitAPI" Condition="'$(REVIT_NET8_DIR)'!=''">
<HintPath>$(REVIT_NET8_DIR)\RevitAPI.dll</HintPath>
<Private>false</Private>
</Reference>
Source:
src/DBTools.App/DBTools.App.csproj:143-165
Assembly Embedding
All CopyLocal dependencies (except forbidden host assemblies) are embedded as resources for single-DLL deployment:
<Target Name="DBT_EmbedCopyLocalAssemblies" AfterTargets="ResolveReferences">
<ItemGroup>
<_EmbedCandidate Include="@(ReferenceCopyLocalPaths)" ... />
<!-- Exclude Revit host assemblies -->
<_EmbedCandidate Remove="..." Condition="'%(Filename)%(Extension)' == 'RevitAPI.dll'" />
<!-- Exclude WPF theme assemblies (need file Location for pack:// URIs) -->
<_EmbedCandidate Remove="..." Condition="$([System.String]::Copy('%(Filename)').StartsWith('DBTools.Themes'))" />
</ItemGroup>
<EmbeddedResource Include="%(_EmbedLogicalDistinct.SourcePath)"
LogicalName="DBTools.EmbeddedAssemblies.%(Name).dll" />
</Target>
Source:
src/DBTools.App/DBTools.App.csproj:234-270
Forbidden Host Assemblies
These assemblies must never be in the output (Revit provides them):
<ItemGroup>
<ForbiddenHostAssembly Include="RevitAPI.dll" />
<ForbiddenHostAssembly Include="RevitAPIUI.dll" />
<ForbiddenHostAssembly Include="AdWindows.dll" />
<ForbiddenHostAssembly Include="UIFramework.dll" />
<ForbiddenHostAssembly Include="Newtonsoft.Json.dll" />
</ItemGroup>
Source:
src/DBTools.App/DBTools.App.csproj:169-177
Build Configuration
Project Properties
<PropertyGroup>
<TargetFrameworks>$(DBT_RevitTargetFrameworks)</TargetFrameworks>
<AssemblyName>DBTools</AssemblyName>
<RootNamespace>DBTools.App</RootNamespace>
<UseWPF>true</UseWPF>
<ILRepackEnabled>false</ILRepackEnabled>
</PropertyGroup>
Source:
src/DBTools.App/DBTools.App.csproj:2-13
InternalsVisibleTo
Test assemblies can access internal types:
<ItemGroup>
<InternalsVisibleTo Include="DBTools.GM.Tests" />
<InternalsVisibleTo Include="DBTools.SGT.Tests" />
<InternalsVisibleTo Include="DBTools.TDV.Tests" />
<InternalsVisibleTo Include="DBTools.Testing.Tests" />
</ItemGroup>
Source:
src/DBTools.App/DBTools.App.csproj:15-20
Warning Suppressions
Tool code suppressions consolidated from individual tool projects:
<NoWarn>$(NoWarn);CS0618;CS0649;CS8600;CS8602;CS8603;CS8604;CS8619;CS8620;
MA0038;MA0051;MA0048;MA0016;MA0098;MA0004;MA0008;MA0015;
CA1068;CA1707;CA1716;CA1720;CA1722;CA1725;CA1822</NoWarn>
Source:
src/DBTools.App/DBTools.App.csproj:136-138
File Structure
src/DBTools.App/
+-- DBTools.App.csproj
+-- manifest.yml # AppHooks module manifest
+-- GlobalUsings.cs
+-- GlobalSuppressions.cs
+-- AssemblyInfo.cs
+-- Addin/
| +-- AddinEntry.cs # IExternalApplication entry point
| +-- TestApiHost.cs # Test harness API host
+-- Bootstrap/
| +-- AppRuntimeFactory.cs # Creates DiAppRuntime
| +-- DiAppRuntime.cs # IAppRuntime implementation
| +-- DbtServiceBootstrapper.cs # DI container builder
| +-- Startup.cs # Legacy startup helper
+-- Features/
| +-- Hooks/
| | +-- AppHookModule.cs # Application-level hooks
| | +-- ViewActivatedHookHandler.cs
| +-- Ribbon/
| +-- DbtRibbonComposer.cs # Ribbon composition
| +-- RibbonDefinition.cs # Tab/panel constants
| +-- RibbonRegistry.cs # Runtime button registry
| +-- RibbonSettingsListener.cs
| +-- RibbonSpecialEffects.cs
| +-- RevitRibbonBuilder.cs
+-- Tools/
| +-- Availability/
| +-- DbtDocumentAvailability.cs
| +-- DbtSelectionAvailability.cs
| +-- DbtActiveViewAvailability.cs
+-- Resources/
+-- (Ribbon icons - embedded resources)
RevitTest Environment Detection
AddinEntry detects when running under ricaun.RevitTest and adjusts behavior:
private static bool DetectRevitTestEnvironment(UIControlledApplication application, ILogger logger)
{
bool hostBoundToRevitTest = RevitTaskAccessor.RevitTask != null;
bool hasRevitTestAssembly = AppDomain.CurrentDomain.GetAssemblies()
.Any(a => a.GetName().Name == "ricaun.RevitTest.Application" ||
a.GetName().Name == "ricaun.RevitTest");
bool isRevitTestFlag = RevitExecutionContext.IsRevitTest;
return hostBoundToRevitTest || hasRevitTestAssembly || isRevitTestFlag;
}
Source:
src/DBTools.App/Addin/AddinEntry.cs:573-629
Skipped in RevitTest:
- RevitTaskService initialization (test host provides its own)
- DbtHookHost attachment
- TestApiHost initialization
Error Handling
Startup Errors
Fatal errors during startup show a message box and return Result.Failed:
private static void TryShowStartupError(string message)
{
// Try WPF MessageBox first
MessageBox.Show(message, "DB Tools", MessageBoxButton.OK, MessageBoxImage.Error, ...);
// Fall back to Win32 MessageBoxW if WPF fails
MessageBoxW(IntPtr.Zero, text, caption, MB_OK | MB_ICONERROR);
}
Source:
src/DBTools.App/Addin/AddinEntry.cs:481-535
Theme Validation
Theme validation is mandatory - if it fails, startup aborts:
try
{
DbtThemeValidator.ValidateOrThrow();
}
catch (Exception ex)
{
logger.LogError(ex, "[AddinEntry] Theme validation failed; aborting add-in startup.");
TryShowStartupError($"DB Tools theme failed to load:\n\n{ex.GetBaseException().Message}");
return Result.Failed;
}
Source:
src/DBTools.App/Addin/AddinEntry.cs:104-113
Troubleshooting
"Theme validation failed" Error
Cause: WPF theme assemblies (DBTools.Themes, DBTools.HandyControl) not found.
Solution:
- Ensure
%APPDATA%/DBTools/vendor/contains theme assemblies - Or rebuild with
bash build.sh --clean BuildAll
Ribbon Not Appearing
Possible Causes:
- Tool manifests not embedded (check build output)
- Tool command type not found (check namespace/assembly in manifest)
- Availability type resolution failed (check availabilityType in manifest)
Diagnosis: Enable debug mode and check log file for errors during Compose().
Tools Disabled Unexpectedly
Check:
- Availability predicate in manifest.yml
- Flags settings (some tools check
flags.EnableTesting) IExternalCommandAvailabilityimplementation returning false
Related Documentation
- Architecture Overview - High-level system architecture
- Project References - How projects relate
- DBTools.Loader - Bootstrap assembly that loads DBTools.App
- DBTools.Core - Core infrastructure library
Source Files Reviewed
| File | Purpose |
|---|---|
src/DBTools.App/DBTools.App.csproj |
Project configuration |
src/DBTools.App/Addin/AddinEntry.cs |
Application entry point |
src/DBTools.App/Addin/TestApiHost.cs |
Test harness API |
src/DBTools.App/Bootstrap/AppRuntimeFactory.cs |
Runtime factory |
src/DBTools.App/Bootstrap/DiAppRuntime.cs |
DI-based runtime |
src/DBTools.App/Bootstrap/DbtServiceBootstrapper.cs |
DI container builder |
src/DBTools.App/Bootstrap/Startup.cs |
Legacy startup helper |
src/DBTools.App/Features/Ribbon/DbtRibbonComposer.cs |
Ribbon composition |
src/DBTools.App/Features/Ribbon/RibbonDefinition.cs |
Ribbon constants |
src/DBTools.App/Features/Hooks/AppHookModule.cs |
Application hooks |
src/DBTools.App/Tools/Availability/DbtDocumentAvailability.cs |
Document availability |
src/DBTools.App/Tools/Availability/DbtSelectionAvailability.cs |
Selection availability |
src/DBTools.App/manifest.yml |
AppHooks manifest |
src/Tools/Common/GM/manifest.yml |
Example tool manifest |
src/DBTools.Core/Tools/DbtHookHost.cs |
Hook coordination (Core) |