【问题标题】:How to find the parent exe of a dll from inside the dll?如何从 dll 中找到 dll 的父 exe?
【发布时间】:2011-06-09 00:51:33
【问题描述】:

我需要根据加载它的进程在 dll 中做一些事情。因此,对于 Windows 编程来说相对较新,我需要帮助找出如何找到加载当前 dll 的 exe。到目前为止,我一直在硬编码 exe 文件名,这是最愚蠢的事情:D

1) 有人建议使用GetModuleFileName() 函数。但这似乎使我的应用程序崩溃。(我使用 0 作为模块句柄)。我没有做任何花哨的事情。我使用了以下语法

GetModuleFileName(0,&fileName,MAX_PATH)

编辑:我从here 了解到,我无法通过此调用获取 .exe 名称,因为它仅返回 dll 名称:(

2) 在 DllMain 中执行此操作是个好主意吗?我知道 DllMain 不是做复杂事情的地方。我也了解加载程序锁定相关的问题。我只需要找到父进程的名称即可。

感谢您的宝贵时间!

添加:我在获取父进程 ID 后尝试使用 GetProcessImageFileName。我收到访问冲突错误。当我尝试调试时,我注意到 openProcess 调用将我的结果参数(图像文件路径-LPTSTR)作为错误指针。
GetProcessImageFileName 调用返回错误代码 87-INVALID PARAMETER。
但是当前的进程id是一个有效的id。
这是代码

LPTSTR fileName={0};  
HANDLE hP=OpenProcess(PROCESS_QUERY_INFORMATION ,FALSE, processes[i]) ;
GetProcessImageFileName(hP,fileName,(DWORD)MAX_PATH+1);

我做错了什么??

谢谢

编辑重要提示:

我发现我正在尝试在空闲进程上使用 openprocess。(即)我忘记了我的父进程可能正在等待我,因为我同步了它。所以现在我得到一个坏消息,我无法使用 OpenProcess 打开空闲进程。 我还能如何查看空闲进程的对象??(我确定它是空闲的,因为我在快照中找不到它。我不得不使用 enumerateprocess 来定位它的 ID;但是我确实使用快照中的正常进程枚举来首先找到父进程ID)

【问题讨论】:

  • “空闲进程”是什么意思?如果您的意思是 空闲进程(Windows 将未使用的 CPU 时间归因于该进程),那么这预计会失败 - 这不是一个真正的进程。

标签: c++ exe parent getmodulefilename


【解决方案1】:

如果您已将 fileName 变量声明为 char fileNamechar fileName[MAX_PATH],您可能会收到一个错误,因为您的参数不正确:您使用了变量的地址(但您没有指定它是否是编译时错误或运行时错误,你说它会使你的应用程序崩溃,所以我在这里和 Richard 一起去,你还没有分配你的变量)。

我尝试了以下代码,它既可以在 DLL 中工作(它获取可执行文件的名称,而不是 DLL 模块),也可以在可执行文件本身中工作。
(注意:代码根据下面的 Remy 的 cmets 更新,谢谢)

WCHAR exePath[MAX_PATH + 1];
DWORD len = GetModuleFileNameW(NULL, exePath, MAX_PATH);
if (len > 0) {
    wcout 
       << L"Exe path" 
       << (len == MAX_PATH) ? L" (truncated):" : L":" 
       << exePath 
       << endl;
} else {
    wcout 
       << L"Error getting exe path: " 
       << GetLastError() 
       << endl;
}

注意:如果缓冲区不够大,GetModuleFileName 将截断结果并返回nSize

更多关于handling filenames in Win32

【讨论】:

  • 您在滥用GetLastError()。如果GetModuleFileName() 返回 > 0,则成功返回数据。这是记录在案的行为。不要使用GetLastError(),除非GetModuleFileName() 返回0。您还错误地混合了TCHARchar*wcout。尝试这样的事情:WCHAR exePath[MAX_PATH + 1]; DWORD len = GetModuleFileNameW(NULL, exePath, MAX_PATH); if (len &gt; 0) wcout &lt;&lt; L"Exe path" &lt;&lt; (len == MAX_PATH) ? L" (truncated):" : L":" &lt;&lt; exePath &lt;&lt; endl; else wcout &lt;&lt; L"Error getting exe path: " &lt;&lt; GetLastError() &lt;&lt; endl;
  • @RemyLebeau,已经有一段时间了,我相信你是对的(我不记得编写这段代码时的情况)。我会更新答案。
【解决方案2】:

参考以下link了解GetModuleFileName()的语法和详细说明

步骤:

首先使用代码获取可执行文件的完整路径:

TCHAR szEXEPath[2048];
char actualpath[2048];
GetModuleFileName ( NULL, szEXEPath, 2048 );
for(int j=0; szEXEPath[j]!=0; j++)
{
    actualpath[j]=szEXEPath[j];
}

从可执行文件的完整路径,使用内置函数str.find_last_of()拆分字符串,只得到可执行文件名

std::string str (actualpath);
std::size_t found = str.find_last_of("/\\");
std::cout<< str.substr(found+1) << '\n';

现在您只能获取可执行文件名。

【讨论】:

  • 虽然这在理论上可以回答问题,it would be preferable 在此处包含答案的基本部分,并提供链接以供参考。
  • 希望这将是有用且易于理解的
  • 不要像这样混合TCHAR[]char[]。如果您想要char[] 中的文件名,请去掉TCHAR[] 并改用GetModuleFileNameA()。也可以看看splitpath()PathStripPath()
【解决方案3】:

我假设您使用 C 进行编码。您很可能没有为文件名分配 MAX_PATH + 1 个字符。

【讨论】:

  • @Richard MAX_PATH+1 没有任何改变 :( 我正在使用 vc++
  • 我编辑了我的原始帖子。我将其缩小到更具体的错误。谢谢。
  • 正如我所说的它的文件名。试试这个char filename[MAX_PATH+1];
猜你喜欢
  • 2017-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多