c# - AcadApplication for AutoCAD 2022 的位置和使用

标签 c# autocad-plugin

我正在尝试找出如何让 AutoCAD 识别正在运行的实例。但是,我遇到了一个问题,应用程序上不存在 AcadApplication 无法识别,如下面的代码所述。

我这样做是为了避免必须制作直接插件,而是制作一个可以单独与 AutoCAD 通信的 WPF 应用程序(创建一个将来也可以提供与 AutoCAD 无关的功能的工具包)。如果这种方法不是一个好主意,请随时告诉我,因为我正在寻找解决此问题的最佳方法。

有人可以帮助我让此代码适用于 AutoCAD 2022 吗? 目前,它正在运行 .NET Framework 4.7.2 的 WPF 应用程序中运行(引用是从我安装的 AutoCAD 中手动包含的)

using System.Windows;

using System.Runtime.InteropServices;
using System;

using aD = Autodesk.AutoCAD.ApplicationServices;

namespace
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        aD.Application.AcadApplication acAppComObj = null;
        const string strProgId = "AutoCAD.Application.22";

        public MainWindow()
        {
            InitializeComponent();

            acAppComObj = Marshal.GetActiveObject(strProgId) as aD.Application.AcadApplication;

            // Get a running instance of AutoCAD
            try
            {
                acAppComObj = (aD.Application.AcadApplication)Marshal.GetActiveObject(strProgId);
            }
            catch // An error occurs if no instance is running
            {
                try
                {
                    // Create a new instance of AutoCAD
                    acAppComObj = (aD.Application.AcadApplication)Activator.CreateInstance(Type.GetTypeFromProgID(strProgId), true);
                }
                catch (Exception)
                {
                    // If an instance of AutoCAD is not created then message and exit
                    MessageBox.Show("Instance of 'AutoCAD.Application' could not be created.");

                    return;
                }
            }
        }
    }
}

为了简洁地回答我的问题,如何使用 AcadApplication 类型,以及从哪里访问它?

最佳答案

这里有一个示例类,您可以使用它来开始使用。

我的猜测是,无法启动 AutoCAD 实例有两个根本原因:

  1. 您没有使用 Autodesk.AutoCAD.Interop.AcadApplication 引用
  2. 您使用的 AutoCAD 2022 progId 错误

尝试一下这段代码,然后看看是否可以向后查找问题。
当您想要启动 AutoCAD/在没有直接插件的情况下使用 AutoCAD 时,您需要使用 COM 互操作对象,而不是 Autodesk.AutoCAD.ApplicationServices。

此外,以下是您需要的新引用资料的路径:
C:\Program Files\Autodesk\AutoCAD 2022\Autodesk.AutoCAD.Interop.dll
C:\Program Files\Autodesk\AutoCAD 2022\Autodesk.AutoCAD.Interop.Common.dll
C:\Program Files (x86)\Reference\Assemblies\Microsoft\Framework.NETFramework\v4.7.2\Microsoft.VisualBasic.dll

using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;


namespace StackOverflow
{
    public partial class MainWindow : Window
    {


        public MainWindow()
        {
            InitializeComponent();
            bool isAutoCADRunning = Utilities.IsAutoCADRunning();
            if (isAutoCADRunning == false)
            {
                MessageBox.Show("Starting new AutoCAD 2022 instance...this will take a some time.");
                Utilities.StartAutoCADApp();
            }
            else
            {
                MessageBox.Show("AutoCAD already running.");
            }
            Utilities.SendMessage("AutoCAD started from WPF");
            MyDriver.CreateMyProfile();
            Utilities.SendMessage("Profile created:" + Utilities.yourProfileName);
            //MyDriver.NetloadMyApp(@"C:\YourPathFolderPath\custom.Dll");
        }
    }



    public class MyDriver
    {
        public static void CreateMyProfile()
        {
            bool isAutoCADRunning = Utilities.IsAutoCADRunning();
            if (isAutoCADRunning == false)
                Utilities.StartAutoCADApp();
            Utilities.CreateProfile();
        }

        public static void NetloadMyApp(String dllPath)
        {
            bool isAutoCADRunning = Utilities.IsAutoCADRunning();
            if (isAutoCADRunning == false)
                Utilities.StartAutoCADApp();
            Utilities.NetloadDll(dllPath);
        }
    }

    public class Utilities
    {
        [System.Runtime.InteropServices.DllImport("user32")]
        public static extern IntPtr GetWindowThreadProcessId(IntPtr hwnd, ref IntPtr lpdwProcessId);

        private static readonly string AutoCADProgId = "AutoCAD.Application.24.1";
        private static AcadApplication App;


        public static void SendMessage(String message)
        {   
            App.ActiveDocument.SendCommand("(princ \"" + message + "\")(princ)" + Environment.NewLine);
        }
            

        public static bool IsAutoCADRunning()
        {
            bool isRunning = GetRunningAutoCADInstance();
            return isRunning;
        }

        public static bool ConfigureRunningAutoCADForUsage()
        {
            if (App == null)
                return false;
            MessageFilter.Register();
            SetAutoCADWindowToNormal();
            return true;
        }

        public static bool StartAutoCADApp()
        {
            Type autocadType = System.Type.GetTypeFromCLSID(new Guid("AA46BA8A-9825-40FD-8493-0BA3C4D5CEB5"), true);
            object obj = System.Activator.CreateInstance(autocadType, true);
            AcadApplication appAcad = (AcadApplication)obj;
            App = appAcad;
            MessageFilter.Register();
            SetAutoCADWindowToNormal();
            return true;
        }

        public static bool NetloadDll(string dllPath)
        {
            if (!System.IO.File.Exists(dllPath))
                throw new Exception("Dll does not exist: " + dllPath);
            App.ActiveDocument.SendCommand("(setvar \"secureload\" 0)" + Environment.NewLine);
            dllPath = dllPath.Replace(@"\", @"\\");
            App.ActiveDocument.SendCommand("(command \"_netload\" \"" + dllPath + "\")" + Environment.NewLine);
            return true;
        }
      

        public static bool CreateProfile()
        {
            if (App == null)
                return false;
            bool profileExists = DoesProfileExist(App, yourProfileName);
            if (profileExists)
            {
                SetYourProfileActive(App, yourProfileName);
                AddTempFolderToTrustedPaths(App);
            }
            else
            {
                CreateYourCustomProfile(App, yourProfileName);
                AddTempFolderToTrustedPaths(App);
            }
            SetYourProfileActive(App, yourProfileName);
            return true;
        }


        public static bool SetAutoCADWindowToNormal()
        {
            if (App == null)
                return false;
            App.WindowState = AcWindowState.acNorm;
            return true;
        }






        private static bool GetRunningAutoCADInstance()
        {
            Type autocadType = System.Type.GetTypeFromProgID(AutoCADProgId, true);
            AcadApplication appAcad;
            try
            {
                object obj = Microsoft.VisualBasic.Interaction.GetObject(null, AutoCADProgId);
                appAcad = (AcadApplication)obj;
                App = appAcad;
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return false;
        }

        public static readonly string yourProfileName = "myCustomProfile";

        private static void SetYourProfileActive(AcadApplication appAcad, string profileName)
        {
            AcadPreferencesProfiles profiles = appAcad.Preferences.Profiles;
            profiles.ActiveProfile = profileName;
        }

        private static void CreateYourCustomProfile(AcadApplication appAcad, string profileName)
        {
            AcadPreferencesProfiles profiles = appAcad.Preferences.Profiles;
            profiles.CopyProfile(profiles.ActiveProfile, profileName);
            profiles.ActiveProfile = profileName;
        }

        private static bool DoesProfileExist(AcadApplication appAcad, string profileName)
        {
            AcadPreferencesProfiles profiles = appAcad.Preferences.Profiles;
            object pNames = null;
            profiles.GetAllProfileNames(out pNames);
            string[] profileNames = (string[])pNames;
            foreach (string name in profileNames)
            {
                if (name.Equals(profileName))
                    return true;
            }
            return false;
        }

        private static void AddTempFolderToTrustedPaths(AcadApplication appAcad)
        {
            string trustedPathsString = System.Convert.ToString(appAcad.ActiveDocument.GetVariable("TRUSTEDPATHS"));
            string tempDirectory = System.IO.Path.GetTempPath();
            List<string> newPaths = new List<string>() { tempDirectory };
            if (!trustedPathsString.Contains(tempDirectory))
                AddTrustedPaths(appAcad, newPaths);
        }

        private static void AddTrustedPaths(AcadApplication appAcad, List<string> newPaths)
        {
            string trustedPathsString = System.Convert.ToString(appAcad.ActiveDocument.GetVariable("TRUSTEDPATHS"));
            List<string> oldPaths = new List<string>();
            oldPaths = trustedPathsString.Split(System.Convert.ToChar(";")).ToList();
            string newTrustedPathsString = trustedPathsString;
            foreach (string newPath in newPaths)
            {
                bool pathAlreadyExists = trustedPathsString.Contains(newPath);
                if (!pathAlreadyExists)
                    newTrustedPathsString = newPath + ";" + newTrustedPathsString;
            }
            appAcad.ActiveDocument.SetVariable("TRUSTEDPATHS", newTrustedPathsString);
        }
    }


    public class MessageFilter : IOleMessageFilter
    {
        [DllImport("Ole32.dll")]
        private static extern int CoRegisterMessageFilter(IOleMessageFilter newFilter, ref IOleMessageFilter oldFilter);

        public static void Register()
        {
            IOleMessageFilter newFilter = new MessageFilter();
            IOleMessageFilter oldFilter = null;
            CoRegisterMessageFilter(newFilter, ref oldFilter);
        }
        public static void Revoke()
        {
            IOleMessageFilter oldFilter = null;
            CoRegisterMessageFilter(null, ref oldFilter);
        }

        public int HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo)
        {
            return 0;
        }

        public int RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType)
        {
            if (dwRejectType == 2)
                // flag = SERVERCALL_RETRYLATER.

                // Retry the thread call immediately if return >=0 & 
                // <100.
                return 99;
            // Too busy; cancel call.
            return -1;
        }

        public int MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType)
        {
            return 2;
        }
    }

    [ComImport()]
    [Guid("00000016-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IOleMessageFilter
    {
        [PreserveSig]
        int HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo);
        [PreserveSig]
        int RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType);
        [PreserveSig]
        int MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType);
    }

}

关于c# - AcadApplication for AutoCAD 2022 的位置和使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70682786/

相关文章:

c# - 如何检查 Point3d 是否不为空?

c# - 加速此 LINQ to SQL 代码

c# - 注册表 - NetworkList 配置文件 - 无法通过程序访问

c# - 在 Autocad 绘图中查找特定属性中具有特定值的对象

styles - 使用 AutoLISP 生成新的尺寸样式

c# - 使用 Lisp 函数将 .NET 插件加载到 AutoCAD 2014

c# - HttpWebRequest.GetResponse : "The underlying connection was closed: An unexpected error occurred on a receive."

c# - 在 C# 中使用通知的生产者和消费者

c# - 如何获取 WPF ListView 以将字节数组格式化为逗号分隔的字符串?

c# - AutoCAD 插件无法定位资源