在 CreateProcess 之后调用 GetModuleFileNameEx 时出现 ERROR_INVALID_HANDLE

Posted

技术标签:

【中文标题】在 CreateProcess 之后调用 GetModuleFileNameEx 时出现 ERROR_INVALID_HANDLE【英文标题】:ERROR_INVALID_HANDLE when calling GetModuleFileNameEx after CreateProcess 【发布时间】:2014-07-21 11:23:42 【问题描述】:

在成功调用 CreateProcess 后,我尝试使用 GetModuleFileNameEx 获取创建的进程的路径(lpApplicationName 和 lpCommandLine 参数可以变化或为空,因此在这种情况下它们不可靠)。 问题是 GetModuleFileNameEx 因错误 6 (ERROR_INVALID_HANDLE) 而失败,导致其缓冲区中的数据无效。我无法理解原因,因为 CreateProcess 成功并且进程句柄应该已经正确保存在 pi.hProcess 中。

希望您能有所启发,在此先感谢!

编辑:更新:我注意到删除 CREATE_SUSPENDED 也可以解决此问题,但我需要设置该标志。我该怎么办?

// Defining GetModuleFileNameExA function
typedef DWORD (WINAPI *fGetModuleFileNameExA)
(
    HANDLE hProcess,
    HMODULE hModule,
    LPSTR lpFilename,
    DWORD nSize
);
//Load dinamically DLL function on program startup:
fGetModuleFileNameExA _GetModuleFileNameExA = (fGetModuleFileNameExA) GetProcAddress( LoadLibraryA("Psapi.dll"), "GetModuleFileNameExA");

// **** OTHER UNRELATED CODE HERE ****


PROCESS_INFORMATION pi;

//This call succeeds
if (!CreateProcessW( ApplicationName, 
                    CommandLine, 
                    NewProcess.lpProcessAttributes, 
                    NewProcess.lpThreadAttributes,
                    NewProcess.bInheritHandles,
                    CREATE_SUSPENDED | CREATE_NEW_CONSOLE,
                    NULL,
                    CurrentDirectory,
                    &NewProcess.bufStartupInfo,
                    &pi)
       ) MessageBoxA(0, "Error creating process", "", 0);

    char ProcessPath[MAX_PATH];

//Problem here: call fails with error 6
if (!_GetModuleFileNameExA(pi.hProcess, NULL, ProcessPath, MAX_PATH)) GetLastError();

//Invalid data is displayed
MessageBoxA(0, ProcessPath, "GetModuleFileNameEx",0);

【问题讨论】:

删除 CREATE_SUSPENDED 似乎是解决方案 如果你创建了暂停,那么还没有模块信息,因为你没有给进程加载任何模块的机会。 既然您显然没有为CreateProcessW 的第一个参数传递NULL,您难道不知道可执行文件的文件名吗? devblogs.microsoft.com/oldnewthing/20150716-00/?p=45131 【参考方案1】:

来自 MSDN 上的CreateProcess documentation:

请注意,函数在进程完成初始化之前返回。如果找不到所需的 DLL 或无法初始化,则终止进程。要获取进程的终止状态,请调用GetExitCodeProcess

...

调用线程可以使用WaitForInputIdle 函数等待新进程完成其初始化并等待用户输入而没有待处理的输入。这对于父进程和子进程之间的同步很有用,因为 CreateProcess 无需等待新进程完成其初始化即可返回。例如,创建进程会在尝试查找与新进程关联的窗口之前使用 WaitForInputIdle。

Similar question

【讨论】:

以上是关于在 CreateProcess 之后调用 GetModuleFileNameEx 时出现 ERROR_INVALID_HANDLE的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中通过 lpEnvironment 调用 CreateProcess()

如何在 Delphi Prism 中调用函数 CreateProcess?

cmd.exe 在使用 CreateProcess 调用后立即关闭

CreateProcess .. WaitForSingleObject .. CloseHandle 调用的最佳 try..finally 位置

调用 CreateProcess() 并获取字符串的返回值

如何为两个单独的 CreateProcess() API 调用打开单独的命令提示符控制台