3

我正在使用 Visual Studio 2010,并且我有一个想要在 Autocad 中打开的 .DWG 文件。到现在我都用过这个。

Process p = new Process();
ProcessStartInfo s = new ProcessStartInfo("D:/Test File/" + fileName);
p.StartInfo = s;
p.Start();

但我想要的是关闭 Autocad 中的文件,而不是 autocad 本身。(意味着 atocad.exe 应该保持运行)。

直到现在我已经使用了它,但它关闭了 acad.exe 而不是文件。

foreach (Process Proc in Process.GetProcesses())
{
    if (Proc.ProcessName.Equals("acad"))
    {
        Proc.CloseMainWindow();
        Proc.Kill();
    }
}
4

6 回答 6

6

从 Autodesk 站点获取 Autocad .NET 库 ( http://usa.autodesk.com/adsk/servlet/index?id=773204&siteID=123112 )

然后你就可以使用ApplicationDocument类了。它们将使您完全控制在应用程序中打开和关闭文档。

您可以找到很多关于此的文章,并且可以提出更多问题。

于 2013-07-19T12:45:50.633 回答
4

AutoCAD 确实有一个 api。有 4 个组件。两个用于进程内,两个用于 COM。

进程内:acdbmgd.dll acmgd.dll

COMInterop:Autodesk.Autocad.Interop.dll Autodesk.Autocad.Interop.Common.dll

这是一种打开 AutoCAD 新实例或连接到现有运行中的 AutoCAD 实例的方法。

您需要将这些 .dll 加载到您的项目引用中。

using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;

namespace YourNameSpace {

public class YourClass {

AcadApplication AcApp;
private const string progID = "AutoCAD.Application.18.2";// this is AutoCAD 2012 program id
private string profileName = "<<Unnamed Profile>>";
private const string acadPath = @"C:\Program Files\Autodesk\AutoCAD 2012 - English\acad.exe";

public void GetAcApp()
    {
        try
        {
            AcApp = (AcadApplication)Marshal.GetActiveObject(progID);

        } catch {
            try {
                var acadProcess = new Process();
                acadProcess.StartInfo.Arguments = string.Format("/nologo /p \"{0}\"", profileName);
                acadProcess.StartInfo.FileName = (@acadPath);
                acadProcess.Start();
                while(AcApp == null)
                {
                    try { AcApp = (AcadApplication)Marshal.GetActiveObject(progID); }
                    catch { }
                }
            } catch(COMException) {
                MessageBox.Show(String.Format("Cannot create object of type \"{0}\"",progID));
            }
        }
        try {
            int i = 0;
            var appState = AcApp.GetAcadState();
            while (!appState.IsQuiescent)
            {
                if(i == 120)
                {
                    Application.Exit();
                }
                // Wait .25s
                Thread.Sleep(250);
                i++;
            }
            if(AcApp != null){
                // set visibility
                AcApp.Visible = true;
            }
        } catch (COMException err) {
            if(err.ErrorCode.ToString() == "-2147417846"){
                Thread.Sleep(5000);
            }
        }
    }
    }
}

关闭它就像

Application.Exit();

并原谅代码。太残忍了,这是我刚开始开发时的第一个方法之一......

于 2013-07-20T00:19:59.257 回答
2

我怀疑你是否能够做到这一点,除非 AutoCAD 有一个 API,你可以连接并要求它为你关闭文件。

您的 c# 应用程序只能对进程 (acad.exe) 执行操作,它无权访问该进程的内部操作。

于 2013-07-19T09:30:49.690 回答
1

此外,您不应该使用 Kill,除非进程变得无响应,而且肯定不会在 CloseMainWindow 之后立即使用。

CloseMainWindow 是要求应用程序自行关闭的礼貌方式。杀死就像从插座中拔出电源线。您没有给它机会自行清理并干净地退出。

于 2013-07-19T13:50:00.007 回答
1

还有另一种可能性 - 只有当您的 C# 代码与 AutoCAD 进程在同一台机器上运行时才有效,并且不建议这样做,但是,如果您真的被卡住并准备忍受窗口切换的麻烦您可以使用 SendKeys 命令将击键发送到应用程序。

MSDN 文章在这里: http: //msdn.microsoft.com/EN-US/library/ms171548 (v=VS.110,d=hv.2).aspx http://msdn.microsoft.com/en-us/库/system.windows.forms.sendkeys.send.aspx

使用它,您可以发送击键来模拟用户使用菜单命令关闭文件。

于 2013-07-19T13:57:05.757 回答
1

要执行文件关闭,最好的方法是按照此ObjectARX SDK for c#中的步骤操作,并使用以下代码更改以下代码。

            [CommandMethod("CD", CommandFlags.Session)]
            static public void CloseDocuments()
            {
                DocumentCollection docs = Application.DocumentManager;
                foreach (Document doc in docs)
                {
                    // First cancel any running command
                    if (doc.CommandInProgress != "" &&
                        doc.CommandInProgress != "CD")
                    {
                        AcadDocument oDoc =
                          (AcadDocument)doc.AcadDocument;
                        oDoc.SendCommand("\x03\x03");
                    }

                    if (doc.IsReadOnly)
                    {
                        doc.CloseAndDiscard();
                    }
                    else
                    {
                        // Activate the document, so we can check DBMOD
                        if (docs.MdiActiveDocument != doc)
                        {
                            docs.MdiActiveDocument = doc;
                        }
                        int isModified =
                          System.Convert.ToInt32(
                            Application.GetSystemVariable("DBMOD")
                          );

                        // No need to save if not modified
                        if (isModified == 0)
                        {
                            doc.CloseAndDiscard();
                        }
                        else
                        {
                            // This may create documents in strange places
                            doc.CloseAndSave(doc.Name);
                        }
                    }
                }
于 2013-08-13T07:20:27.903 回答