10.

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 から現在の言語を取得して切替えるのが定番です。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. RevitAPI.dll と RevitAPIUI.dll の参照
  2. マニフェストファイルの書き方
  3. アドインの追加/設置方法
  4. アドインの作成サンプル(外部ツール編)
  5. アドインの作成サンプル(外部アプリケーション編)
  6. 要素の取得と情報の表示
  7. 要素のカテゴリとマテリアルの取得と表示
  8. よく使うBuiltInCategoryの一覧
  9. 外部ツールでAutodesk.Revit.Documentを取得する方法
  10. エラーメッセージの設定方法
  11. 「はい」、「いいえ」、「キャンセル」ボタンの設置と処理分岐
  12. 要素(カテゴリ、ファミリ、タイプ)とは
  13. ElementIdとUniqueIdの違い
  14. 要素フィルターの使い方
  15. 要素のパラメータ一覧の取得
  16. pyRevitの導入と簡単なアプリケーションの作成
  17. Revit SDKのサンプルの場所とビルド方法
  18. FamilySymbol(タイプ)の取得とパラメータの変更
  19. 相対パスでdllにアイコン画像を埋め込む方法
  20. 「グループ」について

最近更新/作成されたページ