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

AutoCAD C# API中CommandWillStart事件无响应问题求助

AutoCAD C#二次开发:CommandWillStart事件无响应问题排查

问题场景

在AutoCAD C#二次开发中,试图通过CommandWillStart事件监听命令行输入:当输入的命令与JSON配置中的TPX/TP1匹配时,调用GetDistanceBetweenTwoPoints()方法,且不使用[CommandMethod]特性注册命令,但目前事件处理无响应。

现有代码与配置

C#代码

using System;
using System.Collections.Generic;
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Newtonsoft.Json;

namespace Autocad_SetShortcutKey_005
{
public class CommandConfig
{
public string Name { get; set; }
public string Subname { get; set; }
public string Method { get; set; }
}

    public class CommandMappings
    {
        public List<CommandConfig> Commands { get; set; }
    }
    
    public class SetShortcutKeyClass : IExtensionApplication
    {
        private Dictionary<string, Action> commandDictionary;
        Document doc;
        Editor ed;
    
        public SetShortcutKeyClass()
        {
            doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            ed = doc.Editor;
        }
        public void Initialize()
        {
            // Load commands from JSON
            LoadCommands();
    
            // Register for the CommandWillStart event
           
            doc.CommandWillStart += new CommandEventHandler(OnCommandWillStart);
            
        }
    
        public void Terminate()
        {
            // Unsubscribe from the CommandWillStart event
    
            doc.CommandWillStart += new CommandEventHandler(OnCommandWillStart);
            
        }
    
        private void LoadCommands()
        {
            commandDictionary = new Dictionary<string, Action>();
    
            // Read JSON file
            string jsonFilePath = "commands.json";
            if (File.Exists(jsonFilePath))
            {
                
                string jsonContent = File.ReadAllText(jsonFilePath);
                var commandMappings = JsonConvert.DeserializeObject<CommandMappings>(jsonContent);
    
                foreach (var commandConfig in commandMappings.Commands)
                {
                    if (commandConfig.Method == nameof(GetDistanceBetweenTwoPoints))
                    {
                        commandDictionary[commandConfig.Name.ToUpper()] = GetDistanceBetweenTwoPoints;
                        commandDictionary[commandConfig.Subname.ToUpper()] = GetDistanceBetweenTwoPoints;
                    }
                }
            }
            else
            {
                ed.WriteMessage("\n No Json file.");
                return;
            }
        }
    
        private void OnCommandWillStart(object sender, CommandEventArgs e)
        {
            
            string commandName = e.GlobalCommandName.ToUpper();
            
            if (commandDictionary.ContainsKey(commandName))
            {
                
              
                // Execute the custom method
                commandDictionary[commandName].Invoke();
                return;
            }
        }
    
        public  void GetDistanceBetweenTwoPoints()
        {
            PromptPointOptions ppo1 = new PromptPointOptions("\nPick the first point: ");
            PromptPointResult ppr1 = ed.GetPoint(ppo1);
            if (ppr1.Status != PromptStatus.OK) return;
    
            PromptPointOptions ppo2 = new PromptPointOptions("\nPick the second point: ");
            PromptPointResult ppr2 = ed.GetPoint(ppo2);
            if (ppr2.Status != PromptStatus.OK) return;
    
            double distance = ppr1.Value.DistanceTo(ppr2.Value);
            Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog($"\nDistance between points: {distance}");
        }
    }

}

commands.json配置

{
"commands": [
{
"name": "TPX",
"subname": "TP1",
"method": "GetDistanceBetweenTwoPoints"
}
]
}

问题排查与修复方案

1. 文档对象初始化时机错误

原代码在构造函数中获取MdiActiveDocument,此时AutoCAD扩展应用刚启动,可能还没有激活的文档,导致doc为null,后续事件绑定完全失效。

  • 修复:将文档获取逻辑移到Initialize()方法内,同时增加文档未打开时的兼容处理:
public void Initialize()
{
    doc = Application.DocumentManager.MdiActiveDocument;
    if (doc == null)
    {
        Application.DocumentManager.DocumentCreated += OnDocumentCreated;
        return;
    }
    ed = doc.Editor;
    LoadCommands();
    doc.CommandWillStart += OnCommandWillStart;
}

private void OnDocumentCreated(object sender, DocumentCollectionEventArgs e)
{
    doc = e.Document;
    ed = doc.Editor;
    LoadCommands();
    doc.CommandWillStart += OnCommandWillStart;
    Application.DocumentManager.DocumentCreated -= OnDocumentCreated;
}

2. 事件注销逻辑错误

原Terminate()方法中用+=再次订阅事件,正确的注销方式应该是-=,同时需要保留事件处理器的引用避免匿名委托无法注销:

private CommandEventHandler _commandHandler;

public void Initialize()
{
    // ...其他代码
    _commandHandler = new CommandEventHandler(OnCommandWillStart);
    doc.CommandWillStart += _commandHandler;
}

public void Terminate()
{
    if (doc != null && _commandHandler != null)
    {
        doc.CommandWillStart -= _commandHandler;
    }
    Application.DocumentManager.DocumentCreated -= OnDocumentCreated;
}

3. JSON文件路径问题

原代码使用相对路径"commands.json",AutoCAD的工作目录默认不是程序集所在目录,会导致找不到配置文件。

  • 修复:通过程序集路径拼接绝对路径:
string assemblyPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string jsonFilePath = Path.Combine(assemblyPath, "commands.json");

4. CommandWillStart事件的局限性

CommandWillStart仅触发已注册的合法命令(AutoCAD原生命令或通过[CommandMethod]注册的自定义命令),未注册的TPX/TP1会被AutoCAD直接判定为未知命令,不会触发该事件。

  • 修复:新增监听Editor.CommandInput事件,直接捕获命令行输入并拦截未注册命令:
public void Initialize()
{
    // ...其他代码
    doc.Editor.CommandInput += OnCommandInput;
}

private void OnCommandInput(object sender, CommandInputEventArgs e)
{
    string input = e.Input.ToUpper().Trim();
    if (commandDictionary.ContainsKey(input))
    {
        e.Handled = true;
        e.AppendCommand = false;
        commandDictionary[input].Invoke();
    }
}

public void Terminate()
{
    // ...其他代码
    doc.Editor.CommandInput -= OnCommandInput;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 21:27:01