Get Working Directory Windows

Hi, I am currently following a book about SFML, but I am having a problem with getting the current working Directory. What is wrong with it, I have read other that have had the same problem but I still can't figure it out.
Here is my program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifdef RUNNING_WINDOWS
	#define WIN32_LEAN_AND_MEAN
	#include <windows.h>
	#include <Shlwapi.h>
	inline std::string GetWorkingDirectory(){
		HMODULE hModule = GetModuleHandle(nullptr);
		if(hModule){
			char path[256];
			GetModuleFileName(hModule,path,sizeof(path));
			PathRemoveFileSpec(path);
			strcat_s(path,"\\");
			return std::string(path);
		}
		return "";
	}
What problem do you have?

I get the same results with your function as I do with this one:
1
2
3
4
5
6
7
8
9
#include <string>
#include <windows.h>

std::string workingdir()
{
    char buf[256];
    GetCurrentDirectoryA(256, buf);
    return std::string(buf) + '\\';
}



Sorry, my mistake
 
    strcat_s(path,"\\");
should be
 
    strcat_s(path, sizeof path, "\\");


(compiler - dependent).
Last edited on
There is an overload of strcat_s that handles the sizeof() param if it's passed an array (but not a pointer) as the first param. So...

1
2
char path[256];
strcat_s(path,"\\");


should be fine.

What error are you getting? Are you hitting Unicode vs ANSI issues? If so, do what Chervil did and use the -A forms of function (GetModuleFileNameA, PathRemoveFileSpecA)

Or is something else going wrong?

But the right way to get the (current) working directory is to use GetCurrentDirectory(), as shown by Chervil. Your function is returning the directory where the running executable is located, which is not always the working directory. If that's what you need, give your function another name as it doesn't behave the same way as the standard CRT getcwd() (sometimes _getcwd() with Microsoft CRT) and GetCurrentDirectory() and could lead to confusion.

And the WinSDK headers supply the define MAX_PATH for use when declaring buffers to hold paths (it's value is 260.) So you should use that instead.

char buf[MAX_PATH];

(You will also see _MAX_PATH being used, which is the corresponding define provided by the Microsoft CRT library. It has the same value.)

Andy
Last edited on
There is an overload of strcat_s that handles the sizeof() automatically if the first parameter is an array (but not a pointer.) So

1
2
	char path[256];
	strcat_s(path,"\\");


should be fine.

But note that the WinSDK headers provide the define MAX_PATH for in this situation.

char path[MAX_PATH];

It has a value of 260, as does the corresponding Microsoft CRT define _MAX_PATH.

What error are you getting? If it's a Unicode versus ANSI problem, then do as Chervil did and use the -A entrypoints (i.e. GetModuleFileNameA and PathRemoveFileSpecA.)

Or is something else going wrong?

Regards

Andy
Last edited on
While I'm here

1. Passing NULL to GetModuleFileName() does the same thing as passing the current module handle as obtained by calling GetModuleHandle(NULL.) So you can replace

1
2
3
4
	HMODULE hModule = GetModuleHandle(nullptr);
	if(hModule){
		char path[256];
		GetModuleFileName(hModule,path,sizeof(path));


with

1
2
	char path[256];
	GetModuleFileName(nullptr,path,sizeof(path));


(Incidentally, the if() in your code isn't needed as GetModuleHandle(NULL) will never, ever fail. The current exe must always be there!)

2. As you're using the Path API already, you could use PathAppendBackslash rather than strcat_s()

3. Your function does not return the (current) working directory, as returned by the CRT call getcwd() or _getcwd() or GetCurrentDirectory(). It returns the directory where the running exe is located, which is not always the case. So your function should be renamed to avoid confusion with the standard calls.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// This is Microsoft Visual C++ specific code

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <Shlwapi.h>
#pragma comment(lib, "shlwapi.lib")

#include <iostream>
#include <string>
#include <cstring>
using namespace std;

inline std::string GetExeDir() {
	char path[MAX_PATH] = "";
	GetModuleFileNameA(NULL, path, MAX_PATH);
	PathRemoveFileSpecA(path);
	PathAddBackslashA(path);
	return path;
}

std::string GetWorkingDir() {
	char path[MAX_PATH] = "";
	GetCurrentDirectoryA(MAX_PATH, path);
	PathAddBackslashA(path);
	return path;
}

int main() {
	std::string exeDir     = GetExeDir();
	std::string workingDir = GetWorkingDir();
	cout << "Exe Dir     = " << exeDir     << "\n";
	cout << "Working Dir = " << workingDir << "\n";
	return 0;
}


When run from Visual Studio I get

Exe Dir     = W:\Source\Explore\cplusplus_vc10\Debug\
Working Dir = W:\Source\Explore\cplusplus_vc10\temp_test\


As the default working directory is the project directory but the exe is built into the solution's debug folder.
Last edited on
Topic archived. No new replies allowed.