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

ADN Club => AutoCAD .NET API => Тема начата: Пашин Евгений от 30-09-2015, 09:10:12

Название: Получить имя папки, где находится запущенный dll-файл
Отправлено: Пашин Евгений от 30-09-2015, 09:10:12
Кроме шуток, не могу получить имя папки, где лежит запущенный dll-файл!

Код - vb.net [Выбрать]
  1.         MsgBox(Application.StartupPath) ' C:\Program Files\Autodesk\AutoCAD 2014
  2.  
  3.         MsgBox(Application.ExecutablePath) ' C:\Program Files\Autodesk\AutoCAD 2014\acad.exe
  4.  
  5.         MsgBox(Application.CommonAppDataPath) 'C:\ProgramData\Autodesk, Inc.\AutoCAD\R19.1.108.0.0
  6.  

Совсем не то показывает )))

Подскажите как получить место, где dll-лежит ))) Карму подниму )))
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Алексей Кулик от 30-09-2015, 09:29:47
Попробуй Assembly.GetExecutingAssembly( ).Location
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Пашин Евгений от 30-09-2015, 09:39:40
Алексей Кулик, спасибо )))

Код - vb.net [Выбрать]
  1.         Dim myPath As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
  2.  
  3.         MsgBox(myPath.Location)

Я бы точно сам не догадался! Или поиск решения занял бы большое количество времени!

_______________________________________________________________
Это я не понял )))) А почему Вашу карму можно мгновенно плюсовать? ))))
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Алексей Кулик от 30-09-2015, 10:29:20
Вот уж чего не знаю, того не знаю. Я за этими вещами не гонюсь :)
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Владимир Шу от 30-09-2015, 10:54:06
Для VB.NET можно еще использовать специфическую обертку
Код - vb.net [Выбрать]
  1. Dim path As String = My.Application.Info.DirectoryPath
Вернет папку, где лежит библиотека.
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Пашин Евгений от 30-09-2015, 11:03:11
Да, тоже работает!
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Пашин Евгений от 30-09-2015, 11:14:29
Да, тоже работает!

Мало того, это действительный путь к dll-файлу! А не к сборке )))

________________________________________________________________________________
Не понял как получилось двойное сообщение, я же просто подредактировать сообщение хотел...
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Александр Ривилис от 30-09-2015, 11:28:18
Мало того, это действительный путь к dll-файлу! А не к сборке )))
Не понял. О чем это ты?
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Дмитрий Загорулькин от 30-09-2015, 11:33:01
Off-Topic: показать
Что так скромно-то, всего +40? Не надо жадничать, накрути уж от души :)
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Пашин Евгений от 30-09-2015, 11:34:43
Не понял. О чем это ты?

Ну вообще-то я получил не полный путь к папке dll-файла, а лишь все папки, которые находятся до папки BIN\RELEASE...

Код - vb.net [Выбрать]
  1.         Dim myPath As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
  2.  
  3.         MsgBox(myPath.Location) ' Возвращает «D:\Пашин\Visual Studio 2013\Projects\AutoCAD_First_Button_After_Error\AutoCAD_First_Button_After_Error»

 В принципе мне и этого хватает... но вот код

Код - vb.net [Выбрать]
  1. Dim path As String = My.Application.Info.DirectoryPath ' Возвращает «D:\Пашин\Visual Studio 2013\Projects\AutoCAD_First_Button_After_Error\AutoCAD_First_Button_After_Error\bin\Release»

дает весь путь. Жаль, что нельзя отмечать несколько решений, как верные решения )))
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Пашин Евгений от 30-09-2015, 11:37:46
Что так скромно-то, всего +40? Не надо жадничать, накрути уж от души

Вот напишу приложение, которое будет кликать в одну точку и запущу )))) Пущай работает )))) А кстати раньше же работало по +1 к карме в час! Что случилось? Изменились правила?

А если честно, то Алексей Кулик так оперативно сработал, что даже жалко было бы поставить ему просто +1. Очень помогло его решение.
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Александр Ривилис от 30-09-2015, 11:38:24
Странно. Сколько я не проверял всегда получался правильный путь (т.е. каталог в котором непосредственно находится dll-файл).
Есть еще варианты:
Код - C# [Выбрать]
  1.     string curAssemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
  2.     string curAssemblyPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
  3.     string curAssemblyFullName = System.Reflection.Assembly.GetExecutingAssembly().GetName().FullName;
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Александр Ривилис от 30-09-2015, 11:40:01
А кстати раньше же работало по +1 к карме в час! Что случилось? Изменились правила?
Я снял это ограничение. Теперь верну назад. Из-за тебя. Не обсуждается.
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Пашин Евгений от 30-09-2015, 11:43:47
Из-за тебя.

Так я ж от радости, а не от злого умысла...
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Владимир Шу от 30-09-2015, 12:11:46
string curAssemblyPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
У меня этот метод частенько глючит.
Например на кнопке виси макрос:
Код - Auto/Visual Lisp [Выбрать]
  1. ^C^C_NETLOAD "C://ACAD_DLL//_AddMLeader//AddMLeader_2014.dll";bx_addmleader;
Если запускать именно этим макросом, то библиотека загрузится, но файлы будет искать в C:\Users\user\Documents\, соответственно часто ловлю ошибку типа :
Цитировать
************** Exception Text **************
System.IO.FileNotFoundException: Could not find file 'C:\Users\user\Documents\blockXML.xml'.
File name: 'C:\Users\user\Documents\blockXML.xml''

А если запускать руками, через netload и потом командой, то ошибки нет.
К слову, с My.Application.Info.DirectoryPath таких ошибок не возникает в принципе.
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Александр Ривилис от 30-09-2015, 12:17:04
Boxa.Shu,
Если есть возможность, то проверь что в этом случае возвращает Assembly.GetExecutingAssembly().GetName().FullName - должен быть полный путь к dll-файлу
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Владимир Шу от 30-09-2015, 12:23:06
Вечером смогу посмотреть... посмотрю, что там вылезет, может получится выделить тестовое приложение и устойчивым повторением ошибки.
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Пашин Евгений от 30-09-2015, 12:26:26
Что-то я уже запутался... Сейчас все сработало как надо - вернул полный путь к dll-файлу  :o

Код - vb.net [Выбрать]
  1.         Dim myPath As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
  2.  
  3.         MsgBox(myPath.Location)

Приношу свои извинения... Пора выпить чаю, нужно отдохнуть от компьютера.

А вот это код вернул следующее:

Код - vb.net [Выбрать]
  1.         Dim myNewPath As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
  2.  
  3.         MsgBox(myNewPath.FullName)

AutoCAD_First_Button_After_Error, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Александр Ривилис от 30-09-2015, 12:28:38
Еще вариант:
Код - C# [Выбрать]
  1. string codeBase = Assembly.GetExecutingAssembly().CodeBase;
  2. UriBuilder uri = new UriBuilder(codeBase);
  3. string path = Uri.UnescapeDataString(uri.Path);
  4. return Path.GetDirectoryName(path);
Вариант с Assembly.GetExecutingAssembly.Location, как пишут действительно работает не всегда:
http://stackoverflow.com/questions/52797/how-do-i-get-the-path-of-the-assembly-the-code-is-in
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Андрей Бушман от 30-09-2015, 12:32:21
У меня этот метод частенько глючит.
Сильно подозреваю, что это не метод глючит но, скорее всего, ты неверно указываешь путь в своём макросе.
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Пашин Евгений от 30-09-2015, 12:32:50
Вариант с Assembly.GetExecutingAssembly.Location, как пишут действительно работает не всегда

Ну слава богу, а то я подумал, что у меня с глазами не то творится.
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Владимир Шу от 30-09-2015, 12:34:19
Сильно подозреваю, что это не метод глючит но, скорее всего, ты неверно указываешь путь в своём макросе.
Библиотека то грузится и команда стартует...
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Александр Ривилис от 30-09-2015, 12:42:56
Такое чувство, что сборка копируется во временную директорию, а оттуда уже запускается...
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Андрей Бушман от 30-09-2015, 12:46:18
ариант с Assembly.GetExecutingAssembly.Location, как пишут действительно работает не всегда:
http://stackoverflow.com/questions/52797/how-do-i-get-the-path-of-the-assembly-the-code-is-in
Любопытно... Я как-то с этим ранее не сталкивался, всегда использовал
Код - C# [Выбрать]
  1. Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
Да и в юнит-тестах (как пишет автор по вашей ссылке) у меня проблем не возникало. Например, если у меня в настройках проекта определена GET_TEST_CASES_FROM_XML, то данные для test cases читаются из XML; в противном случае - из кода. Например, это видно здесь (https://bitbucket.org/Andrey-Bushman/acadkeyparser/src/e0565c481bdc6ebf65e96aa376edd1553aa8c56d/AcadKeyParser.UnitTests/data/LocalizedProduct_TryParse_BoolValues_Checking.cs?at=master&fileviewer=file-view-default) в строках 34 и 35.
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Андрей Бушман от 30-09-2015, 12:48:34
Такое чувство, что сборка копируется во временную директорию, а оттуда уже запускается...
А вот такое поведение у меня в юнит тестах бывало (вспомнил)! Я в блоге показывал  (http://bushman-andrey.blogspot.ru/2015/06/nunit-dll.html)как этим поведением можно управлять в NUnit. Вполне возможно, что аналогичные настройки имеются в TestDriven.NET и MbUnit GUI.
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Владимир Шу от 30-09-2015, 16:07:44
Виноват. Зря грешил на этот метод.
Гадом оказался метод load у XmlDocument, строчка №12. Несмотря на корректный путь и проверки, почему то берет путь "текущий" (иногда это путь к файлу с которым работаю) и прибавляет к нему имя файла...
В строчках 10 и 11, выводится абсолютно корректный путь, копирую из консоли, вставляю в адресную строку проводника, открывается нужный файл.

Я понимаю что не совсем четко по теме, но все таки, есть идеи?

Код - C# [Выбрать]
  1.             String path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
  2.             String inputFile = Path.Combine(path, "blockXML.xml");
  3.            
  4.             XmlDocument xml = new XmlDocument();
  5.            
  6.             if (File.Exists(inputFile))
  7.             {
  8.                 System.IO.FileStream fs = new System.IO.FileStream(inputFile,
  9.                     System.IO.FileMode.Open, System.IO.FileAccess.Read);
  10.                 acEd.WriteMessage("\n1-" + fs.Name);
  11.                 acEd.WriteMessage("\n2-" + inputFile);
  12.                 xml.Load(inputFile);
  13.             }
  14.             else
  15.             {
  16.                 throw new FileNotFoundException(inputFile);
  17.             }
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Дмитрий Загорулькин от 30-09-2015, 16:21:10
А что это мы поток без using используем? А зачем он там вообще нужен? Если его убрать, проблема остается?
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Андрей Бушман от 30-09-2015, 16:24:54
Boxa.Shu,

Набросай HelloWorld (команду акада) и выложи (не забудь к нему прикрепить и свой XML).
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Владимир Шу от 30-09-2015, 16:26:12
Если закоментить строчки 14-17 ничего не меняется.
Вот лог консоли в автокаде:
Command: _NETLOAD Assembly file name: "C://ACAD_DLL//_AddMLeader//AddMLeader_2014.dll"
Command: bx_addmleader
Укажите экземпляр блока:
1-C:\ACAD_DLL\_AddMLeader\blockXML.xml
2-C:\ACAD_DLL\_AddMLeader\blockXML.xml

Вот лог ошибки:

See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.

************** Exception Text **************
System.IO.FileNotFoundException: Could not find file 'C:\Users\user\Documents\blockXML.xml'.
File name: 'C:\Users\user\Documents\blockXML.xml'
Извините, вам запрещён просмотр содержимого спойлеров.

И все это безобразие только если загружать эту библиотеку макросом с палитры
Код - Auto/Visual Lisp [Выбрать]
  1. ^C^C_NETLOAD "C://ACAD_DLL//_AddMLeader//AddMLeader_2014.dll";bx_addmleader;

Если загрузить руками и запустить команду руками, то все тип топ. Работает как часы.
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Дмитрий Загорулькин от 30-09-2015, 16:40:12
Если закоментить строчки 14-17 ничего не меняется.
А я говорил про строки 8-10:
Код - C# [Выбрать]
  1.                 System.IO.FileStream fs = new System.IO.FileStream(inputFile,
  2.                     System.IO.FileMode.Open, System.IO.FileAccess.Read);
  3.                 acEd.WriteMessage("\n1-" + fs.Name);
Лучше их комментить. Зачем они? В любом случае, FileStream нужно "заворачивать" в using.
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Александр Ривилис от 30-09-2015, 16:54:56
И все это безобразие только если загружать эту библиотеку макросом с палитры

    ^C^C_NETLOAD "C://ACAD_DLL//_AddMLeader//AddMLeader_2014.dll";bx_addmleader;


Если загрузить руками и запустить команду руками, то все тип топ. Работает как часы.
А чего это у тебя двойные прямые слэши? Двойные только обратные должны быть.
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Владимир Шу от 30-09-2015, 17:06:55
Лучше их комментить. Зачем они? В любом случае, FileStream нужно "заворачивать" в using.
Только для тог, что бы проверит что этот файл нормально читается... это тестовая строка.

А чего это у тебя двойные прямы слэши? Двойные только обратные должны быть.
А Вы попробуйте, так как у меня написано - работает, а если с обратными, то нет.

Огромное спасибо Андрею. Сам дурак. Программку начал писать давно, один класс полностью отработал, отладил и забыл про него. Забыл, что в этом классе обращаюсь к xml файлу и там прописан относительный путь от текущего. Изменил на абсолютный и теперь все нормально.
ЗЫ.
Внимательнее нужно быть и писать код один раз...
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Александр Ривилис от 30-09-2015, 17:08:16
А Вы попробуйте, так как у меня написано - работает, а если с обратными, то нет.
Разницу между одиночными (один слэш) и двойными (два слэша) чувствуешь?
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Владимир Шу от 30-09-2015, 17:10:39
Разницу между одиночными (один слэш) и двойными (два слэша) чувствуешь?
Угу.
Голова совсем не варит к вечеру, да так
Код - Auto/Visual Lisp [Выбрать]
  1. ^C^C_NETLOAD "C:/ACAD_DLL/_AddMLeader/AddMLeader_2014.dll";
работает.
Есть принципиальная разница между этими записями?
Код - Auto/Visual Lisp [Выбрать]
  1. ^C^C_NETLOAD "C://ACAD_DLL//_AddMLeader//AddMLeader_2014.dll";
  2. ^C^C_NETLOAD "C:/ACAD_DLL/_AddMLeader/AddMLeader_2014.dll";
и то и то грузит dll, какие подводные камни?
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Алексей Кулик от 30-09-2015, 17:14:52
Boxa.Shu, что-то странное... По идее надо либо c:\\acad_dll\\... либо c:/acad_dll/
Но чтобы работало только так, как у тебя написано - впервые вижу.
---
Добавлено:
пока писал ответ, предыдущий пост был подправлен.
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Александр Ривилис от 30-09-2015, 17:50:47
и то и то грузит dll, какие подводные камни?
Какие именно - не знаю. Но боком выйти может. Есть правила, которые следует соблюдать, если не хочешь получить "нежданку". :)
Название: Re: Получить имя папки, где находится запущенный dll-файл
Отправлено: Андрей Бушман от 06-10-2015, 17:26:52
Какие именно - не знаю. Но боком выйти может.
В виду того, что ObjectARX написан на C++, то возможно будет интересно, опубликованное ниже (набросал пример на коленках), поскольку к нему [ObjectARX] это полностью применимо (комментарии должны быть понятны).

Примечание: особым образом хотелось бы обратить внимание на результаты вызова GetFullPathName, в зависимости от того, как был указан перед этим параметр в вызове функции SetCurrentDirectory - с указанием суффикса "\\" или без... Это я к тому, что порой наличие казалось бы безобидных обратных слешей может давать не тот результат, который возможно ожидался.

Код - C++ [Выбрать]
  1.    /*
  2.   The system keeps track of the process' current drive and directory, but it
  3.   does not keep track of the current directory for every drive. However, there
  4.   is some operating system support for handling current directories for
  5.   multiple drives. This support is offered via the process' environment
  6.   strings. For example, a process can have two environment variables, as shown
  7.   here:
  8.  
  9.     =C:=C:\Utility\Bin
  10.     =D:=D:\Program Files
  11.  
  12.   These variables indicate that the process' current directory for drive C is
  13.   \Utility\Bin and that its current directory for drive D is \Program Files.
  14.  
  15.   If you call a function, passing a drive-qualified name indicating a drive
  16.   that is not the current drive, the system looks in the process' environment
  17.   block for the variable associated with the specified drive letter. If the
  18.   variable for the drive exists, the system uses the variable's value as the
  19.   current directory. If the variable does not exist, the system assumes that
  20.   the current directory for the specified drive is its root directory.
  21.  
  22.   For example, if your process' current directory is C:\Utility\Bin and you
  23.   call CreateFile to open D:ReadMe.Txt, the system looks up the environment
  24.   variable =D:. Because the =D: variable exists, the system attempts to open
  25.   the ReadMe.Txt file from the D:\Program Files directory. If the =D: variable
  26.   did not exist, the system would attempt to open the ReadMe.Txt file from the
  27.   root directory of drive D. The Windows file functions never add or change a
  28.   drive-letter environment variable—they only read the variables.
  29.  
  30.   NOTE  
  31.   You can use the C run-time function _chdir or _wchdir instead of the Windows
  32.   SetCurrentDirectory function to change the current directory. The _chdir and
  33.   _wchdir function call SetCurrentDirectory internally, but _chdir also adds
  34.   or modifies the environment variables by calling SetEnvironmentVariable so
  35.   that the current directory of different drives is preserved.
  36.   */
  37.  
  38.   // There the sample of switching for different cases (current EXE file is
  39.   // located in the "D:\projects\richter-console" directory):
  40.  
  41.   TCHAR szCurDir[MAX_PATH];
  42.  
  43.   /* szCurDir has the C:\ */
  44.   DWORD cchLength = GetFullPathName(TEXT("C:"), MAX_PATH, szCurDir, NULL);
  45.  
  46.   // change the value of the CURRENT DIRECTORY OF DISK C:
  47.   SetEnvironmentVariable(TEXT("=C:"), TEXT("C:\\Temp\\sandbox"));
  48.  
  49.   // szCurDir has the C:\\Temp\\sandbox
  50.   cchLength = GetFullPathName(TEXT("C:"), MAX_PATH, szCurDir, NULL);
  51.  
  52.   // Set the disk without the \\ suffix
  53.   SetCurrentDirectory(TEXT("D:"));
  54.  
  55.   // szCurDir has the C:\Temp\sandbox
  56.   cchLength = GetFullPathName(TEXT("C:"), MAX_PATH, szCurDir, NULL);
  57.  
  58.   // szCurDir has the D:\projects\richter-console
  59.   cchLength = GetFullPathName(TEXT("D:"), MAX_PATH, szCurDir, NULL);
  60.  
  61.   // Set the disk without the \\ suffix
  62.   SetCurrentDirectory(TEXT("C:"));
  63.  
  64.   // szCurDir has the C:\Temp\sandbox
  65.   cchLength = GetFullPathName(TEXT("C:"), MAX_PATH, szCurDir, NULL);
  66.  
  67.   // Set the disk without the \\ suffix
  68.   _wchdir(TEXT("D:"));
  69.  
  70.   /* szCurDir has the D:\ */
  71.   cchLength = GetFullPathName(TEXT("D:"), MAX_PATH, szCurDir, NULL);
  72.  
  73.   // Set the disk with the \\ suffix
  74.   _wchdir(TEXT("D:\\"));
  75.  
  76.   /* szCurDir has the D:\ */
  77.   cchLength = GetFullPathName(TEXT("D:"), MAX_PATH, szCurDir, NULL);
  78.  
  79.   // change the value of the CURRENT DIRECTORY OF DISK D:
  80.   SetEnvironmentVariable(TEXT("=D:"), TEXT("D:\\SDK\\Autodesk"));
  81.  
  82.   // Warning: switch to other disk before the next calling of the
  83.   // GetFullPathName function
  84.   SetCurrentDirectory(TEXT("C:"));
  85.  
  86.   // szCurDir has the D:\SDK\Autodesk
  87.   cchLength = GetFullPathName(TEXT("D:"), MAX_PATH, szCurDir, NULL);
  88.  
  89.   // Set the disk with the \\ suffix
  90.   SetCurrentDirectory(TEXT("C:\\"));
  91.  
  92.   /* szCurDir has the C:\ */
  93.   cchLength = GetFullPathName(TEXT("C:"), MAX_PATH, szCurDir, NULL);