如何在dll内部找到父exe的exe文件?

7
我需要在基于哪个进程加载它的dll中做一些事情。因此,作为相对新手的Windows编程人员,我需要帮助找出如何找到加载当前dll的exe。到目前为止,我一直在硬编码exe文件名,这是最愚蠢的做法:D
1)有人建议使用 GetModuleFileName()函数。但是这似乎会使我的应用程序崩溃。(我使用0作为模块句柄)。我什么也没干。我使用了以下语法 GetModuleFileName(0,&fileName,MAX_PATH) 编辑:从{{link1:here}}中我了解到,我无法通过此调用获取.exe名称,因为它仅返回dll名称:(
2)在DllMain中这样做是一个好主意吗?我知道DllMain不是做复杂工作的地方。我也明白与加载器锁相关的问题。我所需要的就是找到父进程的名称。
感谢您的时间!

补充说明:我尝试在获取父进程 ID 后使用 GetProcessImageFileName。但是我遇到了访问冲突错误。调试过程中我发现,openProcess 调用会把我的结果参数 (image file path-LPTSTR) 留下一个错误指针。
GetProcessImageFileName 调用返回错误代码 87-INVALID PARAMETER。
但是当前进程 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)


你所说的 "an idle process" 是什么意思?如果你指的是 the idle process(Windows归因于未使用的CPU时间),则这是预计会失败的 - 那不是一个真正的进程。 - nobody
3个回答

3
如果您将fileName变量声明为char fileNamechar fileName[MAX_PATH]之类的内容,并且参数不正确,您可能会收到错误信息:您使用变量的地址(虽然您没有说明它是编译时错误还是运行时错误,但您说它会使您的应用程序崩溃,所以我同意Richard的观点,您没有分配变量)。
我尝试了以下代码,无论是从DLL内部(获取可执行文件的名称而不是DLL模块)还是从可执行文件本身中都可以工作。
(注意:根据Remy下面的评论更新了代码,谢谢)
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
更多有关在 Win32 中处理文件名的信息,请参阅此处

你误用了 GetLastError()。如果 GetModuleFileName() 返回 > 0,则成功返回数据。这是有文档记录的行为。除非 GetModuleFileName() 返回 0,否则不要使用 GetLastError()。你还错误地混合使用了 TCHARchar*wcout。尝试像这样做: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; - Remy Lebeau
@RemyLebeau,好久不见了,我相信你是对的(我已经记不清写这段代码时的情况了)。我会更新答案。 - Abel

2
请参考以下链接了解有关 GetModuleFileName() 语法和详细描述:link 执行以下步骤:
首先使用以下代码获取可执行文件的完整路径:
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';

现在你只能获取可执行文件的名称。

虽然这理论上回答了问题,但最好在此处包含答案的基本部分,并提供参考链接。 - Rohit Gupta
希望这对您有用并且易于理解。 - Cibin William
不要像这样混用 TCHAR[]char[]。如果你想要在 char[] 中获取文件名,就要摆脱 TCHAR[] 并使用 GetModuleFileNameA()。同时,还可以查看 splitpath()PathStripPath() - Remy Lebeau

0

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


@Richard,MAX_PATH+1 改动无效 :( 我正在使用vc++。 - ash
我编辑了我的原始帖子。 我将其缩小到更具体的错误。 谢谢。 - ash
就像我之前所说的那样,它是fileName。尝试使用char filename[MAX_PATH+1]; - Richard Schneider

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接