0

I'm trying to get a running program's full path, I'm currently using this code

process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
char phew[MAX_PATH + 1];
GetFinalPathNameByHandle(process, phew, MAX_PATH, FILE_NAME_OPENED);

TRACE("Path : %s\n", phew);

but that always returns and empty string. I need a result like C:\Program\File.exe. I couldn't find any other help for WinAPI elsewhere.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291

2 Answers2

1

GetFinalPathNameByHandle works on file handles, not process handles. Use GetModuleFileNameEx.

C++ Windows - How to get process path from its PID.

Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78
  • 2
    Per the `GetModuleFileNameEx()` documentation: "*To retrieve the name of the main executable module for a remote process, **use the `GetProcessImageFileName` or `QueryFullProcessImageName` function**. This is more efficient and more reliable than calling the `GetModuleFileNameEx` function with a NULL module handle.*" – Remy Lebeau Dec 24 '18 at 19:08
  • An example where `GetModuleFileNameEx()` is unreliable: [A 32-bit process attempts to get the path of a 64-bit process](http://winprogger.com/getmodulefilenameex-enumprocessmodulesex-failures-in-wow64/) and [vice versa](https://stackoverflow.com/questions/46403532/getmodulefilenameex-on-32bit-process-from-64bit-process-on-windows-10). – zett42 Dec 25 '18 at 10:57
  • Also, `GetModuleFileNameEx()` requires more access rights, that is `PROCESS_QUERY_INFORMATION | PROCESS_VM_READ`, which may not be granted to you for some (system) processes. In contrast, both `GetProcessImageFileName()` and `QueryFullProcessImageName()` only require `PROCESS_QUERY_LIMITED_INFORMATION` access right, which is more likely to succeed. – zett42 Dec 25 '18 at 11:07
0

My work code:

string toString(TCHAR* chars)
{
    std::string s;
    std::wstring wStr = chars;
    s = std::string(wStr.begin(), wStr.end());
    std::cout << s << std::endl;
    return s;
}

BOOL GetFileNameFromHandle(HANDLE hFile, TCHAR* pszFileName, const unsigned int uiMaxLen)
{
    pszFileName[0] = 0;

    std::unique_ptr<BYTE[]> ptrcFni(new BYTE[_MAX_PATH * sizeof(TCHAR) + sizeof(FILE_NAME_INFO)]);
    FILE_NAME_INFO* pFni = reinterpret_cast<FILE_NAME_INFO*>(ptrcFni.get());
    BOOL b = GetFileInformationByHandleEx(hFile,
        FileNameInfo,
        pFni,
        sizeof(FILE_NAME_INFO) + (_MAX_PATH * sizeof(TCHAR)));
    if (b)
    {
#ifdef  _UNICODE
        wcsncpy_s(pszFileName,
            min(uiMaxLen, (pFni->FileNameLength / sizeof(pFni->FileName[0])) + 1),
            pFni->FileName,
            _TRUNCATE);
#else
        strncpy_s(pszFileName,
            min(uiMaxLen, (pFni->FileNameLength / sizeof(pFni->FileName[0])) + 1),
            CW2A(pFni->FileName),
            _TRUNCATE);
#endif
    }
    return b;
}

string Help::getFilePath(HANDLE handle)
{
    TCHAR charName[1024];
    bool res = GetFileNameFromHandle(handle, charName, 1024);
    return toString(charName);
}

In main:

HANDLE hFile = ...;
string path = getFilePath(hFile);
Yotic
  • 136
  • 1
  • 8