2010-02-18 52 views
3

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

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

我试过使用文件名调用SaveAs,其余参数为null,但是我的应用程序挂在那个方法调用上,而AutoCAD似乎崩溃 - 您仍然可以使用功能区,但无法对工具栏执行任何操作无法关闭AutoCAD。

我有一种感觉,这是我的NULL参数导致悲伤在这里,但在COM/VBA部门严重缺乏文档。实际上它说AcadDocument类甚至没有SaveAs方法,这显然是。

有没有人在这里执行过同样的事情?任何指导?

另一种方法是使用SendCommand()方法发送_SAVEAS命令,但我的应用程序正在管理一批绘图,并需要知道a)如果保存失败,并且b)保存完成时(其中I “M通过听取EndSave事件做)

编辑

这里所要求的代码 - 所有它做的是推出的AutoCAD(或连接到正在运行的实例,如果它已经运行),打开现有绘图,然后将文档保存到新位置(C:\ Scratch \ Document01B.dwg。)

我的AutoCad类
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"); 
} 

然后(this._acadDocument是AcadDocument类的一个实例。)

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); 
} 
+0

你可以显示代码吗? – t0mm13b 2010-02-18 10:47:21

+0

@ tommieb75:已添加到问题 – 2010-02-18 11:14:20

回答

0

我已经设法解决这个非最佳,非常不完美的方式,所以我仍然有兴趣知道是否有人知道为什么SaveAs方法崩溃AutoCAD并挂起我的应用程序。

我是这样做的:

当打开一个文件或创建一个新的,关闭打开/保存对话框:

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

当保存文档时,发出_SAVEAS命令传递在“2010”的格式和文件名(FULLPATH):

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

this._acadDocument.SendCommand(commandString); 

当退出AutoCAD的转文件对话框提示回(可能是没有必要的,但只是确保):

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

@安迪:很高兴听到你解决它......奇怪的做法!甚至令人惊讶的是,文档没有通知!!!!?!!! WTF! :) – t0mm13b 2010-02-18 15:39:34

+0

是的文件需要大规模的检修。幸运的是,本地的.NET API具有出色的文档,但您只能在AutoCAD中使用它 - 而不是像我试图做的那样从外部应用程序中使用它。不管怎么说,还是要谢谢你。 – 2010-02-18 16:54:50

1

由链路判断到AutoDesk的论坛上关于这个主题,这听起来像你需要在保存后关闭对象...并删除null ...如果我是你,我会将代码合并到try/catch块中检查并确保没有抛出异常!

我不得不质疑using子句的用法,因为你是Launch另一个副本不是你吗?即在您使用的OpenDrawingSave函数内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(); 
    } 
} 

以为我会包含一些链接以供您参考。

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

+0

谢谢你尝试汤姆。没有例外 - 该应用程序挂在AutoCAD的AcadDocument.SaveAs方法 - 它甚至挂起AutoCAD不只是我的应用程序。我不能删除NULL,因为SaveAs方法需要3个参数,但没有文档告诉我要通过其他2个参数。我也无法关闭绘图,因为一旦保存,我需要继续使用它。 – 2010-02-18 14:38:58

+0

否我并未启动AutoCAD的另一个副本,Launch()方法中的代码使用已在运行的实例(然后由_acadApplication引用该实例)。启动AutoCAD时,它会创建一个空白文档,您需要能够发送AutoCAD命令,因此您的注释行是我的应用程序所必需的。当调用Documents.Open()时,它会创建一个新文档,然后我的应用程序将引用该文档而不是初始空白文档。 – 2010-02-18 14:39:23

+0

@安迪:这很有趣,在我提供的链接中,有一个保存参数?!除非最新发布的AutoCAD的COM已经更改 - 您使用的是什么版本的AutoCAD? – t0mm13b 2010-02-18 15:02:45

2

从Autodesk discussion groups,它看起来像第二个参数是保存作为类型,并且可能需要:

app = new AcadApplicationClass();
AcadDocument doc = app.ActiveDocument; doc.SaveAs("d:\Sam.dwg",AcSaveAsType.acR15_dwg,new Autodesk.AutoCAD.DatabaseServices.SecurityParameters());

既然你在AutoCAD 2010中,该类型应该是递增到acR17_dwg或acR18_dwg。

0

在C#和COM,当有可选的参数,你需要使用Type.Missing而不是空的:

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

但由于Visual Studio 2010中,你可以简单地忽略可选参数:

this._acadDocument.SaveAs(fullPath);