You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Revit中IUpdater引发同步警告问题求助:是否未正确注销?

问题分析与解决方法

问题背景

开发了一款基于IUpdater接口的Revit插件,启动时注册UpdaterFloorsROofsWalls,关闭时尝试注销,但未安装插件的机器同步项目时出现警告:

you are trying to synchronize was modified by the third-party updater Unknown : Element Updater which is not currently installed.
(您尝试同步的内容已被未安装的第三方更新器Unknown:Element Updater修改)

需确认问题是否由未正确注销IUpdater引发,并找到解决方法。

插件关键代码

启动时注册Updater

public Result OnStartup(UIControlledApplication a)
{
    UpdaterFloorsROofsWalls elementUpdater = new UpdaterFloorsROofsWalls(a.ActiveAddInId);
    UpdaterRegistry.RegisterUpdater(elementUpdater);

    return Result.Succeeded;
}

关闭时注销Updater

public Result OnShutdown(UIControlledApplication a)
{
    // IUpdater is required to be Unregistered on shut down
    UpdaterFloorsROofsWalls elementUpdater = new UpdaterFloorsROofsWalls(a.ActiveAddInId);
    UpdaterRegistry.UnregisterUpdater(elementUpdater.GetUpdaterId());

    return Result.Succeeded;
}

IUpdater类定义

using Autodesk.Revit.DB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WarningViewer
{
    internal class UpdaterFloorsROofsWalls : IUpdater
    {
        static AddInId m_appId;
        static UpdaterId m_updaterId;

        public UpdaterFloorsROofsWalls (AddInId id){
            m_appId = id;
            m_updaterId = new UpdaterId(m_appId, new Guid("FBFBF6B2-4C06-42d4-97C1-D1B4EB593EFF"));
        }

        public void Execute(UpdaterData data)
        {
            try
            {
                Document doc = data.GetDocument();
                if (doc.ActiveView.Name == _Utilities.viewName)
                {
                    List<ElementId> failingElements = _Utilities.GetElementIdsOfFailingElements(doc);
                    _Utilities.ShowAllWarningsIn3dSub(failingElements, doc, doc.ActiveView);
                }
            } catch (Exception ex) 
            {
                MessageBox.Show(ex.Message);
            }
            
        }

        public string GetAdditionalInformation()
        {
            return "Updater for Floors Roofs and Walls";
        }

        public ChangePriority GetChangePriority()
        {
            return ChangePriority.FloorsRoofsStructuralWalls;
        }

        public UpdaterId GetUpdaterId()
        {
            return m_updaterId;
        }

        public string GetUpdaterName()
        {
            return "Element Updater";
        }
    }
}

问题原因确认

1. 注销逻辑的潜在问题

你的注销代码中,m_appId和m_updaterId是静态变量,虽然当前启动/关闭各实例化一次不会直接报错,但静态变量会导致多次实例化时覆盖原有值,存在潜在风险。不过这不是同步警告的直接原因。

2. 核心原因:模型中留存了Updater修改记录

Revit会在模型元素被IUpdater修改后,将该Updater的ID和名称记录在模型中。即使你在插件关闭时注销了Updater,已修改元素的记录依然存在。当未安装插件的机器同步项目时,Revit找不到对应的Updater,就会弹出警告。

另外,观察你的Execute方法,如果_Utilities.ShowAllWarningsIn3dSub只是显示警告、未修改模型,那你误用了IUpdater——IUpdater的设计目的是响应模型变更并修改模型,而非仅做UI展示,这种场景应该用DocumentChanged事件替代,避免在模型中留下Updater痕迹。

解决方法

方法一:修正插件的Updater实现与注销逻辑

  1. 将静态变量改为实例变量,避免静态共享带来的意外问题:
// 替换原静态变量
private readonly AddInId m_appId;
private readonly UpdaterId m_updaterId;

public UpdaterFloorsROofsWalls(AddInId id)
{
    m_appId = id;
    m_updaterId = new UpdaterId(m_appId, new Guid("FBFBF6B2-4C06-42d4-97C1-D1B4EB593EFF"));
}
  1. 简化注销逻辑,无需新建Updater实例,直接构造UpdaterId注销:
public Result OnShutdown(UIControlledApplication a)
{
    var updaterId = new UpdaterId(a.ActiveAddInId, new Guid("FBFBF6B2-4C06-42d4-97C1-D1B4EB593EFF"));
    UpdaterRegistry.UnregisterUpdater(updaterId);
    return Result.Succeeded;
}

方法二:清理模型中的Updater痕迹

如果模型中已经留存了该Updater的记录,可编写临时工具清理:

// 在文档可用的上下文(如外部命令)中执行
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
    var doc = commandData.Application.ActiveUIDocument.Document;
    var updaterId = new UpdaterId(commandData.Application.ActiveAddInId, new Guid("FBFBF6B2-4C06-42d4-97C1-D1B4EB593EFF"));
    
    using(var trans = new Transaction(doc, "Remove Updater Info"))
    {
        trans.Start();
        UpdaterRegistry.RemoveAllUpdaterInfoFromDocument(doc, updaterId);
        trans.Commit();
    }
    return Result.Succeeded;
}

运行此工具后,模型中该Updater的记录会被移除,未装插件的机器同步时就不会再弹出警告。

方法三:替换IUpdater为事件监听(仅UI展示场景)

如果你的插件只是显示警告、无需修改模型,完全不需要使用IUpdater,改用DocumentChanged事件监听模型变更,再执行UI展示逻辑:

public Result OnStartup(UIControlledApplication a)
{
    a.ControlledApplication.DocumentChanged += OnDocumentChanged;
    return Result.Succeeded;
}

public Result OnShutdown(UIControlledApplication a)
{
    a.ControlledApplication.DocumentChanged -= OnDocumentChanged;
    return Result.Succeeded;
}

private void OnDocumentChanged(object sender, DocumentChangedEventArgs e)
{
    var doc = e.GetDocument();
    if (doc.ActiveView.Name == _Utilities.viewName)
    {
        List<ElementId> failingElements = _Utilities.GetElementIdsOfFailingElements(doc);
        _Utilities.ShowAllWarningsIn3dSub(failingElements, doc, doc.ActiveView);
    }
}

这种方式不会在模型中留下任何第三方工具的记录,从根源避免同步警告。


内容的提问来源于stack exchange,提问作者Skinner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 08:45:26