100

I want to create a file in the current directory (where the executable is running).

My code:

LPTSTR NPath = NULL;
DWORD a = GetCurrentDirectory(MAX_PATH,NPath);
HANDLE hNewFile = CreateFile(NPath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

I get exception at GetCurrentDirectory().

Why am I getting an exception?

Ivan Prodanov
  • 34,634
  • 78
  • 176
  • 248
  • 3
    #include char *getcwd(char *buf, size_t size); http://stackoverflow.com/questions/298510/how-to-get-the-current-directory-in-a-c-program – Anuswadh Aug 04 '13 at 15:19
  • possible duplicate of [How do I get the directory that a program is running from?](http://stackoverflow.com/questions/143174/how-do-i-get-the-directory-that-a-program-is-running-from) – user Mar 09 '14 at 23:34
  • 4
    Please NOTE: current directory is not always the directory that the exe is in. (e.g. c:\users\me> \dir1\dir2\runme.exe here you are in c:\users\me and running exe from \dir1\dir2\). – Mercury Sep 14 '15 at 12:53
  • 2
    NULL pointer - you'll get an Access violation – hfrmobile Apr 23 '20 at 06:27
  • no @hfrmobile, https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getcurrentdirectory – Sergei Krivonos Mar 28 '22 at 11:04
  • @Sergei Krivonos: The documentation says that I am right :o) – hfrmobile Apr 05 '22 at 18:51
  • no @hfrmobile, it says "To determine the required buffer size, set this parameter to NULL and the nBufferLength parameter to 0." so this causes no access violation. – Sergei Krivonos Apr 07 '22 at 10:39
  • You have to set **both** parameters to zero!!! "To determine the required buffer size, set this parameter to NULL and the nBufferLength parameter to 0." If *nBufferLength* is > 0 and buffer point NULL --> possible access violation – hfrmobile Apr 10 '22 at 11:55
  • likely seg fault because of null pointer - it is not pointing to any memory and so dereferencing it will likely cause a crash (which is what takes place inside the function) – Gregor Hartl Watters Dec 11 '22 at 01:37

23 Answers23

152

I would recommend reading a book on C++ before you go any further, as it would be helpful to get a firmer footing. Accelerated C++ by Koenig and Moo is excellent.

To get the executable path use GetModuleFileName:

TCHAR buffer[MAX_PATH] = { 0 };
GetModuleFileName( NULL, buffer, MAX_PATH );

Here's a C++ function that gets the directory without the file name:

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

std::wstring ExePath() {
    TCHAR buffer[MAX_PATH] = { 0 };
    GetModuleFileName( NULL, buffer, MAX_PATH );
    std::wstring::size_type pos = std::wstring(buffer).find_last_of(L"\\/");
    return std::wstring(buffer).substr(0, pos);
}

int main() {
    std::cout << "my directory is " << ExePath() << "\n";
}
Jimmy T.
  • 4,033
  • 2
  • 22
  • 38
  • 5
    NB that you may need to use a wide char, like wchar_t buffer[MAX_PATH]; these days... – rogerdpack Sep 24 '13 at 00:08
  • 3
    Or `GetModuleFileNameA` – Mikhail Aug 05 '14 at 10:51
  • 3
    To reiterate over what @Mikhail said, you would use `GetModuleFileNameA` for code which utilizes a multi-byte character set, and `GetModuleFileNameW` for unicode. `GetModuleFileName` (without the `A` or `W`) is actually an alias for whichever character set your project is set to use, which is how most Win32 API methods which utilize strings are set up. So if you have a unicode project, and your strings are is also unicode, then you would only have to call `GetModuleFileName`. The same applies if your project is multi-byte and uses multi-byte strings. – RectangleEquals Jul 12 '15 at 02:35
  • 1
    I don't like the parameter or the `find_last_of()` method, isn't there some constant which defines the separator in directory names, like ".../.../..." or "...\...\..."? – Dominique Jun 30 '20 at 12:32
  • 1
    this is windows only –  Sep 29 '20 at 13:03
  • I am trying to run this on Windows 10 using Visual Studio Code and I get `'wstring' does not name a type; did you mean 'wctrans'?` – Jorje12 Apr 17 '21 at 08:10
  • This is only useful if your current directory is where your executable is. Those don't always match, especially with visual studio and cmake... – Chad Oct 07 '21 at 14:36
87

The question is not clear whether the current working directory is wanted or the path of the directory containing the executable.

Most answers seem to answer the latter.

But for the former, and for the second part of the question of creating the file, the C++17 standard now incorporates the filesystem library which simplifies this a lot:

#include <filesystem>
#include <iostream>

std::filesystem::path cwd = std::filesystem::current_path() / "filename.txt";
std::ofstream file(cwd.string());
file.close();

This fetches the current working directory, adds the filename to the path and creates an empty file. Note that the path object takes care of os dependent path handling, so cwd.string() returns an os dependent path string. Neato.

Rasmus Dall
  • 1,189
  • 8
  • 12
50

GetCurrentDirectory does not allocate space for the result, it's up to you to do that.

TCHAR NPath[MAX_PATH];
GetCurrentDirectory(MAX_PATH, NPath);

Also, take a look at Boost.Filesystem library if you want to do this the C++ way.

avakar
  • 32,009
  • 9
  • 68
  • 103
  • Hmm,NPath points to another directory,how do I make it show the directory where the executable is placed in? – Ivan Prodanov May 17 '09 at 19:11
  • 8
    The current directory is not the same as the executable's directory, even under C# and Delphi. Perhaps you could make your question clearer? –  May 17 '09 at 19:13
  • John, that's a little more involved and can't be simply answered in a comment. Perhaps you should follow Neil's advice (both of them). – avakar May 17 '09 at 19:19
22

An easy way to do this is:

int main(int argc, char * argv[]){
    std::cout << argv[0]; 
    std::cin.get();
}

argv[] is pretty much an array containing arguments you ran the .exe with, but the first one is always a path to the executable. If I build this the console shows: C:\Users\Ulisse\source\repos\altcmd\Debug\currentdir.exe

  • 3
    Best answer for its simplicity. – Jerry Switalski Oct 20 '20 at 17:33
  • 2
    Note: This won't be updated as the program runs though, so it only tells where the program is run from not necessarily the current working directory. – JStrahl Apr 04 '22 at 13:07
  • 1
    `GetCurrentDirectory` returns current directory of process, i.e the working directory. `argv[0]` is the path of executable file. One different is that the working directory can be changed during the life-cycle of a process while `argv[0]` can not be changed. – Reza Ghodsi Feb 08 '23 at 08:02
14

IMHO here are some improvements to anon's answer.

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

std::string GetExeFileName()
{
  char buffer[MAX_PATH];
  GetModuleFileName( NULL, buffer, MAX_PATH );
  return std::string(buffer);
}

std::string GetExePath() 
{
  std::string f = GetExeFileName();
  return f.substr(0, f.find_last_of( "\\/" ));
}
Community
  • 1
  • 1
cdiggins
  • 17,602
  • 7
  • 105
  • 102
  • 2
    This is actually different. YOu don't provide the directory path, you provide the path of the file, including the file. – dyesdyes Apr 14 '15 at 21:24
10
#include <iostream>    
#include <stdio.h>
#include <dirent.h>

std::string current_working_directory()
{
    char* cwd = _getcwd( 0, 0 ) ; // **** microsoft specific ****
    std::string working_directory(cwd) ;
    std::free(cwd) ;
    return working_directory ;
}

int main(){
    std::cout << "i am now in " << current_working_directory() << endl;
}

I failed to use GetModuleFileName correctly. I found this work very well. just tested on Windows, not yet try on Linux :)

MsLate
  • 149
  • 2
  • 10
6

Please don't forget to initialize your buffers to something before utilizing them. And just as important, give your string buffers space for the ending null

TCHAR path[MAX_PATH+1] = L"";
DWORD len = GetCurrentDirectory(MAX_PATH, path);

Reference

DJMcMayhem
  • 7,285
  • 4
  • 41
  • 61
Jj Rivero
  • 81
  • 1
  • 3
5
WCHAR path[MAX_PATH] = {0};
GetModuleFileName(NULL, path, MAX_PATH);
PathRemoveFileSpec(path);
Zhi Wang
  • 1,138
  • 4
  • 20
  • 34
4
#include <windows.h>
using namespace std;

// The directory path returned by native GetCurrentDirectory() no end backslash
string getCurrentDirectoryOnWindows()
{
    const unsigned long maxDir = 260;
    char currentDir[maxDir];
    GetCurrentDirectory(maxDir, currentDir);
    return string(currentDir);
}
freezotic
  • 81
  • 2
  • 1
    `currentDir` - An argument of type `"char *"` is incompatible with a parameter of type `"LPWSTR"` (Unicode encoding) – ZidoX Oct 04 '20 at 00:07
4

You should provide a valid buffer placeholder. that is:

TCHAR s[100];
DWORD a = GetCurrentDirectory(100, s);
yves Baumes
  • 8,836
  • 7
  • 45
  • 74
3

You can remove the filename from GetModuleFileName() with more elegant way:

TCHAR fullPath[MAX_PATH];
TCHAR driveLetter[3];
TCHAR directory[MAX_PATH];
TCHAR FinalPath[MAX_PATH];
GetModuleFileName(NULL, fullPath, MAX_PATH);
_splitpath(fullPath, driveLetter, directory, NULL, NULL);
sprintf(FinalPath, "%s%s",driveLetter, directory);

Hope it helps!

TLama
  • 75,147
  • 17
  • 214
  • 392
ProXicT
  • 1,903
  • 3
  • 22
  • 46
3

GetCurrentDirectory() gets the current directory which is where the exe is invoked from. To get the location of the exe, use GetModuleFileName(NULL ...). if you have the handle to the exe, or you can derive it from GetCommandLine() if you don't.

As Mr. Butterworth points out, you don't need a handle.

nickd
  • 3,951
  • 2
  • 20
  • 24
  • 4
    Actually, you don't need a real handle - a NULL handle gets the executable file name, with path. –  May 17 '09 at 19:19
2

Why does nobody here consider using this simple code?

TCHAR szDir[MAX_PATH] = { 0 };

GetModuleFileName(NULL, szDir, MAX_PATH);
szDir[std::string(szDir).find_last_of("\\/")] = 0;

or even simpler

TCHAR szDir[MAX_PATH] = { 0 };
TCHAR* szEnd = nullptr;
GetModuleFileName(NULL, szDir, MAX_PATH);
szEnd = _tcsrchr(szDir, '\\');
*szEnd = 0;
123iamking
  • 2,387
  • 4
  • 36
  • 56
1

I guess, that the easiest way to locate the current directory is to cut it from command line args.

#include <string>
#include <iostream>

int main(int argc, char* argv[])
{
  std::string cur_dir(argv[0]);
  int pos = cur_dir.find_last_of("/\\");

  std::cout << "path: " << cur_dir.substr(0, pos) << std::endl;
  std::cout << "file: " << cur_dir.substr(pos+1) << std::endl;
  return 0;
}

You may know that every program gets its executable name as first command line argument. So you can use this.

zexUlt
  • 35
  • 1
  • Very useful for mac as well unlike other answers that I had an issue with. Also liked that you parsed the string to get the directory. thanks - up voted – msj121 Feb 22 '22 at 00:54
  • This code won't give the current directory; it will give the directory where the executable file is found (on some platforms). – Hack5 Feb 27 '23 at 17:01
  • 1
    This won't give the CWD. It will give the path used to execute the binary. If I executed the following: `$ ./prog`, `argv[0]` would be `"./prog` – Ciro García Mar 27 '23 at 01:04
  • This answer is incorrect. Present working directory is not the same as directory where the executable resides. As Ciro has pointed out already. – Agnel Kurian Jul 24 '23 at 05:23
1

I simply use getcwd() method for that purpose in Windows, and it works pretty well. The code portion is like following:

#include <direct.h>

// ...

char cwd[256];
getcwd(cwd, 256);
std::string cwd_str = std::string(cwd);
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
skbr
  • 151
  • 1
  • 5
0

Code snippets from my CAE project with unicode development environment:

/// @brief Gets current module file path. 
std::string getModuleFilePath() {
    TCHAR buffer[MAX_PATH];
    GetModuleFileName( NULL, buffer, MAX_PATH );
    CT2CA pszPath(buffer);
    std::string path(pszPath);
    std::string::size_type pos = path.find_last_of("\\/");
    return path.substr( 0, pos);
}

Just use the templete CA2CAEX or CA2AEX which calls the internal API ::MultiByteToWideChar or ::WideCharToMultiByte

0

if you don't want to use std, you can use this code:

char * ExePath() 
{
   static char buffer[MAX_PATH] = { 0 };
   GetModuleFileName( NULL, buffer, MAX_PATH );
   char * LastSlash = strrchr(buffer, '\\');
   if(LastSlash == NULL)
        LastSlash = strrchr(buffer, '/');
    
   buffer[LastSlash-buffer] = 0;
   return buffer;
}
Elad
  • 1,523
  • 13
  • 10
0

It's depends on your c++ version, try this:

#include <iostream>

#if __cplusplus >= 201703L
// code for C++17 and later
#include <filesystem>
std::string cwd() { return std::filesystem::current_path(); }

#else
// code for earlier versions of c++
#include <unistd.h>
std::string cwd() {
    char buffer[FILENAME_MAX];
    if (getcwd(buffer, FILENAME_MAX) != nullptr) {
        return {buffer};
    }
    return "";
}
#endif


int main() {
    std::cout << cwd();
}

What's more we can get this from linux procfs, it's works in any language:

#include <iostream>
#include <unistd.h>
#include <limits.h>

// ONLY WORKING IN UNIX-LIKE SYSTEMS SUCH AS LINUX
int main() {
    char cwd[PATH_MAX];
    ssize_t size = readlink("/proc/self/cwd", cwd, sizeof(cwd));
    if (size != -1) {
        cwd[size] = '\0'; // Null-terminate the string
        std::cout << "current working directory: " << cwd << std::endl;
    } else {
        std::cerr << "failed to read cwd" << std::endl;
    }

    return 0;
}
AnonymousX
  • 638
  • 7
  • 8
-1

If you are using the Poco library, it's a one liner and it should work on all platforms I think.

Poco::Path::current()
James Selvakumar
  • 2,679
  • 1
  • 23
  • 28
-1

To find the directory where your executable is, you can use:

TCHAR szFilePath[_MAX_PATH];
::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
Andomar
  • 232,371
  • 49
  • 380
  • 404
-2
String^ exePath = Application::ExecutablePath;<br>
MessageBox::Show(exePath);
Lucifer
  • 29,392
  • 25
  • 90
  • 143
Ali
  • 15
  • 2
-2

On a give Windows C++ IDE I went crude and it was simple, reliable, but slow:

system( "cd" );
Yunnosch
  • 26,130
  • 9
  • 42
  • 54
  • 1
    Better avoid the impression of belittling other answers. – Yunnosch Feb 16 '23 at 06:53
  • 3
    Please make the additional insight more obvious which you contribute beyond existing answers, e.g. https://stackoverflow.com/a/71663339/7733418 – Yunnosch Feb 16 '23 at 06:54
-3

In Windows console, you can use the system command CD (Current Directory):

std::cout << "Current Directory = ";
system("cd"); // to see the current executable directory
Tyler2P
  • 2,324
  • 26
  • 22
  • 31