Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get all files listed inside .exe directory not knowing location

I guess my question is this - How would I get the directory of the exe location as an LPCWSTR so that I can input it into my code

#include <iostream>
#include <Windows.h>
int main(int argc, char **argv)
{
WIN32_FIND_DATA a;
HANDLE swap = FindFirstFile(/*(LPCWSTR)__exe_directory__*/,&a);
if (swap!=INVALID_HANDLE_VALUE)
{
    do
    {
        char *sptn = new char [lstrlen(a.cFileName)+1];
        for (int c=0;c<lstrlen(a.cFileName);c++)
        {
            sptn[c]=char(a.cFileName[c]);
        }
        sptn[lstrlen(a.cFileName)]='\0';
        std::cout<<sptn<<std::endl;
    }
    while (FindNextFile(swap,&a));
}
else std::cout<<"undetected file\n";
FindClose(swap);
system("pause");
}

And it would return the listed files in the directory without error. I know for a fact that my code already works given the directory, I tested it already.

like image 984
user3267146 Avatar asked Mar 13 '14 08:03

user3267146


1 Answers

The key is to use GetModuleFileName() (passing nullptr as module handle, to refer to current process EXE), and then call PathRemoveFileSpec() (or PathCchRemoveFileSpec(), if you don't care about Windows versions prior to Windows 8) to strip the file spec from the path.

To use PathRemoveFileSpec() you must link with Shlwapi.lib, as stated in MSDN documentation.

See this compilable code as an example:

#include <iostream>     // For console output
#include <exception>    // For std::exception
#include <stdexcept>    // For std::runtime_error
#include <string>       // For std::wstring
#include <Windows.h>    // For Win32 SDK
#include <Shlwapi.h>    // For PathRemoveFileSpec()

#pragma comment(lib, "Shlwapi.lib")

// Represents an error in a call to a Win32 API.
class win32_error : public std::runtime_error 
{
public:
    win32_error(const char * msg, DWORD error) 
        : std::runtime_error(msg)
        , _error(error)
    { }

    DWORD error() const 
    {
        return _error;
    }

private:
    DWORD _error;
};

// Returns the path without the filename for current process EXE.
std::wstring GetPathOfExe() 
{
    // Get filename with full path for current process EXE
    wchar_t filename[MAX_PATH];
    DWORD result = ::GetModuleFileName(
        nullptr,    // retrieve path of current process .EXE
        filename,
        _countof(filename)
    );
    if (result == 0) 
    {
        // Error
        const DWORD error = ::GetLastError();
        throw win32_error("Error in getting module filename.", 
                          error);
    }

    // Remove the file spec from the full path
    ::PathRemoveFileSpec(filename);

    return filename;
}

int main() 
{
    try 
    {
        std::wcout << "Path for current EXE:\n"
                   << GetPathOfExe() 
                   << std::endl;
    } 
    catch (const win32_error & e) 
    {
        std::cerr << "\n*** ERROR: " << e.what()
                  << " (error code: " << e.error() << ")" 
                  << std::endl;
    } 
    catch (const std::exception& e) 
    {
        std::cerr << "\n*** ERROR: " << e.what() << std::endl;
    }
}

In console:

C:\Temp\CppTests>cl /EHsc /W4 /nologo /DUNICODE /D_UNICODE get_exe_path.cpp
get_exe_path.cpp

C:\Temp\CppTests>get_exe_path.exe
Path for current EXE:
C:\Temp\CppTests

PS
In your code, you seem to refer to the Unicode version of FindFirtFile() (i.e. FindFirstFileW(), since in the comment you expect a LPCWSTR, i.e. const wchar_t*), but then in the following code you use ANSI/MBCS strings (i.e. char*).

I'd suggest you to always use Unicode UTF-16 wchar_t* strings in modern Windows C++ code: it's better for internationalization, and modern Win32 APIs only come with a Unicode version.

Note also that, since you are using C++, it's better to use a robust convenient string class (e.g. std::wstring for Unicode UTF-16 strings with Microsoft Visual C++), instead of C-like raw character pointers. Use the raw pointers at the API interface (since the Win32 API has a C interface), and then safely convert to a std::wstring.

like image 187
Mr.C64 Avatar answered Oct 31 '22 12:10

Mr.C64