この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:6
ページ更新者:T
更新日時:2026-06-11 07:10:02

タイトル: エラーメッセージの設定方法
SEOタイトル: Revit API エラーメッセージ表示完全ガイド (TaskDialog/Exceptions)

この記事の要点
  • Revit API でユーザにメッセージを出すには Autodesk.Revit.UI.TaskDialog を使うのが標準。ボタンや詳細テキスト、リンクも追加可能
  • System.Windows.Forms.MessageBox も使えるが、Revit の UI スレッドや DPI と齟齬が出やすく非推奨
  • エラー処理は try / catchAutodesk.Revit.Exceptions.* を捕捉 → TaskDialog でユーザ通知 + ログ出力
  • FailureMessage / FailureDefinition を使うと Revit ネイティブの警告ダイアログ (Show/Resolve) に統合でき、ジオメトリ検証等で推奨
  • デバッグログは System.Diagnostics.Debug.WriteLine + DebugView、または NLog / log4net でファイル出力

Revit API でメッセージを出す主な方法

方法用途推奨度
TaskDialog.Showシンプルな OK/Cancel 通知★★★ 最推奨
TaskDialog インスタンス詳細テキスト、複数ボタン、リンク付き★★★
FailureMessage / FailureDefinitionジオメトリ検証など Revit ネイティブ警告に統合★★★ ジオメトリ系
System.Windows.Forms.MessageBoxWinForms 互換★ 非推奨 (UI 統合悪)
WPF Window / Dialogカスタム UI 必要時★★ 中
Debug.WriteLine / ログファイル開発者向けデバッグ情報★★★ 並行使用

TaskDialog.Show (最も簡単)

using Autodesk.Revit.UI;

// 最小: タイトルとメッセージ
TaskDialog.Show("情報", "処理が完了しました。");

// 戻り値で OK/Cancel 判定
var res = TaskDialog.Show(
    "確認",
    "選択した要素を削除しますか?",
    TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No,
    TaskDialogResult.No);

if (res == TaskDialogResult.Yes) {
    // 削除処理
}

TaskDialog インスタンス (詳細情報、リンク、複数ボタン)

using Autodesk.Revit.UI;

var td = new TaskDialog("ジオメトリ検証エラー") {
    MainInstruction      = "壁が他の要素と干渉しています",
    MainContent          = "Wall ID: 12345 が、Floor ID: 6789 と干渉します。\n" +
                           "この状態では IFC エクスポートが失敗する可能性があります。",
    ExpandedContent      = "詳細:\n" +
                           "  - 干渉体積: 0.45 m^3\n" +
                           "  - 干渉箇所: (12.5, 8.3, 0.0) - (13.2, 8.7, 3.0)",
    FooterText           = "<a href=\"https://help.example.com/clash\">解決方法</a>",
    TitleAutoPrefix      = false,
    AllowCancellation    = true,
    CommonButtons        = TaskDialogCommonButtons.Close,
    DefaultButton        = TaskDialogResult.Close,
};
td.AddCommandLink(TaskDialogCommandLinkId.CommandLink1, "Wall を移動", "干渉が解消される位置に移動します");
td.AddCommandLink(TaskDialogCommandLinkId.CommandLink2, "そのまま続行", "警告を無視して処理を続行します");

var result = td.Show();
switch (result) {
    case TaskDialogResult.CommandLink1: MoveWall(); break;
    case TaskDialogResult.CommandLink2: ContinueAnyway(); break;
}

Exception を捕捉してユーザ通知

Revit API の例外は Autodesk.Revit.Exceptions 名前空間に定義されています:

using Autodesk.Revit.UI;
using ARExc = Autodesk.Revit.Exceptions;
using System.Diagnostics;

public Result Execute(ExternalCommandData cmd, ref string msg, ElementSet elems) {
    UIApplication uiapp = cmd.Application;
    Document doc = uiapp.ActiveUIDocument.Document;

    try {
        using (var tx = new Transaction(doc, "Add Wall")) {
            tx.Start();
            // ... API 呼び出し ...
            tx.Commit();
        }
        TaskDialog.Show("完了", "壁を追加しました。");
        return Result.Succeeded;

    } catch (ARExc.InvalidOperationException ex) {
        // トランザクション外での編集など
        msg = "無効な操作: " + ex.Message;
        ShowError("操作エラー", ex);
        return Result.Failed;

    } catch (ARExc.ArgumentException ex) {
        // 引数違反
        msg = "引数エラー: " + ex.Message;
        ShowError("引数エラー", ex);
        return Result.Failed;

    } catch (ARExc.OperationCanceledException) {
        // ユーザがキャンセル → 通知不要
        return Result.Cancelled;

    } catch (System.Exception ex) {
        msg = "予期せぬエラー: " + ex.Message;
        ShowError("システムエラー", ex);
        Debug.WriteLine(ex.ToString());
        return Result.Failed;
    }
}

private void ShowError(string title, System.Exception ex) {
    var td = new TaskDialog(title) {
        MainInstruction = ex.Message,
        MainContent     = "詳細はログを確認してください。",
        ExpandedContent = ex.ToString(),
        CommonButtons   = TaskDialogCommonButtons.Close,
    };
    td.Show();
}

FailureMessage / FailureDefinition (Revit ネイティブ警告に統合)

Revit には独自の警告フレームワークがあり、トランザクション中に FailureMessage を発行すると、Revit 標準の警告ダイアログ (Show / Resolve / Cancel) に統合表示されます。複数警告がまとめて出る、Resolve 操作が選べる、エクスポート時に再表示できる等のメリットあり。

using Autodesk.Revit.DB;

// 1. FailureDefinition の登録 (アプリ起動時に 1 回)
public class App : IExternalApplication {
    public static FailureDefinitionId WallClashFailureId;

    public Result OnStartup(UIControlledApplication app) {
        Guid guid = new Guid("12345678-1234-1234-1234-123456789012");
        WallClashFailureId = new FailureDefinitionId(guid);

        FailureDefinition.CreateFailureDefinition(
            WallClashFailureId,
            FailureSeverity.Warning,
            "壁が他の要素と干渉しています。");
        return Result.Succeeded;
    }
    public Result OnShutdown(UIControlledApplication app) => Result.Succeeded;
}

// 2. トランザクション中に発行
using (var tx = new Transaction(doc, "Check Wall")) {
    tx.Start();
    // ... 検証ロジック ...
    if (clash) {
        var fm = new FailureMessage(App.WallClashFailureId);
        fm.SetFailingElement(wall.Id);
        doc.PostFailure(fm);
    }
    tx.Commit();   // ★ コミット時に Revit が警告ダイアログ表示
}

System.Windows.Forms.MessageBox (旧式)

WinForms から移植した既存コードでは使われがちですが、Revit 2024+ では DPI スケーリング不整合UI スレッド競合モーダル親ウィンドウ未指定等の問題が発生しやすいので、新規コードでは TaskDialog を使うべきです。

using System.Windows.Forms;

// 旧式: 親ウィンドウを指定して使う必要あり
var owner = new WindowWrapper(uiapp.MainWindowHandle);  // System.Windows.Forms.IWin32Window
MessageBox.Show(owner, "メッセージ", "タイトル",
    MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);

// IWin32Window ラッパー
public class WindowWrapper : System.Windows.Forms.IWin32Window {
    private readonly IntPtr _handle;
    public WindowWrapper(IntPtr handle) { _handle = handle; }
    public IntPtr Handle => _handle;
}

デバッグログの出力

using System.Diagnostics;
using System.IO;

// 1. Debug.WriteLine (デバッガ または DebugView で確認)
Debug.WriteLine("[MyAddin] Wall created: " + wall.Id);

// 2. ファイルログ (自前)
string logPath = Path.Combine(
    Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
    "MyAddin", "log.txt");
Directory.CreateDirectory(Path.GetDirectoryName(logPath));
File.AppendAllText(logPath,
    $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}{Environment.NewLine}");

// 3. NLog (NuGet) - 推奨
private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger();
Log.Info("Wall created: {WallId}", wall.Id);
Log.Error(ex, "Failed to create wall");

エラー / 警告 / 情報の使い分け

種類UI使うべき場面
情報 (Info)TaskDialog (アイコン無し or 情報)処理完了、件数報告
警告 (Warning)TaskDialog Warning / FailureSeverity.Warning続行可能だが注意点あり
エラー (Error)TaskDialog Error / FailureSeverity.Error続行不可、ユーザ対応必要
重大 (Critical)TaskDialog + ログ + 上位コミット中止データ破損リスク
キャンセル通知なしで Result.Cancelled 返却ユーザの明示的中止

Revit 2024+ の新 UI

Revit 2024 以降、TaskDialog 自体は変わりませんが、ダーク モード対応、DPI 改善リボン UI のリフレッシュが行われました。自前 WPF ウィンドウを使う場合はThemeManager でダークテーマ追従が推奨されます。

よくある落とし穴

症状原因対処
TaskDialog が Revit の裏に出る親ウィンドウ未指定TaskDialog の場合は基本不要。WPF の場合は WindowInteropHelper で親 HWND 指定
例外が握り潰されるcatch せず IExternalCommand から Result.Succeeded 返却必ず try/catch + Result.Failed
トランザクション中に MessageBoxUI スレッドブロックFailureMessage を使う
多発するエラーで OK 連打地獄ループ内で TaskDialog件数集約してから 1 度だけ表示

FAQ

Q: 非同期処理から TaskDialog を呼びたい
A: Revit API はUI スレッドからしか操作できませんUIApplication.Idling イベントや ExternalEvent 経由でメインスレッドに戻して呼んでください。

Q: TaskDialog にチェックボックス「次回から表示しない」を入れたい
A: VerificationText プロパティをセット、表示後 WasVerificationChecked で取得。値は自前で永続化 (User Settings 等)。

Q: ログを Revit のジャーナルファイルに出したい
A: ジャーナルは Revit 専用なので直接書込み非推奨。自前ログを別途出力するのが標準です。

Q: 多言語化したい
A: メッセージリソース (.resx) を用意し、Application.Language から現在の言語を取得して切替えるのが定番です。