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

ADN Club => AutoCAD .NET API => Тема начата: art_rrc от 22-10-2015, 15:23:00

Название: Вставка блока в чертеж из Сборки.dll
Отправлено: art_rrc от 22-10-2015, 15:23:00
Всем привет! Сегодняшний вопрос, очень похож на вчерашний, но все равно подступиться к решению не удалось, слишком много непонятного на первых порах. Суть задачи в следующем: "Нужно в чертеж вставить вхождение блока, а при отсутствии описания блока в текущем чертеже, вставить его из внешнего файла". И мне даже удалось кое-что рабочее изобразить, но в таком случае нужно на диске иметь место с хранением отдельных *.dwg, что неудобно. Подскажите пожалуйста, как же мне грамотно добавить файл в сборку? Прикрутить вчерашний "Uri("pack://application:,...." не удалось, сколько не пробовал.. Да и заметил, что при добавлении файлов в проект, все они дублируются в папке проекта и тут вообще возникли сомнения, эти файлы вообще в *.dll добавляются? Или они так и остаются лежать снаружи и все работает до тех пор, пока я все запускаю с места разработки? Спасибо.
ps Извините, мудрено написал. Простая формулировка: "Как мне переделать "Sub InsertBlockDefFromFile" так, чтоб она добавляла определение в базу блоков чертежа не из внешнего файла, а из сборки".
pps И конечно буду очень рад, если кто-то посмотрит грамотность применения транзакции, блока Try...Catch т.п. Судя по форумам у новичков с этим всегда большие проблемы, вот и я не стал исключением.
Заранее благодарен всем неравнодушным.  :)

Код целиком (Архив проекта во вложении):
Извините, вам запрещён просмотр содержимого спойлеров.
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: Александр Пекшев aka Modis от 22-10-2015, 15:25:55
Никак  ;D
Чтобы подобное изобразить, нужно идти по такому пути:
1. Извлечь файл чертежа из сборки на жесткий диск
2. Провести нужные процедуры с этим файлом в автокаде
3. Удалить файл с диска
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: Александр Ривилис от 22-10-2015, 15:27:07
Простая формулировка: "Как мне переделать "Sub InsertBlockDefFromFile" так, чтоб она добавляла определение в базу блоков чертежа не из внешнего файла, а из сборки".
Никак!!! Т.е. даже если ты будешь хранить блок (dwg-файл) в виде ресурсов в dll-файле, то тебе всё-равно придётся его оттуда вытащить в виде отдельного dwg-файла, а потом уже вставлять из этого файла.

Modis
Опередил! :)
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: art_rrc от 22-10-2015, 15:33:00
Спасибо, а то я с этим URI.. уже как мартышка и очки...   :D Получается, что по всей видимости можно не заморачиваться и оставлять все как есть. Все равно будет специальная папка для хранения *.dll, вот там можно и готовые dwg хранить.
ps Оперативность просто поражает. С такой поддержкой разработчиков можно горы свернуть! Спасибо!
(Жаль что нельзя 2 варианта отметить как правильные. Пришлось нажать первому. Надеюсь, Александр Наумович не обидится  ;))
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: Андрей Бушман от 22-10-2015, 15:37:46
буду очень рад, если кто-то посмотрит грамотность применения транзакции
код не смотрел за неимением времени, да и читать язык гоблинов мне тяжеловато. :) По теме транзакции возможно будет интересно почитать эти (http://bushman-andrey.blogspot.ru/search/label/Transaction) темы.
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: Александр Ривилис от 22-10-2015, 15:49:46
Надеюсь, Александр Наумович не обидится  ;))
Не обижусь. Если всё-таки решишь засунуть в ресурсы (имеет смысл только для того, чтобы чьи-то "шаловливые" ручки не испортили блок), то возможно эта ссылка тебе поможет понять как вытащить ресурс в файл: http://stackoverflow.com/questions/13031778/how-can-i-extract-a-file-from-an-embedded-resource-and-save-it-to-disk
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: art_rrc от 22-10-2015, 18:05:29
Большое спасибо за ссылки, буду изучать. Судя по всему, сборка готова "проглотить" все (почти все), что ей предложат. Получается, что до тех пор пока microsoft/autodesk окончательно не прикрыли лавочку, можно в сборку засунуть старенький .dvb, и так вызывать самые объемные наработки на VBA, пока по их переписи не дойдут руки..) Извлек-запустил-удалил. Глупость еще та, но в целом, скажем с автоматическим созданием интерфейса, может получиться временный вполне рабочий костыль.
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: Алексей Кулик от 23-10-2015, 01:04:07
... Который с громким хрустом переломится, когда в AutoCAD не будет установлен Vba-enabler.
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: art_rrc от 29-10-2015, 14:11:17
Если всё-таки решишь засунуть в ресурсы (имеет смысл только для того, чтобы чьи-то "шаловливые" ручки не испортили блок)
Все таки решился, но проблемы не заставили себя долго ждать, поэтому в очередной раз прошу помощи. На данный момент имеются вот такие наработки:
Извините, вам запрещён просмотр содержимого спойлеров.
Но процедура WriteResourceToFile при попытке отладки безжалостно выдает FatalError (см.прил.2), да так, что понять почему для меня пока не представляется возможным. Хотя файл в указанный папке исправно создает(см.прил.3).
Что касается процедуры Extract, то она также выдает ошибку (см. прил.4).
Пляски с бубном в проекте и в гугле к сожалению не помогли, поэтому вы моя последняя надежда. Помогите пожалуйста справиться. :-[
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: Александр Пекшев aka Modis от 29-10-2015, 15:24:18
Я так и не понял почему, но твоя папка программой не воспринимается. Надеюсь ты ее создавал через контекстное меню обозревателя решений?!

Ну а в общем - вот так работает:
Код - vb.net [Выбрать]
  1. Public Shared Sub WriteResourceToFile(resourceName As String, fileName As String, path As String)
  2.     'проверяем наличие папки и создаем, если отсутсвет
  3.     If Directory.Exists(path).Equals(False) Then
  4.         Directory.CreateDirectory(path)
  5.     End If
  6.     Using resource = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)
  7.         'чтобы проверить (увидеть) имена ресурсов
  8.         For Each n In Assembly.GetExecutingAssembly().GetManifestResourceNames()
  9.             Windows.MessageBox.Show(n)
  10.         Next
  11.         'извлечение
  12.         Using br = New BinaryReader(resource)
  13.             File.WriteAllBytes(IO.Path.Combine(path, fileName), br.ReadBytes(resource.Length))
  14.         End Using
  15.     End Using
  16. End Sub
  17. <CommandMethod("artExtract")>
  18. Public Shared Sub ExtractFile()
  19.     Call WriteResourceToFile("ExtractFromDLL.StarBlock.dwg", "sBlock.dwg", "C:\\art")
  20. End Sub
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: Владимир Шу от 29-10-2015, 16:06:26
Александр Пекшев aka Modis, art_rrc,
У меня не работает ваши коды, resource  = null и соответственно фатал, а вот такой код кушается на ура.
Файлик 1.dwg запихнут в dll и нигде не отсвечивает.
Извините, вам запрещён просмотр содержимого спойлеров.
Код - C# [Выбрать]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.IO;
  8. using Rtm = Autodesk.AutoCAD.Runtime;
  9. using System.Resources;
  10.  
  11. [assembly: Rtm.CommandClass(typeof(WriteResource.Commands))]
  12.  
  13. namespace WriteResource
  14. {
  15.     public class Commands
  16.     {
  17.         public static void WriteResourceToFile(string resourceName , string fileName )
  18.         {
  19.  
  20.             var names = Assembly.GetExecutingAssembly().GetManifestResourceNames();
  21.             using (Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream(names[0]))
  22.             {
  23.                 using (var resReader = new ResourceReader(resource))
  24.                 {
  25.                     string resType;
  26.                     byte[] resData;
  27.  
  28.                     resReader.GetResourceData(resourceName,
  29.                         out resType, out resData);
  30.  
  31.                     int startIndex = 0;
  32.  
  33.                     for (int i = 0; i < resData.Length - 1; i++)
  34.                     {
  35.                         if (resData[i] == 0x41 &&
  36.                             resData[i + 1] == 0x43 &&
  37.                             resData[i + 2] == 0x31 &&
  38.                             resData[i + 3] == 0x30 &&
  39.                             resData[i + 4] == 0x32 &&
  40.                             resData[i + 5] == 0x34)
  41.                         {
  42.                             startIndex = i;
  43.                             break;
  44.                         }
  45.                     }
  46.  
  47.                     using (var file = new FileStream(@fileName, FileMode.OpenOrCreate))
  48.                     {
  49.                         file.Write(resData, startIndex, resData.Length - startIndex);
  50.                     }
  51.                 }
  52.             }
  53.         }
  54.        
  55.         [Rtm.CommandMethod("artExtract")]
  56.         static public void artExtract()
  57.         {
  58.             WriteResourceToFile("1.dwg", "D:\\2.dwg");
  59.         }
  60.     }
  61. }
PS.
И немного поворчу, я понимаю, что VB многое прощает, но все таки стоит указывать тип переменных с которыми работаете...
Как бонус, это поможет достаточно быстро перейти на C#, который таких вольностей не позволяет.
Код - vb.net [Выбрать]
  1.         Using resource As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)
  2.             For Each n As String In Assembly.GetExecutingAssembly().GetManifestResourceNames()
  3.                 acEd.WriteMessage(ControlChars.CrLf + n)
  4.             Next
  5.             Using br As BinaryReader = New BinaryReader(resource)
  6.                 System.IO.File.WriteAllBytes(IO.Path.Combine(Path, fileName), br.ReadBytes(resource.Length))
  7.             End Using
  8.         End Using
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: art_rrc от 29-10-2015, 16:57:55
Надеюсь ты ее создавал через контекстное меню обозревателя решений?!
Думаю, что да. ПКМ -> add... -> New Folder. А файлик забросил просто перетаскиванием из папки.
Ну а в общем - вот так работает
Здорово! Все получилось! Я даже на радостях сначала дописал проверку:
Код - vb.net [Выбрать]
  1. For Each iFile In Directory.GetFiles(path)
  2.                     If IO.Path.Combine(path, fileName).ToString = iFile.ToString Then
  3.                         File.Delete(IO.Path.Combine(path, fileName))
  4.                         'Windows.MessageBox.Show("Такой файл уже есть! Удаляем его!")
  5.                         Exit For
  6.                     End If
  7.                 Next
Но потом с удивлением заметил, что даже при наличии файла все без проблем перезаписывается. Я считаю, что перезапись файлов ведет к определенным рискам, или раз не ругается, то и не захламлять код лишним циклом не стоит? Посоветуйте пожалуйста.
В коде от Boxa.Shu пока для меня слишком много непонятного, но уверен, что это станет отличным подспорьем для меня в ближайшем будущем.
VB многое прощает, но все таки стоит указывать тип переменных с которыми работаете...
Как бонус, это поможет достаточно быстро перейти на C#, который таких вольностей не позволяет.
Отличный совет! Большое спасибо!
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: Александр Пекшев aka Modis от 29-10-2015, 17:02:05
Думаю, что да. ПКМ -> add... -> New Folder. А файлик забросил просто перетаскиванием из папки.
Нельзя так делать! Все нужно добавлять через контекстное меню обозревателя решений!
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: art_rrc от 29-10-2015, 17:14:41
Нельзя так делать! Все нужно добавлять через контекстное меню обозревателя решений!
Это как? Properties -> Resources... ->Add Resource -> add existing file... ?
Но ведь твой код через:
Код - vb.net [Выбрать]
  1. Using br = New BinaryReader(resource)
  2.             File.WriteAllBytes(IO.Path.Combine(path, fileName), br.ReadBytes(resource.Length))
  3.         End Using
У меня вполне корректно работает.
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: Владимир Шу от 29-10-2015, 17:19:46
Нельзя так делать! Все нужно добавлять через контекстное меню обозревателя решений!
Я добавлял через свойства проекта, как показал на картинке, так что не все. =о)
Понял почему получал null в resource, я функции скармливал только имя файла, вместо полного пути.
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: Александр Пекшев aka Modis от 29-10-2015, 17:33:41
Это как? Properties -> Resources... ->Add Resource -> add existing file... ?
Нет, я не про это. Это совсем уже другое - если добавлять так, то твой код можно упростить (Если, допустим у тебя в ресурсах будет всего один файл, которой ты знаешь как называется, то его получать можно напрямую из Properties.Reources.FileName)
А в обозревателе проекта нужно добавлять файлы через контекстное меню (как и создавать папки) - ПКМ-Добавить-Существующий элемент (ПКМ-Добавить-Создать папку). Как в заморской версии это звучит не знаю, но думаю догадаться можно. При этом все эти папки и файлы записываются в какой-то там спец файл для компиляции.
ПКМ -> add... -> New Folder. А файлик забросил просто перетаскиванием из папки.
А т.к. ты файлик забросил просто перетаскиванием, то правильный путь не прописался. А когда ты поставил EmbeddedResource, тогда уже все прописалось, только проигнорировав папку. В итоге это Call WriteResourceToFile("ExtractFromDLL.StarBlock.dwg", "sBlock.dwg", "C:\\art") работало, а это  Call WriteResourceToFile("ExtractFromDLL.BlocksFolder.StarBlock.dwg", "C:\\art\sBlock.dwg") - не работало, хотя файл и лежал в папке BlocksFolder...
Ну что-то типа того) Я объяснять не умею :-)
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: Александр Ривилис от 29-10-2015, 17:39:07
P.S.: В VB.NET не нужно дублировать обратные слэши. Т.е. не "C:\\art", а "C:\art" и не "C:\\art\sBlock.dwg", а "C:\art\sBlock.dwg"
Обратные слэши дублируются в C-подобных языках (C/C++/C#) и Lisp
Название: Re: Вставка блока в чертеж из Сборки.dll
Отправлено: art_rrc от 29-10-2015, 18:34:21
Спасибо большое всем за ответы. Буду доводить наработки до ума, с учетом ваших рекомендаций.