0

I just want to get full path of my executable file written on console, but the variable path just stores numbers how can i convert it to string (I know this code only outputs memory location of path)?

#include <iostream>
#include <windows.h>
#include <string>

using namespace std;

int main() {

    WCHAR path[MAX_PATH];

    GetModuleFileName(NULL, path, 500);

    cout << "File path is: " << path << endl;
}
Gorkem Polat
  • 94
  • 2
  • 11

4 Answers4

2

There are a couple of problems with your code:

  • You're passing the wrong size parameter to GetModuleFilename - the buffer size is supposed to be the size in TCHARs, which would be MAX_PATH in your case, not 500. That's a buffer overflow waiting to happen as 500 > MAX_PATH
  • You're using the narrow stream for your output, that can't print a wide string so you're seeing the address instead. To print wide characters, you need to use std::wcout instead.
Timo Geusch
  • 24,095
  • 5
  • 52
  • 70
  • thanks! Yes, wcout solves the problem i can print the file path, but what if i want to convert it to string? For example, i want to load an image with imread() and it accepts string in the file parameter. – Gorkem Polat Mar 17 '14 at 22:21
  • Simple answer - don't build the unicode version, build one that uses narrow strings if narrow strings is what you need. Alternatively, you can use some of the built-in Windows string conversion functions to turn a wide string into a narrow string. – Timo Geusch Mar 17 '14 at 22:42
  • @TimoGeusch: You can't use any random function, or codepage. The best bet is to get the 8.3 name, which is plain ASCII IIRC. – MSalters Mar 17 '14 at 22:51
0

wchar are 16bit and you are using cout and that output stream expect 8bit char that's why you get weird number on the output

when you have to use wchar use wcout and take care of the kind of string you use!

alexbuisson
  • 7,699
  • 3
  • 31
  • 44
0

As already noted in the comments, you may want to use wcout to print a WCHAR string.

You may want to consider a function like this to wrap the GetModuleFileName() call in a convenient C++ way:

#include <stdexcept> // For std::runtime_error
#include <string>    // For std::wstring
#include <Windows.h> // For Win32 API

// 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 full path of current 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);
    }

    return filename;
}

Note that if you want the size in WCHARs of a raw string buffer, you may want to use _countof().

Mr.C64
  • 41,637
  • 14
  • 86
  • 162
  • is there any way to store path in `string` format? – Gorkem Polat Mar 17 '14 at 23:03
  • @Splendor: One option is to explicitly use `GetModuleFileNameA()` i.e. the ANSI version, and `char` strings (instead of `wchar_t` ones). Or convert from `std::wstring` to ANSI using `CW2A` (which is a convenient RAII wrapper on `WideCharToMultiByte()` API). – Mr.C64 Mar 17 '14 at 23:07
  • @Mr.C64 What's a `Midule`? :) #trolly – CodeAngry Mar 18 '14 at 00:17
  • @Mr.C64 since i want to use char strings, `GetModuleFileNameA` is the function i was looking for, thank you – Gorkem Polat Mar 18 '14 at 08:28
  • @Splendor: If you find some answers helpful, you may want to upvote them, and mark the best reply as answer. – Mr.C64 Mar 18 '14 at 12:09
0
#include <iostream>
#include <string>
#include <windows.h>

std::wstring app_path() {
    std::wstring path;
    path.resize(MAX_PATH, 0);
    auto path_size(GetModuleFileName(nullptr, &path.front(), MAX_PATH));
    path.resize(path_size);
    return path;
}

int main() {
    auto path(app_path());
    std::wcout << L"File path is: " << path << std::endl;
}

Try this one!

CodeAngry
  • 12,760
  • 3
  • 50
  • 57
  • Why don't you just use `_countof()` instead of the verbose `sizeof()` stuff? – Mr.C64 Mar 17 '14 at 22:39
  • @Mr.C64 To be educational. :) To force him too look it up and understand it. – CodeAngry Mar 17 '14 at 22:40
  • 1
    Would be a lot easier to just pass `MAX_PATH`. BTW, you have a one-off error. You should pass the buffer size, not the buffer size - 1. This will incorrectly truncate valid paths of length `MAX_PATH-1` – MSalters Mar 17 '14 at 22:53
  • @MSalters **Windows XP: The string is truncated to nSize characters and is not null-terminated.** - My non-native English says that on XP, I should reserve the ending NULL myself. --- Added 1 extra character just in case. – CodeAngry Mar 17 '14 at 22:58
  • @CodeAngry, is there any way to store path in string format? I want to use `imwrite` to save image and path must be in string format to use that function – Gorkem Polat Mar 17 '14 at 23:06
  • @Splendor Modified the code. Check it out. – CodeAngry Mar 17 '14 at 23:13
  • @CodeAngry: You're quoting the "when the path length exceeds `nSize`" behavior, which shouldn't happen for `MAX_PATH`. – MSalters Mar 18 '14 at 00:10