-
Всем привет! Сегодняшний вопрос, очень похож на вчерашний, но все равно подступиться к решению не удалось, слишком много непонятного на первых порах. Суть задачи в следующем: "Нужно в чертеж вставить вхождение блока, а при отсутствии описания блока в текущем чертеже, вставить его из внешнего файла". И мне даже удалось кое-что рабочее изобразить, но в таком случае нужно на диске иметь место с хранением отдельных *.dwg, что неудобно. Подскажите пожалуйста, как же мне грамотно добавить файл в сборку? Прикрутить вчерашний "Uri("pack://application:,...." не удалось, сколько не пробовал.. Да и заметил, что при добавлении файлов в проект, все они дублируются в папке проекта и тут вообще возникли сомнения, эти файлы вообще в *.dll добавляются? Или они так и остаются лежать снаружи и все работает до тех пор, пока я все запускаю с места разработки? Спасибо.
ps Извините, мудрено написал. Простая формулировка: "Как мне переделать "Sub InsertBlockDefFromFile" так, чтоб она добавляла определение в базу блоков чертежа не из внешнего файла, а из сборки".
pps И конечно буду очень рад, если кто-то посмотрит грамотность применения транзакции, блока Try...Catch т.п. Судя по форумам у новичков с этим всегда большие проблемы, вот и я не стал исключением.
Заранее благодарен всем неравнодушным. :)
Код целиком (Архив проекта во вложении):
Извините, вам запрещён просмотр содержимого спойлеров.
-
Никак ;D
Чтобы подобное изобразить, нужно идти по такому пути:
1. Извлечь файл чертежа из сборки на жесткий диск
2. Провести нужные процедуры с этим файлом в автокаде
3. Удалить файл с диска
-
Простая формулировка: "Как мне переделать "Sub InsertBlockDefFromFile" так, чтоб она добавляла определение в базу блоков чертежа не из внешнего файла, а из сборки".
Никак!!! Т.е. даже если ты будешь хранить блок (dwg-файл) в виде ресурсов в dll-файле, то тебе всё-равно придётся его оттуда вытащить в виде отдельного dwg-файла, а потом уже вставлять из этого файла.
Modis
Опередил! :)
-
Спасибо, а то я с этим URI.. уже как мартышка и очки... :D Получается, что по всей видимости можно не заморачиваться и оставлять все как есть. Все равно будет специальная папка для хранения *.dll, вот там можно и готовые dwg хранить.
ps Оперативность просто поражает. С такой поддержкой разработчиков можно горы свернуть! Спасибо!
(Жаль что нельзя 2 варианта отметить как правильные. Пришлось нажать первому. Надеюсь, Александр Наумович не обидится ;))
-
буду очень рад, если кто-то посмотрит грамотность применения транзакции
код не смотрел за неимением времени, да и читать язык гоблинов мне тяжеловато. :) По теме транзакции возможно будет интересно почитать эти (http://bushman-andrey.blogspot.ru/search/label/Transaction) темы.
-
Надеюсь, Александр Наумович не обидится ;))
Не обижусь. Если всё-таки решишь засунуть в ресурсы (имеет смысл только для того, чтобы чьи-то "шаловливые" ручки не испортили блок), то возможно эта ссылка тебе поможет понять как вытащить ресурс в файл: http://stackoverflow.com/questions/13031778/how-can-i-extract-a-file-from-an-embedded-resource-and-save-it-to-disk
-
Большое спасибо за ссылки, буду изучать. Судя по всему, сборка готова "проглотить" все (почти все), что ей предложат. Получается, что до тех пор пока microsoft/autodesk окончательно не прикрыли лавочку, можно в сборку засунуть старенький .dvb, и так вызывать самые объемные наработки на VBA, пока по их переписи не дойдут руки..) Извлек-запустил-удалил. Глупость еще та, но в целом, скажем с автоматическим созданием интерфейса, может получиться временный вполне рабочий костыль.
-
... Который с громким хрустом переломится, когда в AutoCAD не будет установлен Vba-enabler.
-
Если всё-таки решишь засунуть в ресурсы (имеет смысл только для того, чтобы чьи-то "шаловливые" ручки не испортили блок)
Все таки решился, но проблемы не заставили себя долго ждать, поэтому в очередной раз прошу помощи. На данный момент имеются вот такие наработки:
Извините, вам запрещён просмотр содержимого спойлеров.
Но процедура WriteResourceToFile при попытке отладки безжалостно выдает FatalError (см.прил.2), да так, что понять почему для меня пока не представляется возможным. Хотя файл в указанный папке исправно создает(см.прил.3).
Что касается процедуры Extract, то она также выдает ошибку (см. прил.4).
Пляски с бубном в проекте и в гугле к сожалению не помогли, поэтому вы моя последняя надежда. Помогите пожалуйста справиться. :-[
-
Я так и не понял почему, но твоя папка программой не воспринимается. Надеюсь ты ее создавал через контекстное меню обозревателя решений?!
Ну а в общем - вот так работает:
Public Shared Sub WriteResourceToFile(resourceName As String, fileName As String, path As String)
'проверяем наличие папки и создаем, если отсутсвет
If Directory.Exists(path).Equals(False) Then
Directory.CreateDirectory(path)
End If
Using resource = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)
'чтобы проверить (увидеть) имена ресурсов
For Each n In Assembly.GetExecutingAssembly().GetManifestResourceNames()
Windows.MessageBox.Show(n)
Next
'извлечение
Using br = New BinaryReader(resource)
File.
WriteAllBytes(IO.
Path.
Combine(path, fileName
), br.
ReadBytes(resource.
Length)) End Using
End Using
End Sub
<CommandMethod("artExtract")>
Public Shared Sub ExtractFile()
Call WriteResourceToFile("ExtractFromDLL.StarBlock.dwg", "sBlock.dwg", "C:\\art")
End Sub
-
Александр Пекшев aka Modis, art_rrc,
У меня не работает ваши коды, resource = null и соответственно фатал, а вот такой код кушается на ура.
Файлик 1.dwg запихнут в dll и нигде не отсвечивает.
Извините, вам запрещён просмотр содержимого спойлеров.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Rtm = Autodesk.AutoCAD.Runtime;
using System.Resources;
[assembly: Rtm.CommandClass(typeof(WriteResource.Commands))]
namespace WriteResource
{
public class Commands
{
public static void WriteResourceToFile(string resourceName , string fileName )
{
var names = Assembly.GetExecutingAssembly().GetManifestResourceNames();
using (Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream(names[0]))
{
using (var resReader = new ResourceReader(resource))
{
string resType;
byte[] resData;
resReader.GetResourceData(resourceName,
out resType, out resData);
int startIndex = 0;
for (int i = 0; i < resData.Length - 1; i++)
{
if (resData[i] == 0x41 &&
resData[i + 1] == 0x43 &&
resData[i + 2] == 0x31 &&
resData[i + 3] == 0x30 &&
resData[i + 4] == 0x32 &&
resData[i + 5] == 0x34)
{
startIndex = i;
break;
}
}
using (var file = new FileStream(@fileName, FileMode.OpenOrCreate))
{
file.Write(resData, startIndex, resData.Length - startIndex);
}
}
}
}
[Rtm.CommandMethod("artExtract")]
static public void artExtract()
{
WriteResourceToFile("1.dwg", "D:\\2.dwg");
}
}
}
PS.
И немного поворчу, я понимаю, что VB многое прощает, но все таки стоит указывать тип переменных с которыми работаете...
Как бонус, это поможет достаточно быстро перейти на C#, который таких вольностей не позволяет.
Using resource As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)
For Each n As String In Assembly.GetExecutingAssembly().GetManifestResourceNames()
acEd.WriteMessage(ControlChars.CrLf + n)
Next
Using br As BinaryReader = New BinaryReader(resource)
System.
IO.
File.
WriteAllBytes(IO.
Path.
Combine(Path, fileName
), br.
ReadBytes(resource.
Length)) End Using
End Using
-
Надеюсь ты ее создавал через контекстное меню обозревателя решений?!
Думаю, что да. ПКМ -> add... -> New Folder. А файлик забросил просто перетаскиванием из папки.
Ну а в общем - вот так работает
Здорово! Все получилось! Я даже на радостях сначала дописал проверку:
For Each iFile In Directory.GetFiles(path)
If IO.Path.Combine(path, fileName).ToString = iFile.ToString Then
File.
Delete(IO.
Path.
Combine(path, fileName
)) 'Windows.MessageBox.Show("Такой файл уже есть! Удаляем его!")
Exit For
End If
Next
Но потом с удивлением заметил, что даже при наличии файла все без проблем перезаписывается. Я считаю, что перезапись файлов ведет к определенным рискам, или раз не ругается, то и не захламлять код лишним циклом не стоит? Посоветуйте пожалуйста.
В коде от Boxa.Shu пока для меня слишком много непонятного, но уверен, что это станет отличным подспорьем для меня в ближайшем будущем.
VB многое прощает, но все таки стоит указывать тип переменных с которыми работаете...
Как бонус, это поможет достаточно быстро перейти на C#, который таких вольностей не позволяет.
Отличный совет! Большое спасибо!
-
Думаю, что да. ПКМ -> add... -> New Folder. А файлик забросил просто перетаскиванием из папки.
Нельзя так делать! Все нужно добавлять через контекстное меню обозревателя решений!
-
Нельзя так делать! Все нужно добавлять через контекстное меню обозревателя решений!
Это как? Properties -> Resources... ->Add Resource -> add existing file... ?
Но ведь твой код через:
Using br = New BinaryReader(resource)
File.
WriteAllBytes(IO.
Path.
Combine(path, fileName
), br.
ReadBytes(resource.
Length)) End Using
У меня вполне корректно работает.
-
Нельзя так делать! Все нужно добавлять через контекстное меню обозревателя решений!
Я добавлял через свойства проекта, как показал на картинке, так что не все. =о)
Понял почему получал null в resource, я функции скармливал только имя файла, вместо полного пути.
-
Это как? 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...
Ну что-то типа того) Я объяснять не умею :-)
-
P.S.: В VB.NET не нужно дублировать обратные слэши. Т.е. не "C:\\art", а "C:\art" и не "C:\\art\sBlock.dwg", а "C:\art\sBlock.dwg"
Обратные слэши дублируются в C-подобных языках (C/C++/C#) и Lisp
-
Спасибо большое всем за ответы. Буду доводить наработки до ума, с учетом ваших рекомендаций.