Как узнать в каком приложении создан dwg-файл?

Автор Тема: Как узнать в каком приложении создан dwg-файл?  (Прочитано 18279 раз)

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

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Как программно узнать в каком приложении создан dwg-файл?
Я имею ввиду линейку AutoCAD: AutoCAD Electrical, AutoCAD Architecture, AutoCAD Civil 3D, AutoCAD MEP ну и просто AutoCAD.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
1. Не плоди одинаковые темы в разных разделах. В других разделах я их удалю.
2. Однозначного ответа на твой вопрос нет.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Не плоди одинаковые темы в разных разделах. В других разделах я их удалю.

Если есть решение на Lisp, то оно мне тоже подойдет или на VBA. Эта информация не для меня.

Однозначного ответа на твой вопрос нет.

Я пока тоже не могу найти решение.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Можно определить какое приложение сейчас запущено. Можно пытаться искать "следы" от использования вертикального приложения, но это всё будет не достоверной информацией. Если чертеж создали в чистом AutoCAD, а потом редактировали в Civil 3D, то к кой категории его отнести? Или наоборот чертеж создали в Civil 3D, а потом открыли в чистом AutoCAD и удалили все следы использования Civil 3D? Короче говоря однозначного ответа на этот вопрос нет.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Печалька   :(

Оффлайн Виктор Чекалин

  • Administrator
  • *****
  • Сообщений: 694
  • Карма: 111
  • Skype: chekalin-v
Александр, А есть ли возможность определить в каком приложении был последний раз сохранен dwg файл? Думается мне это более реально, чем определить в каком приложении файл был создан изначально.

Я с dwg практически не работаю, но иногда приходится открывать файлы заказчика, а вот понять в каком именно приложении был сохранен этот файл, чтобы открыть его в том же самом и получить ту же же модель, что и заказчик - бывает проблематично. Конечно в итоге мы узнаем это у заказчика, но на это может уйти несколько дней.
В Revit к примеру такую информацию можно узнать, даже не открывая самого файла. Понятно, что структура разная, но все же может быть и в случае с dwg такая есть возможность.

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
И еще вопрос, а написанное в этой теме (http://adn-cis.org/forum/index.php?topic=2679.0) и первые 6 байт dwg файла, как то соотносятся или это совсем разное?

Извините, вам запрещён просмотр содержимого спойлеров.
Хотя конечно потрошить dwg файл, эт плохо.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Boxa.Shu
В любом случае открытого API для этой цели нет.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Согласно скрину Boxa.Shu указан ключ ACAD-A001:419, который соответствует обычному AutoCAD 2012 (R18.0) Rus.
Вообще по ключу можно определить наименование продукта, его версию и локализацию (т.е. программно выполнить парсинг этого ключа).
Цитировать
В любом случае открытого API для этой цели нет.
Если всегда ждать API, то можно ждать до пенсии :)

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
указан ключ ACAD-A001:419, который соответствует обычному AutoCAD 2012 (R18.0).
Я не знаю, это первый попавшийся файл из сети от смежников, понятия не имею в чем они его создавали и в чем он редактировался, но судя по кодам на скрине, получается что простой 2012.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
А есть ли возможность определить в каком приложении был последний раз сохранен dwg файл?
Если вытащить записанное в файле строковое представление ключа, то остальное будет не сложным. Например, для ключей:

Цитировать
ACAD-101:409
ACAD-D000:419
ACAD-F000:419
acad-7001:409
acadlt-9009:419

Результат в консоли получаю следующий:
Цитировать
AutoCAD key: ACAD-101:409
AutoCAD 2002 [R15.2] English (United States)

AutoCAD key: ACAD-D000:419
Autodesk Civil 3D 2014 [R19.1] Russian (Russia)

AutoCAD key: ACAD-F000:419
Autodesk Civil 3D 2016 [R20.1] Russian (Russia)

AutoCAD key: acad-7001:409
AutoCAD 2009 [R17.2] English (United States)

AutoCAD key: acadlt-9009:419
AutoCAD LT 2011 [R18.1] Russian (Russia)

Код тоже достаточно прост:
Код - C# [Выбрать]
  1. using System;
  2. using Bushman.CAD;
  3.  
  4. namespace sample {
  5.   class Program {
  6.     static void Main(string[] args) {
  7.       String key = String.Empty;
  8.       const String prompt = "AutoCAD key: ";
  9.       Console.Write(prompt);
  10.       while ((key = Console.ReadLine()).ToLower() != "q") {
  11.         ILocalizedProduct product = null;
  12.         Boolean result = LocalizedProduct.TryParse(key, out product);
  13.         if (result) {
  14.           Console.WriteLine("{0} {1} [R{2}.{3}] {4} ",
  15.             product.Name,
  16.             product.Year,
  17.             product.Version.Major,
  18.             product.Version.Minor,
  19.             product.Culture.EnglishName);
  20.         }
  21.         else {
  22.           Console.WriteLine("Invalid key of AutoCAD.");
  23.         }
  24.         Console.Write("\n" + prompt);
  25.       }
  26.     }
  27.   }
  28. }

вся "изюминка" заключается в отдельном XML файле, который, по мере появления новых версий акада, можно расширять новыми значениями:

Извините, вам запрещён просмотр содержимого спойлеров.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Виктор Чекалин
Однозначно можно лишь определить в формате какой версии AutoCAD сохранён файл (определяется первыми 6 символами файла). Но даже в какой версии сохраняли определить (используя публичные API) нельзя. Например, в AutoCAD 2016 можно сохранить в формате AutoCAD 2010.
Формат вертикальных приложений такой-же, как у чистого  AutoCAD.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Хотя конечно потрошить dwg файл, эт плохо.

Плохо и не очень надежно, но... Код не критиковать! :) Для формата файла AutoCAD до 2004 работать не будет, так как информация о приложении в нём не сохраняется.

Код - C# [Выбрать]
  1. using System;
  2. using System.IO;
  3. using System.Xml;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8.  
  9. namespace GetDwgSaveInfo
  10. {
  11.   class Program
  12.   {
  13.     static void Main(string[] args)
  14.     {
  15.       if (args.Length > 0)
  16.       {
  17.         string name = "", build_version = "", registry_version = "";
  18.         string app = GetDwgFileSavedApp(args[0], ref name,
  19.           ref build_version, ref registry_version);
  20.         Console.WriteLine("Application = {0} Name = {1} Build Version = {2} Registry Version = {3}",
  21.           app, name, build_version, registry_version);
  22.       }
  23.       else
  24.       {
  25.         Console.WriteLine("DWG-filename not provided");
  26.       }
  27.       Console.WriteLine("---- Press any key ----"); Console.ReadKey();
  28.     }
  29.  
  30.  
  31.     /// <summary>
  32.     /// Получение имени приложения, в котором сохранён dwg-файл.
  33.     /// </summary>
  34.     /// <param name="dwgfilepath">Путь к dwg-файлу.</param>
  35.     /// <param name="name">Имя приложения.</param>
  36.     /// <param name="build_version">Версия exe-файла.</param>
  37.     /// <param name="registry_version">Версия в реестре.</param>
  38.     /// <returns></returns>
  39.     public static string GetDwgFileSavedApp(string dwgfilepath,
  40.       ref string name,
  41.       ref string build_version,
  42.       ref string registry_version)
  43.     {
  44.       const string Desc = "<ProductInformation name =";
  45.       try
  46.       {
  47.         string line = System.IO.File.ReadAllText(dwgfilepath, Encoding.Unicode);
  48.         int lineStart = line.IndexOf(Desc);
  49.         int lineEnd = line.IndexOf("\0", lineStart + 1);
  50.         string s = new StringBuilder(line.Substring(lineStart, lineEnd-lineStart))
  51.           .Replace("\\\"", "\"").ToString();
  52.         using (XmlReader reader = XmlReader.Create(new StringReader(s)))
  53.         {
  54.           reader.Read();
  55.           name = reader.GetAttribute("name");
  56.           build_version = reader.GetAttribute("build_version");
  57.           registry_version = reader.GetAttribute("registry_version");
  58.           return reader.GetAttribute("install_id_string");
  59.         }
  60.       }
  61.       catch { };
  62.       return null;
  63.     }
  64.   }
  65. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Код не критиковать!
Вы же знаете, что я так "не играю"... :)
Цитировать
Плохо и не очень надежно
Согласен, применительно к текущей версии кода.  :P

Некоторые моменты сразу бросаются в глаза... Куда подевали проверку первых шести байтов на предмет того, новее ли это чем 2004-й? Почему не проверяете значение переменных lineStart и lineEnd? Мало ли, ведь DWG мог быть сгенерирован не автокадом, но сторонним приложением (например работающем на основе платформы ODA или какой-нибудь другой).

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Некоторые моменты сразу бросаются в глаза... Куда подевали проверку первых шести байтов на предмет того, новее ли это чем 2004-й? Почему не проверяете значение переменных lineStart и lineEnd? Мало ли, ведь DWG мог быть сгенерирован не автокадом, но сторонним приложением (например работающем на основе платформы ODA или какой-нибудь другой).
Проверка первых 6 байт в данном случае смысла не имеет - меня не интересует в формате какой версии сохраняли файл. Меня интересует каким приложением и какой версией это было сделано. Если в файле этой информации нет, то функция вернёт null. Так как стоят try/catch, то проверка lineStart и lineEnd смысла не имеют. Что будет в случае ODA меня честно говоря не слишком интересует (и на этом форуме не обсуждаем), но и с ним аварийного завершения не будет. Если они сделали по образцу и подобию AutoCAD, то должна получится нормальная информация, если нет - то будет null.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Если в файле этой информации нет, то функция вернёт null. Так как стоят try/catch, то проверка lineStart и lineEnd смысла не имеют.
Если в случае пакетной обработки исключение будет происходить часто, то скорость обработки будет отвратительной - вам это прекрасно известно. Тогда почему бы сразу, предусмотрительно, не избегать try\catch, если это можно сделать без особого труда?

Что будет в случае ODA меня честно говоря не слишком интересует (и на этом форуме не обсуждаем)
А меня как раз интересует именно практическое применение кода, а не сферические кони в вакууме. Мы нередко получаем от сторонних организаций DWG, созданные не в автокаде.
Если они сделали по образцу и подобию AutoCAD, то должна получится нормальная информация, если нет - то будет null.
Оно понятно, но предусмотреть обратный поворот событий не мешало бы (имхо).

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А меня, как раз, интересует практическое применение, а не сферические кони в вакууме.
Вот и проверь. В действительности в коде есть значительно более грубая вещь - чтение всего файла в память, которую следовало бы избежать. По сравнению с этим все остальные прегрешения - мелочь...

Кстати проверил файл, созданный не в AutoCAD. Вполне приличная информация:
Цитировать
C:\Temp>GetDwgSaveInfo.exe Проверка.dwg
Application = ODA Name = Teigha(R).NET for .dwg files Build Version = 2.5 Registry Version = 3.8
---- Press any key ----
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Если в случае пакетной обработки исключение будет происходить часто, то скорость обработки будет отвратительной
Это при чтении файлов? Да вообще фиолетово, в зависимости от машины - дельта будет ну где то 5 секунд МАКСИМУМ на порядка 100000 файлов - это в крайнем случае - то есть если все выдали ошибку - это конечно ужасная разница.

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
За ваши ответы +500 к карме каждому! Андрей Бушман и Boxa.Shu, вам отдельное спасибо, что вытащили вопрос к решению!

Александр, а файл GetDwgSaveInfo.exe точно не вирус, а то мой Symantec Endpoint Protection ну никак не хочет его запускать!

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Александр, а файл GetDwgSaveInfo.exe точно не вирус, а то мой Symantec Endpoint Protection ну никак не хочет его запускать!
Точно. Можешь сам скомпилировать его из исходника, который я выложил.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Это при чтении файлов? Да вообще фиолетово, в зависимости от машины - дельта будет ну где то 5 секунд МАКСИМУМ на порядка 100000 файлов - это в крайнем случае - то есть если все выдали ошибку - это конечно ужасная разница.
Как говорится, обожгёшься на молоке - будешь дуть на воду. Вот пример существенной разницы в скорости. В обозначенном примере я выполнял полную итерацию по всем объектам базы данных чертежа. Чертёж 50 Мб, количество объектов - 736 323. Один из обозначенных способов использовал try\catch, отлавливая ошибки. Два другие используют подходы в которых исключение не генерируется.

Время полной итерации по всем объектам базы данных чертежа в варианте с try\catch составило 05 мин. 36,1859781 сек.
Та же самая операция, но без try\catch для двух других вариантов заняла 0 мин. 14,1793398 сек. и 0 мин. 0,2781968 сек. соответственно.

Как видим, на больших объёмах данных разница может оказаться существенной: в одном случае операция заняла даже менее половины секунды, в то время как в другом - более 5,5 мин. В процессе работы возникало около 100 000 исключений. Конечно, при пакетной обработке файлов, применительно к данной задаче, их будет значительно меньше. Однако я считаю, что если есть возможность избавитья от try\catch, то лучше было бы это сделать (имхо). Его можно было бы оставить, как перестраховку, но добавить логику проверки, которая позволила бы избежать лишние появления исключений.

Отмечено как Решение Пашин Евгений 03-09-2015, 10:21:27

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Я что-то важное пропустил...

Пришлось код Александра переписать на VB

Взял форму, установил кнопку на форму и вот это код вписал:

Код - vb.net [Выбрать]
  1. Imports System.IO
  2. Imports System.Text
  3. Imports System.Xml
  4. Imports System.Collections.Generic
  5. Imports System.Linq
  6. Imports System
  7. Imports System.Threading.Tasks
  8.  
  9. Public Class Form1
  10.     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
  11.         Dim Name As String = "", Build_Version As String = "", Registry_Version As String = ""
  12.         Const Desc As String = "<ProductInformation name ="
  13.         Try
  14.             Dim line As String = System.IO.File.ReadAllText("C:\Users\Pashin.Evgeniy\Desktop\Чертеж_Civil3D_пустой.dwg", Encoding.Unicode)
  15.             Dim lineStart As Integer = line.IndexOf(Desc)
  16.             Dim lineEnd As Integer = line.IndexOf(">", lineStart + 1)
  17.             Dim s As String = New StringBuilder(line.Substring(lineStart, lineEnd - lineStart)).Replace("\""", """").ToString()
  18.             s = s & ">"
  19.             Dim reader As XmlReader = XmlReader.Create(New StringReader(s))
  20.             Using (reader)
  21.                 reader.Read()
  22.                 Name = reader.GetAttribute("name")
  23.                 Build_Version = reader.GetAttribute("build_version")
  24.                 Registry_Version = reader.GetAttribute("install_id_string")
  25.             End Using
  26.             MsgBox(Registry_Version)
  27.         Catch ex As Exception
  28.             MsgBox(ex.Message) ' "Ну, что опять не так?"
  29.         End Try
  30.     End Sub
  31. End Class

Работает! Но файл пустой. А с файлом какого размера будет гораздо медленнее? Файл 7.9 Мб тоже быстро. Может я что-то не понял?


Переписал файл чертежа в AutoCAD и Registry Version изменился... Жаль, что нет аттрибута, который бы отвечал за название исходного приложения.

Все равно подойдет! Всем большое спасибо!

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Как говорится, обожгёшься на молоке - будешь дуть на воду.
Тут Вы как-бы об кастрюлю обожглись - в смысле не туда дуете. try->catch действительно медленная операция, но не на ту разницу, что в Вашем примере. Однозначно необходимы дополнительные проверки, либо при очень большом кол-ве итераций, либо когда проверяемая процедура имеет долгую обработку при получении ошибочных данных (например введя в строку браузера левый адрес - он долго будет понимать, что его нет) - как в Вашем случае - то есть минуты у Вас появились, не из-за того что долго работала try->catch, а из-за долгой работы TargetDb.GetObjectId в случае ошибки. Проверьте сами какая будет разница в секундах если проверять 100000 чисел деленных на ноль, проверкой делителя и через try catch - вот Вам и будет реальная разница.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А с файлом какого размера будет гораздо медленнее? Файл 7.9 Мб тоже быстро. Может я что-то не понял?
Дело не в скорости (хотя это тоже важно). В случае если чертеж будет размером в сотни мегабайт (или даже гигабайты) не исключено что алгоритм не сработает. Возможно в этом случае будет активное использование виртуальной памяти и это приведёт к сильному замедлению. Но на чертежах меньшего размера я не вижу повода для беспокойства.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Дело не в скорости (хотя это тоже важно). В случае если чертеж будет размером в сотни мегабайт (или даже гигабайты) не исключено что алгоритм не сработает. Возможно в этом случае будет активное использование виртуальной памяти и это приведёт к сильному замедлению. Но на чертежах меньшего размера я не вижу повода для беспокойства.
Понятно.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
минуты у Вас появились, не из-за того что долго работала try->catch, а из-за долгой работы TargetDb.GetObjectId в случае ошибки
Я это прекрасно понимаю и не утверждал, что причина такой разницы во времени находится в использовании конструкции try\catch. Причина, понятное дело, в возникающих Exception, на обработку которых в try\catch и происходят дополнительные затраты времени. :) Я высказал своё мнение и пояснил причины, лежащие в его основе. Править код с учётом этих замечаний или нет - это уж каждый как хочет. )