代码之家  ›  专栏  ›  技术社区  ›  Andy Shellam

在COM悬挂式AutoCAD中另存为

  •  3
  • Andy Shellam  · 技术社区  · 15 年前

    我正在实现一个应用程序,它在AutoCAD的ObjectARX界面中使用COM来自动执行绘图操作,如打开和另存为。

    根据文档,我应该能够调用acaddocument.save as()并传递一个文件名、一个“另存为类型”和一个安全参数。文档明确声明,如果安全性为空,则不会尝试任何与安全相关的操作。但是,它并没有给出正确的对象类型的任何指示,以作为“另存为类型”参数传递。

    我尝试用文件名调用saveas,其余参数为空,但我的应用程序挂起了该方法调用,AutoCAD似乎崩溃了-您仍然可以使用功能区,但无法对工具栏执行任何操作,无法关闭AutoCAD。

    我有种感觉,这是我的空参数导致了这里的悲伤,但是COM/VBA部门严重缺乏文档。事实上,它说acaddocument类甚至没有一个saveas方法,它显然有这个方法。

    这里有人实施了同样的事情吗?有什么指导吗?

    另一种方法是,我使用send command()方法发送一个“另存为”命令,但我的应用程序正在管理一批绘图,需要知道a)如果保存失败,b)保存完成时(我通过监听endsave事件来执行此操作)。

    编辑

    以下是所需的代码-它所要做的就是启动AutoCAD(或者连接到正在运行的实例,如果它已经在运行),打开一个现有的图形,然后将文档保存到一个新的位置(c:\scratch\document01b.dwg)。

    using (AutoCad cad = AutoCad.Instance)
    {
        // Launch AutoCAD
        cad.Launch();
    
        // Open drawing
        cad.OpenDrawing(@"C:\Scratch\Drawing01.dwg");
    
        // Save it
        cad.SaveAs(@"C:\Scratch\Drawing01B.dwg");
    }
    

    然后在我的autocad类中(此.“acadddocument”是acadddocument类的一个实例。)

    public void Launch()
    {
        this._acadApplication = null;
        const string ProgramId = "AutoCAD.Application.18";
    
        try
        {
            // Connect to a running instance
            this._acadApplication = (AcadApplication)Marshal.GetActiveObject(ProgramId);
        }
        catch (COMException)
        {
            /* No instance running, launch one */
    
            try
            {
                this._acadApplication = (AcadApplication)Activator.CreateInstance(
                    Type.GetTypeFromProgID(ProgramId), 
                    true);
            }
            catch (COMException exception)
            {
                // Failed - is AutoCAD installed?
                throw new AutoCadNotFoundException(exception);
            }
        }
    
        /* Listen for the events we need and make the application visible */
        this._acadApplication.BeginOpen += this.OnAcadBeginOpen;
        this._acadApplication.BeginSave += this.OnAcadBeginSave;
        this._acadApplication.EndOpen += this.OnAcadEndOpen;
        this._acadApplication.EndSave += this.OnAcadEndSave;
    
    #if DEBUG
        this._acadApplication.Visible = true;
    #else
        this._acadApplication.Visible = false;
    #endif
    
        // Get the active document
        this._acadDocument = this._acadApplication.ActiveDocument;
    }
    
    public void OpenDrawing(string path)
    {
        // Request AutoCAD to open the document
        this._acadApplication.Documents.Open(path, false, null);
    
        // Update our reference to the new document
        this._acadDocument = this._acadApplication.ActiveDocument;
    }
    
    public void SaveAs(string fullPath)
    {
        this._acadDocument.SaveAs(fullPath, null, null);
    }
    
    4 回复  |  直到 9 年前
        2
  •  1
  •   t0mm13b    15 年前

    从连接到 AutoDesk 关于这个主题的论坛,听起来您需要在保存后关闭对象…并删除空值…如果我是您,我会将代码包装为 try / catch 要检查的块并确保没有异常被抛出!

    我不得不质疑using子句的用法,因为你 Launch 你是在复制另一本吗?即在 OpenDrawing Save 您正在使用的函数 this._acadApplication 还是我误解了?

    using (AutoCad cad = AutoCad.Instance)
    {
        try{
           // Launch AutoCAD
           cad.Launch();
    
           // Open drawing
           cad.OpenDrawing(@"C:\Scratch\Drawing01.dwg");
    
           // Save it
           cad.SaveAs(@"C:\Scratch\Drawing01B.dwg");
        }catch(COMException ex){
           // Handle the exception here
        }
    }
    
    public void Launch()
    {
        this._acadApplication = null;
        const string ProgramId = "AutoCAD.Application.18";
    
        try
        {
            // Connect to a running instance
            this._acadApplication = (AcadApplication)Marshal.GetActiveObject(ProgramId);
        }
        catch (COMException)
        {
            /* No instance running, launch one */
    
            try
            {
                this._acadApplication = (AcadApplication)Activator.CreateInstance(
                    Type.GetTypeFromProgID(ProgramId), 
                    true);
            }
            catch (COMException exception)
            {
                // Failed - is AutoCAD installed?
                throw new AutoCadNotFoundException(exception);
            }
        }
    
        /* Listen for the events we need and make the application visible */
        this._acadApplication.BeginOpen += this.OnAcadBeginOpen;
        this._acadApplication.BeginSave += this.OnAcadBeginSave;
        this._acadApplication.EndOpen += this.OnAcadEndOpen;
        this._acadApplication.EndSave += this.OnAcadEndSave;
    
    #if DEBUG
        this._acadApplication.Visible = true;
    #else
        this._acadApplication.Visible = false;
    #endif
    
        // Get the active document
        // this._acadDocument = this._acadApplication.ActiveDocument; 
        // Comment ^^^ out? as you're instantiating an ActiveDocument below when opening the drawing?
    }
    
    public void OpenDrawing(string path)
    {
        try{
           // Request AutoCAD to open the document
           this._acadApplication.Documents.Open(path, false, null);
    
           // Update our reference to the new document
           this._acadDocument = this._acadApplication.ActiveDocument;
        }catch(COMException ex){
           // Handle the exception here
        }
    }
    
    public void SaveAs(string fullPath)
    {
        try{
           this._acadDocument.SaveAs(fullPath, null, null);
        }catch(COMException ex){
           // Handle the exception here
        }finally{
           this._acadDocument.Close();
        }
    }
    

    我想我会为你提供一些链接。

    希望这有帮助, 最好的问候, 汤姆。

        3
  •  0
  •   Andy Shellam    15 年前

    我已经设法以一种非最优的、非常不完美的方式解决了这个问题,所以我仍然有兴趣知道是否有人知道为什么saveas方法会崩溃autocad并挂起我的应用程序。

    我是这样做的:

    打开文档或创建新文档时,关闭“打开/保存”对话框:

    this._acadDocument.SetVariable("FILEDIA", 0);
    

    保存文档时,发出以“2010”作为格式和文件名(fullpath)传递的\u saveas命令:

    string commandString = string.Format(
        "(command \"_SAVEAS\" \"{0}\" \"{1}\") ",
        "2010",
        fullPath.Replace('\\', '/'));
    
    this._acadDocument.SendCommand(commandString);
    

    退出AutoCAD“打开文件”对话框时,再次提示(可能不需要,但只需确保):

    this._acadDocument.SetVariable("FILEDIA", 1);
    
        4
  •  0
  •   Maxence    9 年前

    对于C和COM,当存在可选参数时,需要使用 Type.Missing 而不是空值:

    this._acadDocument.SaveAs(fullPath, Type.Missing, Type.Missing);
    

    但自Visual Studio 2010以来,您只需省略可选参数:

    this._acadDocument.SaveAs(fullPath);