autosave

Автор Тема: autosave  (Прочитано 32031 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Привалов ДмитрийАвтор темы

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
autosave
« : 29-05-2015, 09:19:16 »
Добрый день!

Есть необходимость "допилить" Autosave автокада.

2 события для перехвата
database.BeginSave += new DatabaseIOEventHandler(database_BeginSave);
database.SaveComplete += new DatabaseIOEventHandler(database_EndSave);

Дальше нужно сделать
database.SaveAs()
SaveAs выдает ошибки
BeginSave - eFileSharingViolation
SaveComplete - вылетает без возврата ошибки

Испробовал функции с различными параметрами:
database.SaveAs()
document.Database.SaveAs
Результат тот же.
Если сделать отдельную команду, то все ОК, сохраняет. Т.е. SaveAs работает сам по себе

Отсюда предположение, что база заблокирована во время событий BeginSave и SaveComplete

Подскажите что можно сделать.

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: autosave
« Ответ #1 : 29-05-2015, 09:30:33 »
Если в обработчике событий через SaveAs ты пытаешься заменить текущий DWG файл, то я подозреваю, что это не удаётся по той причине, что на время работы кода в обработчике события  файл вероятно блокируется. Насколько я понимаю, твой алгоритм способствует появлению бесконечного цикла, ведь когда ты вызываешь SaveAs - снова срабатывают те же события, на которые ты повесил обработчики. В коде одного из обработчиков ты опять вызываешь сохранение и так до бесконечности (ситуация аля "у попа была собака"). Видимо для того, чтобы избежать подобных казусов сохранение в обработчике этих событий и было запрещено на уровне API.

А чем не устроила отдельная команда? Вариант, мягко говоря не самый лучший, но в качестве общей информации обозначаю: при помощи команды undefine можно спрятать команду (и определить свою с тем же именем), но вызвать оригинальную всё равно можно, если перед именем поставить точку (так что финт ушами - так себе), ну или пользователь может вызвать redefine, вернув оригинал в обычную область видимости.

Оффлайн Привалов ДмитрийАвтор темы

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Re: autosave
« Ответ #2 : 29-05-2015, 10:04:27 »
А чем не устроила отдельная команда?

Дело не в команде, а в несовершенстве Autosave.
Долго рассказывать, про проблемы с чертежами в конторе, расскажу про проблемы автосейва от Автодеска.

"Autosave" записывает бэкап в один файл, при нажатии на "_qsave" бэкап удаляется.
Т.к. если "_qsave" удачно, то как считает автодеск все гуд и бэкап не нужен.
Дальше, если пройдет глючное"_qsave" до следующего "Autosave",
То порушится автокад и сохраняемый чертеж, и не будет бэкапа!

Выход, поставить создавать bak файл. Будет копия предыдущего сохранения, Autosave ее не затирает.
bak файл легко убирается галочкой юзерами. Да и в принципе не нужен в папке чертежа, это будет промежуточный мусор, нужный только для восстановления.

Поэтому хорошо бы стандартный механизм допилить. папка, с записью всех копий файла через 10 минут в течении дня-трех.

Все готово, осталось только SaveAs запустить внутри Autosave.

А про "ты опять вызываешь сохранение и так до бесконечности" спасибо! Скорее всего это и есть причина падения в SaveComplete.


Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: autosave
« Ответ #3 : 29-05-2015, 10:07:31 »
Если речь о бэкапах, то я когда-то написал такое решение (возможно будет интересно). Ключевой момент в моём варианте - юзер сам должен решать, когда ему создавать очередной вариант резервной копии.

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: autosave
« Ответ #4 : 29-05-2015, 10:20:28 »
Хотя, согласно официальной документации, использовать undefine и redefine всё же не стоит:

Цитата: Autodesk ObjectARX for AutoCAD 2016 : Interoperability Guide > User Interface Considerations (Dialogs, Commands, Menus, and System Variables) >
Do Not Use UNDEFINE and REDEFINE Commands
 
Level
Requirement

Applies to
ObjectARX and .NET applications

You cannot use the UNDEFINE and REDEFINE AutoCAD commands. Using these commands can confuse users and can conflict with other applications. Particularly troublesome is the situation when QUIT, END, SAVE, OPEN, and NEW are redefined by more than one application. ObjectARX provides a variety of mechanisms for applications to receive control at these key events. (Refer to the Notification chapter in the ObjectARX Developer's Guide for a discussion of reactors.)

Оффлайн Doublefish

  • ADN Club
  • ****
  • Сообщений: 288
  • Карма: 10
  • AutoCAD Civil 3D
Re: autosave
« Ответ #5 : 29-05-2015, 10:23:58 »
Я пользую команду movebak из express tools для создания bak файлов в заданной папке.

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: autosave
« Ответ #6 : 29-05-2015, 10:31:36 »
Я пользую команду movebak из express tools для создания bak файлов в заданной папке.
я не вижу пользы в ней, т.к. она не даёт возможности откатиться к нужной версии чертежа. Каждое сохранение по прежнему переписывает этот единственный BACK. То, где лежит BACK-файл: рядом с DWG или в подкаталоге - это особой роли не играет (имхо). Ключевой момент - иметь возможность откатиться к нужной версии чертежа. BACK может оказаться повреждённым, как и оригинал, в виду того, что повреждённое состояние было сохранено.

Оффлайн Привалов ДмитрийАвтор темы

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Re: autosave
« Ответ #7 : 29-05-2015, 10:33:51 »
Если речь о бэкапах, то я когда-то написал такое решение (возможно будет интересно).

Близко к тому, что нужно, но логика нужна другая.
1. случаи аварийные, т.е. рядом с файлом не надо. Когда надо тогда и залезли в папку автосохранения. Также идет работа в сетевых папках.
2. механизм автосейва использовать удобнее, поставил 10 минут и забыл. не вызывая доп команды. Настраивается юзером, как угодно.
3. бэкап - постоянный спам, подлежащий удалению через 1-3 дня, т.е это локальная, очищаемая папка.

SaveComplete + Singleton + запирающий флаг, чтоб избежать зацикливания, скорее всего то, что нужно. Опробую.

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: autosave
« Ответ #8 : 29-05-2015, 10:43:48 »
1. случаи аварийные, т.е. рядом с файлом не надо. Когда надо тогда и залезли в папку автосохранения. Также идет работа в сетевых папках.
Мои пользователи в основном так же работают с файлами, расположенными в сети. Каталоги сохранения настраиваются посредством конфиг-файла, имеющего формат xml (он там, кстати, показан). При помощи конфига можно указывать как абсолютный, так и относительный путь к каталогу резервных копий (как правило, он там же - на сервере).

2. механизм автосейва использовать удобнее, поставил 10 минут и забыл. не вызывая доп команды.
Я отказался от этого, т.к. подобный подход способствует быстрому раздуванию каталогов с контрольными точками сохранения и по факту будет содержать огромное количество ненужных файлов, не соответствующих самой идее контрольных точек восстановления. Отдаю предпочтение осмысленному нажатию на кнопке создания контрольной точки сохранения, т.к. именно пользователь, а не автосэйв, имеет чёткое представление о том, когда целесообразней эту точку создать. Такие точки обозначают очередной пройденный этап проектирования, либо один из возможных вариантов решения (т.е. своего рода ветвление). В дальнейшем от какой-то ветки можно будет легко отказаться (в случае необходимости).

3. бэкап - постоянный спам, подлежащий удалению через 1-3 дня, т.е это локальная, очищаемая папка.
Я делаю отличие бэкапа от контрольной точки восстановления, созданной пользователем. Это разные понятия. Мой код создаёт именно контрольные точки, а не бэкапы.

SaveComplete + Singleton + запирающий флаг, чтоб избежать зацикливания, скорее всего то, что нужно.
Этой фразы я не понял. Польза обозначенного паттерна в данной ситуации мне так же не очевидна. Синглтон гарантирует, что объект некоторого класса всегда будет присутствовать в единственном экземпляре. Какое это отношение имеет к автосохранению и как может помочь - я не представляю.

Оффлайн Привалов ДмитрийАвтор темы

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Re: autosave
« Ответ #9 : 29-05-2015, 11:01:32 »
Мои пользователи так же работают с файлами, расположенными в сети. Каталоги сохранения настраиваются посредством конфиг-файла, имеющего формат xml (он там, кстати, показан). При помощи конфига можно указывать как абсолютный, так и относительный путь к каталогу резервных копий.
Это не спорю, можно.

способствует быстрому раздуванию каталогов.  т.к. именно пользователь имеет чёткое представление о том, когда целесообразней эту точку создать.
Каталог "сам почищу" до старта команды при старте, по дате файлов...это детали
имеет чёткое представление...спорить на эту тему не будем, у меня свои юзеры, у вас свои ;-)


Я различаю бэкап от контрольной точки восстановления
А мне не нужно нового термина - точка восстановления. это именно бэкап через заданный промежуток времени. Это именно то, что ожидают мои пользователи от Autosave. Наверное тоже не стоит спорить.

Этой фразы я не понял. Польза обозначенного паттерна в данной ситуации мне так же не очевидна.
Ок, какие еще варианты?)))

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: autosave
« Ответ #10 : 29-05-2015, 11:23:19 »
Ок, какие еще варианты?)))

Например такой:
Код - C# [Выбрать]
  1.   public sealed class ExtensionApplication : IExtensionApplication {
  2.     public void Initialize() {
  3.       Document doc = cad.DocumentManager.MdiActiveDocument;
  4.       if (null == doc)
  5.         return;
  6.       Database db = doc.Database;
  7.       Editor ed = doc.Editor;
  8.       using (doc.LockDocument()) {
  9.         using (Transaction tr = db.TransactionManager.StartTransaction()) {
  10.           ed.WriteMessage("\nThe \"{0}\" assembly successfully loaded.\n",
  11.             this.GetType().Assembly.Location);
  12.           db.SaveComplete += db_SaveComplete;
  13.           tr.Commit();
  14.         }
  15.       }
  16.     }
  17.  
  18.     private Boolean savingMarker = true;
  19.  
  20.     private void db_SaveComplete(object sender, DatabaseIOEventArgs e) {
  21.       if (savingMarker = !savingMarker)
  22.         return;
  23.       Database db = sender as Database;
  24.       if (null == db) {
  25.         return;
  26.       }
  27.       Document doc = cad.DocumentManager.MdiActiveDocument;
  28.       Editor ed = doc.Editor;
  29.      
  30.       using (doc.LockDocument()) {
  31.         try {
  32.           String path = Path.GetDirectoryName(doc.Name);
  33.           String fileName = Path.GetFileNameWithoutExtension(doc.Name);
  34.           StringBuilder sb = new StringBuilder();
  35.           sb.Append(Path.Combine(path, fileName));
  36.           DateTime time = DateTime.Now;
  37.           sb.AppendFormat("_{0}-{1}-{2}_{3}-{4}-{5}.bak", time.Year,
  38.             time.Month.ToString("D2"), time.Day.ToString("D2"),
  39.             time.Hour.ToString("D2"), time.Minute.ToString("D2"),
  40.             time.Second.ToString("D2"));
  41.           String fullName = sb.ToString();
  42.           db.SaveAs(fullName, DwgVersion.Current);
  43.           ed.WriteMessage("\nFile saved as '{0}'.", sb.ToString());
  44.         }
  45.         catch (System.Exception ex) {
  46.           ed.WriteMessage("Exception: '{0}'.", ex.Message);
  47.         }
  48.       }
  49.     }
  50.  
  51.     public void Terminate() {
  52.     }
  53.   }

В приведённом примере резервные копии сохраняются в том же каталоге, где хранится оригинал.

Цитата: AutoCAD Output
Command: NETLOAD

The "C:\public\Debug\DWG_save_sandbox\DWG_save_sandbox.R20.1.dll" assembly successfully loaded.

Command:
Command:
Command: _qsave
File saved as 'C:\public\data\test_2015-05-29_11-36-45.bak'.
Command:
Command:
Command: _qsave
File saved as 'C:\public\data\test_2015-05-29_11-36-46.bak'.
Command:
Command:
Command: _qsave
File saved as 'C:\public\data\test_2015-05-29_11-36-49.bak'.
Command:
Command:
Command: _qsave
File saved as 'C:\public\data\test_2015-05-29_11-36-51.bak'.
Command:
Command:
Command: _qsave
File saved as 'C:\public\data\test_2015-05-29_11-36-52.bak'.

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: autosave
« Ответ #11 : 29-05-2015, 11:34:27 »
Подправил код: изменил формат суффикса в имени сохранённой копии файла, а так же в консоль акада вывел имя этой копии.

Оффлайн Привалов ДмитрийАвтор темы

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Re: autosave
« Ответ #12 : 29-05-2015, 11:41:27 »
Например такой:
я тоже самое и написал, только словами))

SaveComplete - db.SaveComplete += db_SaveComplete;

запирающий флаг - private Boolean savingMarker = true;

Singleton - единственный экземпляр
(savingMarker и db_SaveComplete&SaveAs)

и тоже самое по сути у меня в коде ;-)

Кстати по поводу Singleton.
Если 2 раза вызвать netload выполняемой при загрузке библиотеки, не создаст ли она 2 события db.SaveComplete += db_SaveComplete;???

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: autosave
« Ответ #13 : 29-05-2015, 11:45:54 »
я тоже самое и написал...
и тоже самое по сути у меня в коде ;-)
Тогда я не понял причины наличия этого топика, ведь обозначенный мною выше код работает (без всяких "синглтонов"). Если у тебя такой же, то должен был работать и твой...

Singleton - единственный экземпляр
(savingMarker и db_SaveComplete&SaveAs)
Этой фразы я не понимаю, ну да ладно...

Цитировать
Кстати по поводу Singleton.
Если 2 раза вызвать netload выполняемой при загрузке библиотеки, не создаст ли она 2 события db.SaveComplete += db_SaveComplete;???
Опять не понимаю, при чём тут Singleton. Дважды в один и тот же AppDomain загрузить одну и ту же Assembly невозможно. Соответственно и регистрация событий будет выполнена лишь единожды, при первой (и ей же последней) загрузке управляемой сборки.

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
Re: autosave
« Ответ #14 : 29-05-2015, 11:57:04 »
Off-Topic: показать
У меня почему-то подозрение, что автору нужна система контроля версий.
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!