3

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

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

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

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

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

另一种方法是我使用 SendCommand() 方法发送 _SAVEAS 命令,但我的应用程序正在管理一批绘图并且需要知道 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 类中(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);
}
4

4 回答 4

2

从 Autodesk讨论组中,看起来第二个参数是要另存为的类型,并且可能是必需的:

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。

于 2010-04-28T17:57:48.210 回答
1

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

我不得不质疑 using 子句的用法,因为您正在Launch复制另一个副本,不是吗?即在您正在使用的OpenDrawingSave功能内this._acadApplication还是我误解了?

使用(AutoCad cad = AutoCad.Instance)
{
    尝试{
       // 启动 AutoCAD
       cad.Launch();

       // 打开绘图
       cad.OpenDrawing(@"C:\Scratch\Drawing01.dwg");

       // 保存
       cad.SaveAs(@"C:\Scratch\Drawing01B.dwg");
    }catch(COMException ex){
       // 这里处理异常
    }
}

公共无效启动()
{
    this._acadApplication = null;
    常量字符串 ProgramId = "AutoCAD.Application.18";

    尝试
    {
        // 连接到正在运行的实例
        this._acadApplication = (AcadApplication)Marshal.GetActiveObject(ProgramId);
    }
    捕捉(COMException)
    {
        /* 没有实例在运行,启动一个 */

        尝试
        {
            this._acadApplication = (AcadApplication)Activator.CreateInstance(
                Type.GetTypeFromProgID(ProgramId),
                真的);
        }
        捕获(COMException 异常)
        {
            // 失败 - 是否安装了 AutoCAD?
            抛出新的 AutoCadNotFoundException(异常);
        }
    }

    /* 监听我们需要的事件并使应用程序可见 */
    this._acadApplication.BeginOpen += this.OnAcadBeginOpen;
    this._acadApplication.BeginSave += this.OnAcadBeginSave;
    this._acadApplication.EndOpen += this.OnAcadEndOpen;
    this._acadApplication.EndSave += this.OnAcadEndSave;

#如果调试
    this._acadApplication.Visible = true;
#别的
    this._acadApplication.Visible = false;
#万一

    // 获取活动文档
    // this._acadDocument = this._acadApplication.ActiveDocument;
    // 评论 ^^^ out? 当您在打开绘图时实例化下面的 ActiveDocument 时?
}

公共无效OpenDrawing(字符串路径)
{
    尝试{
       // 请求 AutoCAD 打开文档
       this._acadApplication.Documents.Open(path, false, null);

       // 更新我们对新文档的引用
       this._acadDocument = this._acadApplication.ActiveDocument;
    }catch(COMException ex){
       // 这里处理异常
    }
}

公共无效另存为(字符串全路径)
{
    尝试{
       this._acadDocument.SaveAs(fullPath, null, null);
    }catch(COMException ex){
       // 这里处理异常
    }最后{
       this._acadDocument.Close();
    }
}

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

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

于 2010-02-18T13:52:48.453 回答
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);
于 2010-02-18T15:33:46.593 回答
0

对于 C# 和 COM,当有可选参数时,您需要使用Type.Missing而不是 null:

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

但从 Visual Studio 2010 开始,您可以简单地省略可选参数:

this._acadDocument.SaveAs(fullPath);
于 2015-08-19T15:49:14.720 回答