/* C# 6.0 (Visual Studio 2015)
Program.cs
© Андрей Бушман, 2016
Пример работы с AutoCAD через COM из внешнего приложения. */
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using static System.Console;
namespace Bushman.Sandbox.AutoCAD {
class Program {
/// <summary>
/// Вывод в поток Error сообщения об ошибке.
/// </summary>
/// <param name="ex">Объект исключения, подлежащий
/// обработке.</param>
/// <param name="c">Цвет текста.</param>
static void WriteErrorMsg(Exception ex, ConsoleColor c
) {
ConsoleColor prew = ForegroundColor;
ForegroundColor = c;
Error.WriteLine("\nException (HResult = {0}):\n{1}",
ex.HResult, ex.Message);
ForegroundColor = prew;
}
private const int sleep = 500;
/// <summary>
/// Метод предназначен для получения COM-объекта или
/// значения его свойств. Или же для вызова метода COM-
/// объекта, возвращающего некоторое значение.
/// </summary>
/// <param name="func">Лямбда-выражение, подлежащее
/// выполнению.</param>
/// <returns>Возвращаемый тип Object вызывающая сторона
/// должна присваивать dynamic-переменной, дабы можно
/// было полноценно использовать свойства, методы и
/// события полученного объекта (без рефлексии).
/// </returns>
static object CallFunc(Func<object> func) {
while (true) {
try {
object obj = func();
return obj;
}
catch (COMException ex) {
WriteErrorMsg(ex, ConsoleColor.Yellow);
// В качестве эксперимента:
// Thread.Sleep(sleep);
}
catch (Exception ex) {
WriteErrorMsg(ex, ConsoleColor.Red);
throw;
}
}
}
/// <summary>
/// Метод предназначен для изменения свойств COM-объекта
/// , или же для вызова метода COM-объекта, ничего не
/// возвращающего в качестве результата.
/// </summary>
/// <param name="func">Лямбда-выражение, подлежащее
/// выполнению.</param>
static void DoAction(Action func) {
while (true) {
try {
func();
return;
}
catch (COMException ex) {
WriteErrorMsg(ex, ConsoleColor.Yellow);
// В качестве эксперимента:
// Thread.Sleep(sleep);
}
catch (Exception ex) {
WriteErrorMsg(ex, ConsoleColor.Red);
throw;
}
}
}
static void Main(string[] args) {
Title = "AutoCAD through COM";
/* Вариант 1:
Получить ссылку на экземпляр Application уже
запущенного приложения AutoCAD.
Примечание 1:
Если параметром указывать "AutoCAD.Application",
то создастся экземпляр Application той версии
AutoCAD, которая была запущена последней.
Примечание 2:
Можно конкретизировать нужную версию, указывая
Major: "AutoCAD.Application.19".
*/
/*
dynamic app = CallFunc(()=> Marshal.GetActiveObject(
"AutoCAD.Application"));
*/
/* *************************************************
Вариант 2:
Создать новый экземпляр Application приложения
AutoCAD (см. выше примечания 1 и 2). */
Type comAppType = Type.GetTypeFromProgID(
"AutoCAD.Application");
dynamic app = CallFunc(() => Activator
.CreateInstance(comAppType));
/* *************************************************
Далее, для получения информации о методах,
свойствах и событиях объекта Application (и не
только его) смотрим документацию:
http://help.autodesk.com/view/ACD/2017/ENU/?guid=GUID-A809CD71-4655-44E2-B674-1FE200B9FE30
Это приходится делать т.к. Intellisense не
сможет давать подсказок для dynamic.
*/
/* Далее используем интересующие нас методы,
свойства и события: */
dynamic docs = CallFunc(() => app.Documents);
// Открываем существующий документ
dynamic doc1 = CallFunc(() => docs.Open(
@"c:\shared\111.dwg"));
// Создаём новый документ на основе DWT-шаблона
dynamic doc2 = CallFunc(() => docs.Add(
@"Tutorial-mArch.dwt"));
dynamic count = CallFunc(() => docs.Count);
dynamic title = CallFunc(() => app.Caption);
// по умолчанию Visible установлен в false
DoAction(() => app.Visible = true);
WriteLine("\nPress any key for dociments close...");
ReadKey();
// Сохранение документа
// DoAction(()=> doc1.Save());
// закрытие без сохранения изменений
// DoAction(() => doc1.Close(false));
// сохранение изменений и закрытие
DoAction(() => doc1.Close(true));
/* В методе SaveAs вторым параметром указываем
числовое значение перечисления AcSaveAsType,
которое можно найти в файле
"ObjectARX 20XX\inc-win32\acadi.h": */
// 36 - это значение для варианта DWG2007
DoAction(() => doc2.SaveAs(@"c:\shared\222.dwg", 36)
);
DoAction(() => doc2.Close());
WriteLine("\nPress any key for exit...");
ReadKey();
DoAction(() => app.Quit());
}
}
}