public partial class Form1 : Form
{
const int sleep = 500;
const uint RPC_E_CALL_REJECTED = 0x80010001;
const uint RPC_E_RETRY = 0x80010109;
const uint RPC_E_SERVERCALL_RETRYLATER = 0x8001010A;
const uint RPC_S_SERVER_TOO_BUSY = 1723;
const uint RPC_E_SERVERFAULT = 0x80010105;
const uint HRESULT = 0x800706BA;
public Form1()
{
InitializeComponent();
}
private static string FormatNumber(string text)
{
if (double.TryParse(text, out double number))
{
return number.ToString("N", CultureInfo.CreateSpecificCulture("en-US"));
// Console.WriteLine(number);
}
return text;
}
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;
}
/// <summary>
/// Проверка доступности COM объекта Application,
/// представляющего экземпляр AutoCAD.
/// </summary>
/// <param name="app">COM объект Application.</param>
/// <returns>Возвращается true в случае готовности
/// объекта Application к работе. В противном случае
/// возвращается false.</returns>
///
static bool CheckReady(object app)
{
if (app == null)
return false;
dynamic acad = app;
bool isQuiescent = false;
while (true)
{
try
{
dynamic state = acad.GetAcadState();
isQuiescent = state.IsQuiescent;
break;
}
catch (COMException ex)
{
uint err = (uint)ex.ErrorCode;
switch (err)
{
case RPC_E_CALL_REJECTED:
case RPC_E_RETRY:
case RPC_E_SERVERCALL_RETRYLATER:
case RPC_S_SERVER_TOO_BUSY:
case RPC_E_SERVERFAULT:
case HRESULT:
{
WriteErrorMsg(ex, ConsoleColor.Yellow);
Thread.Sleep(sleep);
break;
}
default:
{
WriteErrorMsg(ex, ConsoleColor.Red);
throw;
}
}
}
catch (Exception ex)
{
WriteErrorMsg(ex, ConsoleColor.Red);
throw;
}
}
return isQuiescent;
}
/// <summary>
/// Получить COM объект Application.
/// </summary>
/// <param name="func">Лямбда-выражение, возвращающее
/// искомый COM объект Application.</param>
/// <returns>Возвращается COM объект Application.
/// </returns>
static object GetApp(Func<object> func)
{
if (func == null)
{
throw new ArgumentNullException(nameof(func));
}
while (true)
{
try
{
object obj = func();
return obj;
}
catch (COMException ex)
{
uint err = (uint)ex.ErrorCode;
switch (err)
{
case RPC_E_CALL_REJECTED:
case RPC_E_RETRY:
case RPC_E_SERVERCALL_RETRYLATER:
case RPC_S_SERVER_TOO_BUSY:
case RPC_E_SERVERFAULT:
case HRESULT:
{
WriteErrorMsg(ex, ConsoleColor.Yellow);
Thread.Sleep(sleep);
break;
}
default:
{
WriteErrorMsg(ex, ConsoleColor.Red);
throw;
}
}
}
catch (Exception ex)
{
WriteErrorMsg(ex, ConsoleColor.Red);
throw;
}
}
}
//
/// <summary>
/// Метод предназначен для получения COM-объекта или
/// значения его свойств. Или же для вызова метода COM-
/// объекта, возвращающего некоторое значение.
/// </summary>
/// <param name="app">COM объект Application.</param>
/// <param name="func">Лямбда-выражение, подлежащее
/// выполнению.</param>
/// <returns>Возвращаемый тип Object вызывающая сторона
/// должна присваивать dynamic-переменной, дабы можно
/// было полноценно использовать свойства, методы и
/// события полученного объекта (без рефлексии).
/// </returns>
static object CallFunc(object app, Func<object> func)
{
if (app == null)
throw new ArgumentNullException(nameof(app));
if (func == null)
throw new ArgumentNullException(nameof(func));
while (!CheckReady(app))
{
// ждём, когда приложение будет готово...
}
object obj = func();
return obj;
}
/// <summary>
/// Метод предназначен для изменения свойств COM-объекта
/// , или же для вызова метода COM-объекта, ничего не
/// возвращающего в качестве результата.
/// </summary>
/// <param name="app">COM объект Application.</param>
/// <param name="func">Лямбда-выражение, подлежащее
/// выполнению.</param>
static void DoAction(object app, Action func)
{
if (app == null)
throw new ArgumentNullException(nameof(app));
if (func == null)
throw new ArgumentNullException(nameof(func));
while (!CheckReady(app))
{
// ждём, когда приложение будет готово...
}
func();
}