How to get Current Directory?
Asked Answered
B

24

108

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?

Blanchblancha answered 17/5, 2009 at 19:5 Comment(9)
#include <unistd.h> char *getcwd(char *buf, size_t size); #299010Marchioness
possible duplicate of How do I get the directory that a program is running from?Calamitous
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).Magallanes
NULL pointer - you'll get an Access violationSecretariat
no @hfrmobile, learn.microsoft.com/en-us/windows/win32/api/winbase/…Cofferdam
@Sergei Krivonos: The documentation says that I am right :o)Secretariat
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.Cofferdam
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 violationSecretariat
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)Arthropod
S
155

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";
}
Somatic answered 17/5, 2009 at 19:10 Comment(8)
NB that you may need to use a wide char, like wchar_t buffer[MAX_PATH]; these days...Stichomythia
Or GetModuleFileNameAFluorine
To reiterate over what @Fluorine 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.Forswear
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 "...\...\..."?Rebus
this is windows onlySemifinalist
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'?Martini
This is only useful if your current directory is where your executable is. Those don't always match, especially with visual studio and cmake...Dilettantism
@Martini Did you compiled as C++ code?Given
I
99

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.

Impious answered 26/9, 2018 at 16:4 Comment(3)
How can we use <filesystem> library to get the path of the directory containing the executable please?Sadoff
afaik the <filesystem> does not have a straightforward way to do that. Sorry. Please see the other answers for that partof the question.Impious
The subject of the question is "How to get Current Directory?"Secretariat
N
52

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.

Narbada answered 17/5, 2009 at 19:8 Comment(3)
Hmm,NPath points to another directory,how do I make it show the directory where the executable is placed in?Blanchblancha
The current directory is not the same as the executable's directory, even under C# and Delphi. Perhaps you could make your question clearer?Somatic
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).Narbada
S
25

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

Septilateral answered 10/11, 2018 at 7:29 Comment(3)
Best answer for its simplicity.Weig
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.Hotpress
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.Dioxide
K
15

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( "\\/" ));
}
Kabul answered 13/9, 2012 at 0:20 Comment(1)
This is actually different. YOu don't provide the directory path, you provide the path of the file, including the file.Sussna
P
9
#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 :)

Photochronograph answered 3/8, 2016 at 22:8 Comment(0)
I
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

Icken answered 2/12, 2011 at 19:54 Comment(0)
B
5
WCHAR path[MAX_PATH] = {0};
GetModuleFileName(NULL, path, MAX_PATH);
PathRemoveFileSpec(path);
Bubonocele answered 9/1, 2013 at 5:28 Comment(0)
D
4

You should provide a valid buffer placeholder. that is:

TCHAR s[100];
DWORD a = GetCurrentDirectory(100, s);
Diaconate answered 17/5, 2009 at 19:11 Comment(0)
P
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.

Peeling answered 17/5, 2009 at 19:17 Comment(1)
Actually, you don't need a real handle - a NULL handle gets the executable file name, with path.Somatic
T
3
#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);
}
Terefah answered 19/2, 2014 at 17:29 Comment(1)
currentDir - An argument of type "char *" is incompatible with a parameter of type "LPWSTR" (Unicode encoding)Kyongkyoto
I
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!

Iced answered 15/3, 2014 at 17:41 Comment(0)
A
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;
Arithmetic answered 25/8, 2017 at 15:13 Comment(0)
P
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.

Platinumblond answered 3/2, 2020 at 9:19 Comment(4)
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 votedHousing
This code won't give the current directory; it will give the directory where the executable file is found (on some platforms).Garlandgarlanda
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 "./progTwill
This answer is incorrect. Present working directory is not the same as directory where the executable resides. As Ciro has pointed out already.Hellion
C
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);
Clippard answered 3/2, 2022 at 12:45 Comment(0)
D
1

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;
}
Dafna answered 30/7, 2023 at 16:53 Comment(1)
The question is asking for Windows, not Linux!Given
C
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

Clynes answered 14/10, 2014 at 3:35 Comment(0)
M
0

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

Poco::Path::current()
Misfire answered 17/5, 2019 at 6:52 Comment(0)
A
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;
}
Amplify answered 1/2, 2022 at 10:55 Comment(1)
The question is asking about getting the current directory, not the execute path.Given
G
0

The documentation says...

[out] lpBuffer

A pointer to the buffer that receives the current directory string. This null-terminated string specifies the absolute path to the current directory.

To determine the required buffer size, set this parameter to NULL and the nBufferLength parameter to 0.

You're getting the required buffer size, not the path (NPath is NULL) and you're passing MAX_PATH to nBufferLength.

Wikipedia says...

C++11 corrects this by introducing a new keyword to serve as a distinguished null pointer constant: nullptr. It is of type nullptr_t, which is implicitly convertible and comparable to any pointer type or pointer-to-member type. It is not implicitly convertible or comparable to integral types, except for bool.

There's no way to deference a nullptr and NULL (make an access violation exception).

The code should be this:

LPTSTR NewPath;
DWORD a = GetCurrentDirectory(0, NULL);
NewPath = new TCHAR[a];
GetCurrentDirectory(a, NPath);
HANDLE hNewFile = CreateFile(NewPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
Given answered 2/11, 2023 at 14:12 Comment(0)
L
-1

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

TCHAR szFilePath[_MAX_PATH];
::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
Lest answered 17/5, 2009 at 19:22 Comment(0)
M
-2
String^ exePath = Application::ExecutablePath;<br>
MessageBox::Show(exePath);
Merimerida answered 19/4, 2014 at 6:8 Comment(1)
The question doesn't say it's managed or not, so default it's unmanaged, don't post C++ managed code!Given
E
-3

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

system( "cd" );
Ecdysis answered 15/2, 2023 at 19:18 Comment(2)
Better avoid the impression of belittling other answers.Replay
Please make the additional insight more obvious which you contribute beyond existing answers, e.g. https://mcmap.net/q/202440/-how-to-get-current-directoryReplay
P
-4

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

std::cout << "Current Directory = ";
system("cd"); // to see the current executable directory
Pillowcase answered 29/3, 2022 at 13:52 Comment(1)
How storing to a variable?Given

© 2022 - 2024 — McMap. All rights reserved.