Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Bolonat от Ноябрь 01, 2017, 08:10



Название: Как получить имя модуля dll
Отправлено: Bolonat от Ноябрь 01, 2017, 08:10
Здравствуйте!
Мне нужно получить наименование dll и полный путь к ней. Для этого в dll использую функцию WINAPI GetModuleFileName():
Код:
char dllname[_MAX_PATH] = {0};
::GetModuleFileName( NULL, (LPWSTR)dllname, sizeof(dllname) );
QString qstr=dllname;
qDebug()<<qstr;
В результате в dllname получаю массив символов Unicode - полный путь и имя .exe файла, загружающего dll.
Как сделать правильно?



Название: Re: Как получить имя модуля dll
Отправлено: Bolonat от Ноябрь 01, 2017, 10:08
Какой-то замкнутый круг получается... Я получаю путь и  имя exe вместо пути и имени dll, потому что в GetModuleFileName() указываю первый параметр NULL. А получить HMODULE или HINSTANCE dll-ки  можно только из WINAPI DllEntryPoint. То есть, если dll загружается из другого каталога, получается я путь к ней узнать не могу?    


Название: Re: Как получить имя модуля dll
Отправлено: Авварон от Ноябрь 01, 2017, 10:25
Цитировать
Retrieves the fully qualified path for the file that contains the specified module. The module must have been loaded by the current process.

hModule [in, optional]
A handle to the loaded module whose path is being requested. If this parameter is NULL, GetModuleFileName retrieves the path of the executable file of the current process.


Название: Re: Как получить имя модуля dll
Отправлено: Bolonat от Ноябрь 01, 2017, 10:33
Цитировать
Retrieves the fully qualified path for the file that contains the specified module. The module must have been loaded by the current process.

hModule [in, optional]
A handle to the loaded module whose path is being requested. If this parameter is NULL, GetModuleFileName retrieves the path of the executable file of the current process.

Как в Qt получить HMODULE или HINSTANCE dll-ки, чтобы передать его в GetModuleFileName()?

P.S. MSDN я тоже читаю...


Название: Re: Как получить имя модуля dll
Отправлено: Bolonat от Ноябрь 01, 2017, 10:52
Попробовала вместо хэндла dll использовать хэндл окна:
Код:
::GetModuleFileName( (HMODULE)this->winId(), (LPWSTR)dllname, sizeof(dllname) );

Получаю массив, заполненный нулями.


Название: Re: Как получить имя модуля dll
Отправлено: Igors от Ноябрь 01, 2017, 11:11
Как в Qt получить HMODULE или HINSTANCE dll-ки, чтобы передать его в GetModuleFileName()?

P.S. MSDN я тоже читаю...
Можно получить из хендла путь и наоборот, а что Вы хотите - неясно. Может узнать в какой dll сидит текущий исполняемый код? (других разумных вариантов не видно). Тогда курите GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS


Название: Re: Как получить имя модуля dll
Отправлено: Bolonat от Ноябрь 01, 2017, 11:18
Можно получить из хендла путь и наоборот, а что Вы хотите - неясно. Может узнать в какой dll сидит текущий исполняемый код? (других разумных вариантов не видно). Тогда курите GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
Я хочу получить имя модуля dll и путь к dll из самой dll. Если я снова выразилась неясно, пожалуйста, сообщите об этом сразу, не наблюдайте молча.


Название: Re: Как получить имя модуля dll
Отправлено: Bolonat от Ноябрь 01, 2017, 14:04
Получилось. Кому интересно, хэндл dll в Qt под Win можно получить так (https://stackoverflow.com/questions/2396328/get-hmodule-from-inside-a-dll):
Код:
static HMODULE GetThisDllHandle()
{
  MEMORY_BASIC_INFORMATION info;
  size_t len = VirtualQueryEx(GetCurrentProcess(), (void*)GetThisDllHandle, &info, sizeof(info));
  assert(len == sizeof(info));
  return len ? (HMODULE)info.AllocationBase : NULL;
}
а затем передать его в GetModuleFileName(). В результате получаем полный путь с именем dll из самой dll.


Название: Re: Как получить имя модуля dll
Отправлено: Авварон от Ноябрь 01, 2017, 16:02
Это всё хорошо, но постановку задачи вы так и не сказали:)
Например, изначально было не ясно, что нужно получить путь к _своей_ dll, а не к какой-либо загруженной (напр., кутешной).


Название: Re: Как получить имя модуля dll
Отправлено: Igors от Ноябрь 01, 2017, 16:32
а не к какой-либо загруженной (напр., кутешной).
Напр так
Код
C++ (Qt)
typedef QString (*Func)(const char *, int);
Func func = &QString::fromLocal8Bit;
HMODULE hmodule = 0;
bool ok = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
   LPCTSTR(func),
&hmodule);
if (ok && hmodule) {
ushort path[MAX_PATH] = { 0 };
ok = GetModuleFileName(hmodule, path, MAX_PATH - 1);
QString fullName = QString::fromUtf16(path);
qDebug() << "ok =" << ok << "path =" << fullName;
}
 


Название: Re: Как получить имя модуля dll
Отправлено: kambala от Ноябрь 01, 2017, 23:16
Получилось. Кому интересно, хэндл dll в Qt под Win можно получить так (https://stackoverflow.com/questions/2396328/get-hmodule-from-inside-a-dll):
Код:
static HMODULE GetThisDllHandle()
{
  MEMORY_BASIC_INFORMATION info;
  size_t len = VirtualQueryEx(GetCurrentProcess(), (void*)GetThisDllHandle, &info, sizeof(info));
  assert(len == sizeof(info));
  return len ? (HMODULE)info.AllocationBase : NULL;
}
а затем передать его в GetModuleFileName(). В результате получаем полный путь с именем dll из самой dll.
а как это связано с Qt? обычные винапишные вызовы


Название: Re: Как получить имя модуля dll
Отправлено: Bolonat от Ноябрь 02, 2017, 07:55
Напр так [...]
Спасибо большое. В моих попытках применить  GetModuleHandleEx() с флагом GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, неизменно в hmodule возвращался 0. В вашем варианте все работает.

Это всё хорошо, но постановку задачи вы так и не сказали:)
А мне казалось, что все ясно :). Вообще, хочу чтобы ini файл настройки моей dll лежал рядом с dll, а не рядом с exe. Это на случай если dll и exe находятся в разных каталогах. Ну и... неплохо знать откуда загружается dll, если их несколько одинаковых(разных версий) валяется в разных местах ).

Цитировать
а как это связано с Qt?
Разработку веду в Qt.(Естественно, обычные винапишные. Как я понимаю, из-за кроссплатформенности Qt других и быть не может)
 


Название: Re: Как получить имя модуля dll
Отправлено: Igors от Ноябрь 02, 2017, 14:27
В моих попытках применить  GetModuleHandleEx() с флагом GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, неизменно в hmodule возвращался 0.
Нужен любой адрес кода (но не данных) сидящий в этой dll. Это может быть адрес ф-ции ((void*)GetThisDllHandle) или статического метода, (QString::fromLocal8Bit) но не обычного

обычные винапишные вызовы
И заметьте: когда до этого доходит дело - поклонники этой платформы ну прямо куда-то испаряются  :)


Название: Re: Как получить имя модуля dll
Отправлено: kambala от Ноябрь 03, 2017, 01:29
Разработку веду в Qt.(Естественно, обычные винапишные. Как я понимаю, из-за кроссплатформенности Qt других и быть не может)
 
не совсем понимаю это высказывание. При попытке скомпилировать этот код на платформе, отличной от виндоус, компилятор скажет «давай, до свидания», и кросс-платформенность Qt никак не поможет. Но этот же код будет прекрасно работать и оторванно от Qt (при компиляции под виндоус, естественно), если писать «просто» на С или С++. Суть в том, что вопрос чисто о виндоус-специфической вещи, которая к Qt никакого отношения не имеет.

да, и «разработку в Qt» вести нельзя :)


Название: Re: Как получить имя модуля dll
Отправлено: Bolonat от Ноябрь 03, 2017, 08:18
Нужен любой адрес кода (но не данных) сидящий в этой dll. Это может быть адрес ф-ции ((void*)GetThisDllHandle) или статического метода, (QString::fromLocal8Bit) но не обычного
Aаа, теперь понятно - я просто "курить" не умею...)


не совсем понимаю это высказывание. При попытке скомпилировать этот код на платформе, отличной от виндоус, компилятор скажет «давай, до свидания», и кросс-платформенность Qt никак не поможет. Но этот же код будет прекрасно работать и оторванно от Qt (при компиляции под виндоус, естественно), если писать «просто» на С или С++. Суть в том, что вопрос чисто о виндоус-специфической вещи, которая к Qt никакого отношения не имеет.
Изначально, суть вопроса была - получить путь и наименование загруженной dll. Я не знала, есть ли Qt-шные методы и применила
"чисто виндоус-специфическую вещь" (благо, у меня не стоит задача разработать кроссплатформенное ПО), о чем и сообщила на форуме. Если бы кто-то предложил
другой способ, который имеет отношение к Qt, я бы с радостью применила его. Но сейчас я понимаю, что существование этого
способа маловероятно именно по причине кроссплатформенности Qt.    



Название: Re: Как получить имя модуля dll
Отправлено: Igors от Ноябрь 03, 2017, 12:00
Суть в том, что вопрос чисто о виндоус-специфической вещи, которая к Qt никакого отношения не имеет.
А я думаю имеет - от кросс-платформенного фреймворка мы вправе ожидать кросс-платформенного решения, чтобы не бегать по API каждой из платформ. Тем более что запрос/потребность совершенно разумны. Может правда "плохо искали" - ну тогда "ткните носиком"  :)


Название: Re: Как получить имя модуля dll
Отправлено: Bolonat от Ноябрь 03, 2017, 12:49
А я думаю имеет - от кросс-платформенного фреймворка мы вправе ожидать кросс-платформенного решения.
Извините, но на мой дилетантский взгляд, это только добавит фреймворку багов и тормозов, и, скорее всего, разработчики это понимают.