Как я могу открыть AutoCAD 2015 через .NET API
Я проработал хороший час и еще не нашел что-то, что поможет в этом. Я работаю над открытием AutoCAD из .NET API в VS2013 с использованием С#, но по какой-то причине я никогда не смогу запустить AutoCAD. Я использую следующий код:
using System;
using System.Runtime.InteropServices;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
namespace IOAutoCADHandler
{
public static class ACADDocumentManagement
{
[CommandMethod("ConnectToAcad")]
public static void ConnectToAcad()
{
AcadApplication acAppComObj = null;
// no version number so it will run with any version
const string strProgId = "AutoCAD.Application";
// Get a running instance of AutoCAD
try
{
acAppComObj = (AcadApplication)Marshal.GetActiveObject(strProgId);
}
catch // An error occurs if no instance is running
{
try
{
// Create a new instance of AutoCAD
acAppComObj = (AcadApplication)Activator.CreateInstance(Type.GetTypeFromProgID(strProgId), true);
}
catch //// STOPS HERE
{
// If an instance of AutoCAD is not created then message and exit
// NOTE: always shows this box and never opens AutoCAD
System.Windows.Forms.MessageBox.Show("Instance of 'AutoCAD.Application'" +
" could not be created.");
return;
}
}
// Display the application and return the name and version
acAppComObj.Visible = true;
System.Windows.Forms.MessageBox.Show("Now running " + acAppComObj.Name +
" version " + acAppComObj.Version);
// Get the active document
AcadDocument acDocComObj;
acDocComObj = acAppComObj.ActiveDocument;
// Optionally, load your assembly and start your command or if your assembly
// is demandloaded, simply start the command of your in-process assembly.
acDocComObj.SendCommand("(command " + (char)34 + "NETLOAD" + (char)34 + " " +
(char)34 + @"C:\Users\Administrator\Documents\All Code\main-libraries\IOAutoCADHandler\bin\Debug\IOAutoCADHandler.dll" + (char)34 + ") ");
acDocComObj.SendCommand("DRAWCOMPONENT");
}
}
К сожалению, он всегда останавливается в вложенном операторе catch
и всегда отображает всплывающее окно без открытия AutoCAD. Любые предложения о том, как хотя бы сделать AutoCAD для меня?
EDIT: сообщение об ошибке
![][1]()
Ответы
Ответ 1
Проблема в том, что вы кодируете (правильно) интерфейс InterCAD. Я рекомендую против этого (из-за возможных изменений версии).
Другая проблема заключается в том, что документация для плагинов AutoCAD, использующая новый .net api, предназначена для плагинов, когда AutoCAD уже запущен.
Конечная проблема может заключаться в том, что идентификатор программы AutCAD является загадкой. Я прибегал к настройке настраиваемого параметра, но по умолчанию используется значение "AutoCAD.Application", которое примет зарегистрированный в настоящее время AutoCAD.Application на производственной машине. Если на компьютере установлено несколько версий, и вы хотите быть конкретными, то вы можете добавить номер версии (который вам потребуется исследовать) в ProgID, например: "AutoCAD.Application.19" или "AutoCAD.Application.20" на 2015 год.
Для первой проблемы один метод - использовать динамику для объектов autoCad, особенно для создания экземпляров. Я использовал ObjectARX api для создания своего приложения в фиктивном проекте, а затем переключился на динамику, когда я доволен именами свойств и методов.
В автономном приложении .Net, которое запускает AutoCAD, вы можете использовать что-то вроде:
// I comment these out in production
//using Autodesk.AutoCAD.Interop;
//using Autodesk.AutoCAD.Interop.Common;
//...
//private static AcadApplication _application;
private static dynamic _application;
static string _autocadClassId = "AutoCAD.Application";
private static void GetAutoCAD()
{
_application = Marshal.GetActiveObject(_autocadClassId);
}
private static void StartAutoCad()
{
var t = Type.GetTypeFromProgID(_autocadClassId, true);
// Create a new instance Autocad.
var obj = Activator.CreateInstance(t, true);
// No need for casting with dynamics
_application = obj;
}
public static void EnsureAutoCadIsRunning(string classId)
{
if (!string.IsNullOrEmpty(classId) && classId != _autocadClassId)
_autocadClassId = classId;
Log.Activity("Loading Autocad: {0}", _autocadClassId);
if (_application == null)
{
try
{
GetAutoCAD();
}
catch (COMException ex)
{
try
{
StartAutoCad();
}
catch (Exception e2x)
{
Log.Error(e2x);
ThrowComException(ex);
}
}
catch (Exception ex)
{
ThrowComException(ex);
}
}
}
Ответ 2
Я открываю приложение очень прямолинейно. Во-первых, обязательно обратитесь к правильной библиотеке типов. Я использую библиотеку типов AutoCAD 2014, расположенную по адресу:
c:\program files\common files\autodesk shared\acax19enu.tlb
Для инициализации приложения:
using AutoCAD;
namespace test
{
class Program
{
static void Main(string[] args)
{
AutoCAD.AcadApplication app;
app = new AcadApplication();
app.Visible = true;
Console.Read();
}
}
}
Ответ 3
Если на компьютере установлено несколько версий AutoCAD, создание экземпляра с помощью ProgID "AutoCAD.Application" будет запускать последнюю версию, запущенную на этом компьютере текущим пользователем. Если версия используемой сборки Interop не соответствует версии, которая запускается, вы получите исключение System.InvalidCastException с HRESULT 0x80004002 (E_NOINTERFACE).
В вашем конкретном случае {070AA05D-DFC1-4E64-8379-432269B48B07} IID в вашем сообщении об ошибке является GUID для интерфейса AcadApplication
в 64-разрядном R19 (AutoCAD 2013 и 2014). Таким образом, запускается AutoCAD 2013 или 2014, и вы не можете использовать этот COM-объект для типа 2015, потому что 2015 - это R20 (не совместим с бинарными).
Чтобы этого избежать, вы можете добавить определенную версию в свой ProgID (например, "AutoCAD.Application.20" для AutoCAD 2015 (R20.0) до 2016 (R20.1)), чтобы запустить версию, соответствующую вашим сборкам Interop или вы можете использовать позднюю привязку (например, удалите свои ссылки на Autodesk.AutoCAD.Interop * и используйте ключевое слово dynamic
вместо типов AutoCAD).
В последнем случае вы потеряете автозаполнение, но ваша программа будет работать со всеми версиями AutoCAD.
Проверьте также 32-разрядные и 64-разрядные, поскольку сборки TypeLib/Interop не совпадают.
Ответ 4
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Tekkit
{
class Program
{
static void Main(string[] args)
{
//make sure to add last 2 using statements
ProcessStartInfo start = new ProcessStartInfo("calc.exe");
Process.Start(start);//starts the process
}
}
}