Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: prajdziswet от 17-11-2017, 16:17:27

Название: Закрытие чертежа - "чертеж занят"?
Отправлено: prajdziswet от 17-11-2017, 16:17:27
Наверное вопрос легкий (Autocad 2014), но я не знаю как правильно:

При открытии чертежа проверяю "учебную версию" если учебная хочу сразу закрыть - но вываливается ошибка "чертеж занят". как правильно закрыть чертеж, ну или оно чтобы дождалось (как освободился чертеж" и закрыло. Делаю так:
Код - C# [Выбрать]
  1. Autodesk.AutoCAD.ApplicationServices.Document dwgopen = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  2. bool pr=dwgopen.Database.IsEmr;
  3. if (pr)
  4. dwgopen.CloseAndDiscard();
  5.  
Как закрыть чертеж?
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: Александр Ривилис от 17-11-2017, 16:35:18
1. Пожалуйста прочитай у меня в подписи как следует форматировать код на форуме и в дальнейшем соблюдай это правило.
2. В каком контексте ты пытаешься закрыть документ? Это событие открытия документа или команда? И еслиа команда то контекста документа или контекста приложения?
Слишком мало информации.
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: avc от 17-11-2017, 16:47:17
Простейший вариант - затолкай в консоль команду Close. Когда сможет тогда и выполнится.
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: prajdziswet от 17-11-2017, 18:57:15
при автозагрузке одного из лисп вызывается команда через командную строку:
Код - Auto/Visual Lisp [Выбрать]
  1. (command "checkuv")
А до этого загружается dll на c#, типо что то такого:
Код - C# [Выбрать]
  1. public class Main : IExtensionApplication
  2.     {
  3. //.........
  4.  
  5.         [CommandMethod("checkuv")]
  6.         public void checkuv()
  7.         {
  8. //ну и впринципе сам код который писался ранее
  9. Autodesk.AutoCAD.ApplicationServices.Document dwgopen = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  10. bool pr=dwgopen.Database.IsEmr;
  11. if (pr)
  12. dwgopen.CloseAndDiscard();
  13.          }
  14.  
  15. //.........
  16. }
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: Александр Ривилис от 17-11-2017, 19:41:24
Для начала попробуй заменить:
Код - C# [Выбрать]
  1. [CommandMethod("checkuv")]
на
Код - C# [Выбрать]
  1. [CommandMethod("checkuv",CommandFlags.Session)]
Еще вариант с использованием COM/ActiveX здесь: http://adndevblog.typepad.com/autocad/2012/05/closing-drawing-file-without-saving.html
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: prajdziswet от 17-11-2017, 22:03:22
Не помогло, не то не другое:
при загрузке автокада и запуска отдельно команды, оно срабатывает.
Но при загрузке команды через лисп - оно выдает ошибку и аварийно закрывается
(https://s7.postimg.org/9mfx86kxz/image.png) (https://postimg.org/image/9mfx86kxz/)

как и предложение avc правда не в консоль а в командную строку close
Код - C# [Выбрать]
  1. dwgop.SendStringToExecute("(command \"_close\")\n", true, false, false);
- все тоже аварийное закрытие автокада

//без флага CommandFlags.Session простой способ закрытия выбивал ошибку, но не фатальную...

___________
а есть ли событие завершение открытие загрузки чертежа? = просто у меня подозрение, что оно просто не загружает доконца чертеж = т.е в него еще грузятся лиспы и длл ====и мы пытаемся закрыть его, хоть он еще не загрузился?
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: Александр Ривилис от 18-11-2017, 00:16:16
а есть ли событие завершение открытие загрузки чертежа? = просто у меня подозрение, что оно просто не загружает доконца чертеж = т.е в него еще грузятся лиспы и длл ====и мы пытаемся закрыть его, хоть он еще не загрузился?
Такого события в чистом виде нет. И в любом случае из события закрыть чертеж ты не сможешь - в лучшем случае сможешь запустить команду на закрытие. Вариант с COM\ActiveX уже проверил?
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: Дмитрий Загорулькин от 18-11-2017, 00:19:03
И в любом случае из события закрыть чертеж ты не сможешь
Вы имеете в виду события документа? Может быть, стоит попробовать сделать это в Application.Idle?
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: Александр Ривилис от 18-11-2017, 00:21:32
Может быть, стоит попробовать сделать это в Application.Idle?
Запустить из этого события команду, закрывающую чертеж - можно. А вот выполнять в этом событии что-то типа CloseAndDiscard я бы не рискнул.
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: Александр Ривилис от 18-11-2017, 00:34:23
Кстати команду можно запускать через:
Код - C# [Выбрать]
  1. [DllImport("accore.dll", CharSet = CharSet.Unicode,  CallingConvention = CallingConvention.Cdecl,  EntryPoint = "ads_queueexpr")]
  2. extern static private int ads_queueexpr(byte[] command);
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: prajdziswet от 18-11-2017, 15:08:32
Вариант с COM\ActiveX уже проверил?
да я сразу тогда и проверил, и отписался что не тот и не тот не прошел ...
насчет accore.dll попробую...
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: prajdziswet от 19-11-2017, 18:07:59
Кстати команду можно запускать через:
Александр, а это на 2014 автокаде работает или с 2015, или не так делаю:
Код - C# [Выбрать]
  1. ads_queueexpr(System.Text.Encoding.UTF32.GetBytes("Close"));
У меня самое интересное что оно запускается в отладчике раньше чем запускается сам автокад, а если дать потом с чертежа ничего не происходит. Пробывал и "_Close" и UTF8...может я что то не так делаю ::)
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: Александр Ривилис от 19-11-2017, 19:09:23
Кстати команду можно запускать через:
Александр, а это на 2014 автокаде работает или с 2015, или не так делаю:
Код - C# [Выбрать]
  1. ads_queueexpr(System.Text.Encoding.UTF32.GetBytes("Close"));
У меня самое интересное что оно запускается в отладчике раньше чем запускается сам автокад, а если дать потом с чертежа ничего не происходит. Пробывал и "_Close" и UTF8...может я что то не так делаю ::)
Работает начиная с AutoCAD 2000 еще до всяких .NET.

Должно быть как-то так:
Код - C# [Выбрать]
  1. ads_queueexpr("(command \"_Close\")\n");
В описании ads_queueexpr кажется ошибка. Должно быть:
Код - C# [Выбрать]
  1. [DllImport("accore.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
  2. extern static private int ads_queueexpr(string strExpr);
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: prajdziswet от 19-11-2017, 20:57:22
все таже ошибка:

(https://s18.postimg.org/6haj2pmqt/image.png) (https://postimg.org/image/6haj2pmqt/)

как впринципе если и в лисп(автозагрузки) вставить команду закрытия... :'(

п.с конечно можно поробывать ход конем, хоть мне и не нравится -не красиво  :( :
запускать паралельный процесс с эксепшн и таймером(первый самый вариант хоть исключение выкидвало) и через Invoke пробывать пока не закроет


Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: Александр Ривилис от 19-11-2017, 21:02:46
Ничего не понял. Еще же AutoCAD не загрузился.
Не нужно насиловать AutoCAD. Просто придумай другой алгоритм без закрытия чертежа. Например предупреди пользователя и всё.
А если речь идёт об AutoCAD 2014, то просто установи для него SP1 и забудь про отметку учебной версии.
Или воспользуйся моим кодом для снятия флажка учебной версии в AutoCAD 2014: http://adn-cis.org/forum/index.php?topic=1110.0
Тему читать всю от начала и до конца. Обратить внимание на EMRCLEAR.
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: prajdziswet от 19-11-2017, 21:18:50
Например предупреди пользователя и всё.
А если речь идёт об AutoCAD 2014, то просто установи для него SP1 и забудь про отметку учебной версии.

Насчет сервес-пака он установлен и у меня то оно просто предупреждало пользователя, что "учебная версия" (а так автокад молчит). Но люди как пользовались, так и пользуются - а на наши чертежи потом ругаются, админ выложил "DWG TrueView" - чтобы люди пользовались и чистили (часть чистит, но все равно воз поныне там).

Или воспользуйся моим кодом для снятия флажка учебной версии в AutoCAD 2014: http://adn-cis.org/forum/index.php?topic=1110.0
Тему читать всю от начала и до конца. Обратить внимание на EMRCLEAR.
МХ, а вот это интересно - просто я думал что сбросить флаг нельзя так как он только для чтения - обязательно прочитаю (впринципе задумка и была чистка -скидывания учебки, просто флаг только для чтения и я подумал, что нельзя скинуть)
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: Александр Ривилис от 19-11-2017, 22:02:19
МХ, а вот это интересно - просто я думал что сбросить флаг нельзя так как он только для чтения - обязательно прочитаю (впринципе задумка и была чистка -скидывания учебки, просто флаг только для чтения и я подумал, что нельзя скинуть)
Он и есть "только для чтения", но так как Autodesk отказался от флага учебной версии, то я себе позволил небольшой "хак".
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: avc от 19-11-2017, 22:33:29
По теме закрытия у меня как-то была задача обновлять файл чертежа если пользователь открыл старый локальный  а на сервере лежит новая версия. Так вот из обработчика события открытия файла я так и не смог сделать его закрытие. Ограничился (в точности как писалось выше) предупреждением пользователю типа "Файл старый, вызови команду обновления". А вот уже из команды - пожалуйста, все вполне закрывается и открывается. Команда конечно сессионная. Вот рабочий код (Cns - это мой класс для работы с консолью Автокада):
Код - C# [Выбрать]
  1.   [CommandMethod("ReOpen", CommandFlags.NoBlockEditor | CommandFlags.Session | CommandFlags.Modal)]
  2.     public static void ReOpen()
  3.     {
  4.        try
  5.       {
  6.         Document doc = AcadApp.DocumentManager.MdiActiveDocument;
  7.         if (doc == null) return;
  8.  
  9.         if (!DocSaved)
  10.         {
  11.           if (!Cns.Query(
  12.             "Чертеж отредактирован и не сохранен!\n" +
  13.             "Перезагрузка вызовет потерю всех изменений.\n" +
  14.             "Закрыть файл без сохранения?"))
  15.             return;
  16.         }
  17.  
  18.         if (!doc.TryClose()) return;
  19.         string fileName = LoadFile(.......);
  20.         if (File.Exists(fileName))
  21.           AcadApp.DocumentManager.Open(fileName, false);
  22.         else
  23.           Cns.Err("Файл " + fileName + " не существует");
  24.         }
  25.       catch (System.Exception ex) { Cns.Err(ex); }
  26.     }
  27.        
  28.     public static bool DocSaved
  29.     {
  30.       get
  31.       {
  32.         object obj = AcadApp.GetSystemVariable("DBMOD"); // Check the value of DBMOD, if 0 then the drawing has no unsaved changes
  33.         return (System.Convert.ToInt16(obj) == 0);
  34.       }
  35.     }
  36.        
  37.     public static bool TryClose(this Document doc)
  38.     {
  39.       if (doc.LockMode(true) != DocumentLockMode.NotLocked)
  40.       {
  41.         Cns.Warning("Файл " + Path.GetFileNameWithoutExtension(doc.Name) + " заблокирован. Закрыть не получится.");
  42.         return false;
  43.       }
  44.       try
  45.       {
  46.         doc.CommitAll();
  47.         doc.CloseAndDiscard();
  48.       }
  49.       catch (Exception e)
  50.       {
  51.         Cns.Warning("Попытка закрыть чертеж " + Path.GetFileNameWithoutExtension(doc.Name) + " не удалась. Ошибка: " + e.Message);
  52.         return false;
  53.       }
  54.       return true;
  55.     }
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: prajdziswet от 19-11-2017, 23:06:49
то я себе позволил небольшой "хак".
буду разбираться...Спасибо!!!
Команда конечно сессионная. Вот рабочий код (Cns - это мой класс для работы с консолью Автокада)
И тебе avc, Большое Спасибо..Как раз у меня получается наверное не совсем сессионная (и смотрю закрывать как я),это хорошо видно на accore.dll - автокад даже не успевает загрузится, как она идет на обработку...Так же получается при моем (простом закрытии через ".CloseAndDiscard();),еще автокад грузит лисп-ы в чертеж и длл в автокад (но автокад уже загружен и поэтому исключение у меня вываливается, но чертеж не доконца еще загружен)=> как я пытаюсь его закрыть...

Большое СПАСИБО за подсказки ... :)

п.с А закрытие можно реализовать как писал выше(но мне это вариант не очень нравится = лучше прочитаю решение Александра по снятию флага= это лучше). А решение может быть таким (но это "костыль" извиняюсь за название, но моймете по ходу рассуждения):
- так как в моем случае автокад .CloseAndDiscard() - выдает исключение, можно его вызывать через определение время..
т.е вызываем паралельный поток (чтобы автокад продолжал выполнять свои действия) выполняющий через определенное время допустим 1 сек (или таймер) закрытие файла..и пробуем закрывать файл пока он не закроет, так как файл закрыть можно только из основного потока вызываем наш метод через Invoke...

но это не очень красивое решение, как писал выше "костыль"....
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: avc от 19-11-2017, 23:43:22
Сама идея закрывать чертеж по событию его открытия - уже звучит бредово. Понятно что документ будет заблокирован и куча процессов его читает в этот момент. Поэтому я не долго мучился и сдался. Хотя полно случаев когда это нужно. Можно и без таймеров попробовать - повесить обработчик простоя OnIdle и ждать пока разблокирован будет файл. Все в одном потоке. Может даже ивок не понадобится.
Эх, вот бы было событие BeforeOpen и получало бы оно имя файла до того как его Автокад начнет открывать - вот тогда была б красота....
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: Дмитрий Загорулькин от 19-11-2017, 23:55:29
Эх, вот бы было событие BeforeOpen и получало бы оно имя файла до того как его Автокад начнет открывать - вот тогда была б красота....
Это (http://help.autodesk.com/view/OARX/2018/ENU/?guid=OREFNET-Autodesk_AutoCAD_ApplicationServices_DocumentCollection_DocumentCreateStarted) разве не оно?
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: Александр Ривилис от 20-11-2017, 00:16:55
Это разве не оно?
Имя файла в нём не известно.
Название: Re: Закрытие чертежа - "чертеж занят"?
Отправлено: prajdziswet от 20-11-2017, 08:12:20
Сама идея закрывать чертеж по событию его открытия - уже звучит бредово. Понятно что документ будет..
полностью согласен - но я привел, как вариант - хоть мне удобнее поступить (да и красивее будет), как предложил Александр...

Спасибо...(всегда что-то новое подчерпнешь...)