How to get the path to executable from Visual C++ Console App (CRT, not MFC)

Hi!

I want get the path to the executable. In mfc this is done with GetProcessImageFileName or GetModuleFileNameEx, but this is not possible using a 'standard' c++..

Argv[0] only returns the file name. So how do I get this info?

Thank you!
davidhqAsked:
Who is Participating?
 
peprConnect With a Mentor Commented:
Try the code like this:

#include <windows.h>
...
    char buffer[MAX_PATH];
    DWORD dwResult = GetModuleFileName(NULL, buffer, MAX_PATH);
    //if (dwResult == 0)
    //    throw runtime_error("The GetModuleFileName() failed.\n");
    std::string fullExeName(buffer);
    std::cout << "My full executable name is '" << fullExeName << "'\n";

This was cut from the application that is not compiled as Unicode enabled. For Unicode path, you have to play with the buffer.
0
 
grg99Commented:
AFAIK there is no "standard" way in C or C++ to inquire about this.

You could do a combination of argv[0], and if that does not look like a full path,  and get the current working directory, putting those two together might be the right thing to do.  Or maybe not.  You'll have to experiment with various combinations of relative paths and various cwd's.



0
 
davidhqAuthor Commented:
Thank you for the comment. The problem is that the exe is in PATH and when run from a different location, the working directory will be wrong. So I need the path to the exe, not the current directory.. Any further ideas? thank you!
david
0
Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

 
peprCommented:
The GetModuleFileName() and GetModuleFileNameEx() are win32 system functions. No need to use MFC to use them. See http://msdn2.microsoft.com/en-us/library/ms683197.aspx and http://msdn2.microsoft.com/en-us/library/ms683198.aspx. The GetModuleFileName() (i.e. without Ex) is implemented in  Kernel32 and you get it when including windows.h. The Ex version is implemented inside psapi library and you have to include psapi.h.

You cannot hope for "more standard" way of getting the full executable path. To give you at least one reason why... For example, the path can be returned in Unicode if NTFS is used. This may not be usual in other file systems these days.
0
 
waysideCommented:
Another option is to get the value of the PATH variable (getenv()), break it into pieces (strtok()), build a full path using the directory from the path and the exe from argv[0], and test for its existence (_stat()).

When you find the one that exists, you will now have the full path.
0
 
davidhqAuthor Commented:
Thank you all.. I think the solution GetModuleFileName is the best.. However I have a strange problem with it..

Error      6      error C2065: 'DWORD' : undeclared identifier      
Error      10      error C3861: 'GetModuleFileName': identifier not found      

I did #include <windows.h>

hmm? thank you!
david
0
 
itsmeandnobodyelseCommented:
beside of strtok the idea of wayside is good.

beside of typo's the below should do the job.

Regards, Alex



#include <sys/stat.h>
#include <stdlib.h>
#include <string>
using namespace std;

string getexepath(const string& file)
{
     struct stat fs;
     // first check  the file only
     if (stat(file.c_str(), &fs) == 0)
           return file;
     // get working directory
     string cwd(512, '\0');
     if (getcwd(&cwd[0], cwd.length()) == NULL)
           return ""; // error retrieving current working directory
     cwd.resize(strlen(cwd.c_str());  // make correct length
     // check whether backslash or slash was used
     int pos = (int)cwd.find_first_of("\\/");
     char cslash = '/';  // take forward slash as default
     if (pos != string::npos && cwd[pos] == '\\')
         cslash = '\\';
     string path = cwd + cslash + file;
     if (stat(path.c_str(), &fs) == 0)
           return path;
     
     string pathenv = getenv("PATH");
     pathenv += ';';  // add semicolon for parsing
     int lpos = 0;
     int npos = 0;
     while ((npos = (int)pathenv.find(';', lpos)) != string::npos)
     {
            if (lpos < npos)
            {
                  path = pathenv.substr(lpos, npos - lpos) + cslash + file;
                  if (stat(path.c_str(), &fs) == 0)
                       return path;
            }
            lpos = npos+1;
     }
      return "";
}

0
 
itsmeandnobodyelseCommented:
>>>> I did #include <windows.h>
DWORD is defined in windef.h which was included by windows.h.

I assume you included it above stdafx.h where it was ignored. Or you forgot to switch off Precompiled Header.
0
 
itsmeandnobodyelseCommented:
>>>> I think the solution GetModuleFileName is the best..
That will only work on windows platform. And you have to include all windows api via windows.h.

But beside of that you are right.
0
 
davidhqAuthor Commented:
itsmeandnobodyelse: thank you as well.. yes -> I only need it on windows. Sorry I accepted the other solution (I'm also quite new on EE, so maybe I should have accepted both solutions - didn't realize it)

Regarding the inclusion of "windows.h" - yes I forgot about that gotcha (long time since I last wrote unmanaged code:)

I also had to un-set unicode to get rid of the error when compiling char buffer[]. Here is how to do it:

Project properties / General / Character Set: Use Unicode
changed to "Not set"

Thank you again.. Using EE has paid off big time already.

Bye!
david
0
 
itsmeandnobodyelseCommented:
>>>> so maybe I should have accepted both solutions

It is not important. You may do so next time.

Thank you for your comment.

Regards, Alex
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.