in the directory containing my exe I have a folder called "saves".
I want to display the files this directory contains.
I used the code found here:
Listing directory contents using C and Windows
Now the tricky part.
if I use .\\saves\\ as my directory it tells me that the path could not be found.
However if I use ..\\release\\saves\\ it works fine. But that's stupid. I don't want to go to the parent folder and than go back. Especially regarding that I don't know what name the user gives to the directory containing the exe (in my case it's "release" but who knows what the user does :-D).
I read through this: http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85).aspx#fully_qualified_vs._relative_paths but it didn't help very much.
I also tried saves\\ or .\saves\\ but it doesn't work either.
I hope somebody can tell me how to fix this.
You're actually doing nothing wrong in code -- you've been launching the project from Visual Studio, which sets the Working Directory to the parent of the Release/Debug folders.
Go to Project->Settings(Properties)->Configuration Properties->Debugging->Working Directory
You can also run the exe outside of VS and the relative paths will behave like you expect.
If it is relative from the path to the executable, and not from the path of the current working directory, you could use GetModuleFileName() to obtain the full path to the executable. Then, remove the name of the executable from the end of the path and build the paths using that:
std::string executable_directory_path()
{
std::vector<char> full_path_exe(MAX_PATH);
for (;;)
{
const DWORD result = GetModuleFileName(NULL,
&full_path_exe[0],
full_path_exe.size());
if (result == 0)
{
// Report failure to caller.
}
else if (full_path_exe.size() == result)
{
// Buffer too small: increase size.
full_path_exe.resize(full_path_exe.size() * 2);
}
else
{
// Success.
break;
}
}
// Remove executable name.
std::string result(full_path_exe.begin(), full_path_exe.end());
std::string::size_type i = result.find_last_of("\\/");
if (std::string::npos != i) result.erase(i);
return result;
}
I would use boost::filesystem
http://www.boost.org/doc/libs/1_53_0/libs/filesystem/doc/index.htm.
As a bonus you will get operating system independent code.
I think your mistake was using \\saves\\and forgeting to specify a search parameter/string
You should use:
saves\\*
this will search for any file or folder
Related
I already know how to set a relative working directory path and access resources inside of visual studio. However, when I build my solution and move the exe to a separate file I have to include all the resources in the same directory as the exe. I'd prefer to have a folder with said resources alongside the exe to keep things clean. Is there a macro I need to use? Is the working directory the right setting to change for this?
example
Sorry for this incredibly basic question, but I think I lack the vocabulary to accurately describe the issue.
For a Windows solution, GetModuleFileName to find the exact path of your EXE. Then a simple string manipulation to make a resource path string.
When you program starts, you can use this to ascertain the full path of your EXE.
std::string pathToExe(MAX_PATH, '\0');
GetModuleFileName(nullptr, szPathToExe.data(), MAX_PATH); // #include <windows.h> to get this function declared
On return, szPathToExe will be something like "C:\\Path\\To\\Your\\Program\\Circle.exe"
Then strip off the file name to get the absolute path
std::string resourceFolderPath = szPathToExe;
size_t pos = strPath.find_last_of("\\");
strPath = strPath.substr(0, pos+1); //+1 to include the backslash
Then append your resource folder name and optionally another trailing backslash.
resourceFolderPath += "res\\";
Then change all your I/O calls to open files relative to resourceFolderPath
You should probably add reasonable error checking to the above code such as validating the return code from GetModuleFileName and find_last_of calls.
I want to create a program that opens another .exe file in C++, I want the program to be able to run from any directory, so I will not know the full address of the file.
Eg-
The Program that I make will be present in a folder, which in turn has subfolders, which further contains javaportable.exe. I want the program to run the above mentioned .exe without getting the full path. Something like cd operator in normal DOS navigation. Also, if it is possible, I want to select another .exe, which will run through javaportable.exe, and is present in the previous folder.
First of all the standard C++ library does not provide any such functions to list the files of a directory. You can use boost libraries to get this done. Solution to this problem is not that easy. You will have to implement a lot of techniques to get this done. I can give you all the possible starting pointers.
To port this code to other OS you may need to add OS specific code using # preprocessor directives. Boost Liberay is already cross platform.
First of all you need to get the current path of the directory your program is present in:
For this you can use the following windows os specific code
#include <iostream>
#include <direct.h>
int main(){
char *path = NULL;
path = _getcwd(NULL, 0); // or _getcwd
if (path != NULL)
std::cout << path;
}
Here the path variable contains the address of the current directory. You can pass this path to the next function which will further use it to list the files and directories for you. For listing the directories you can use Boost Liberaries http://www.boost.org/
Next you will need to get all the files and folders present in current directory. Use Boost library for this
Use this sample code from boost
http://www.boost.org/doc/libs/1_37_0/libs/filesystem/example/simple_ls.cpp
Then make a class and store the address received and files names with path in its objects. You can store all the listed address in a object like dir[1].str[size], dir[2].str[size],...so on.
Now again pass all the folder addresses you received to boost function and get further filenames. All of the above will require many passes.
You can also get the list of files for specific file extension too:
#define BOOST_FILESYSTEM_VERSION 3
#define BOOST_FILESYSTEM_NO_DEPRECATED
#include <boost/filesystem.hpp>
namespace fs = ::boost::filesystem;
// return the filenames of all files that have the specified extension
// in the specified directory and all subdirectories
void get_all(const fs::path& root, const string& ext, vector<fs::path>& ret)
{
if(!fs::exists(root) || !fs::is_directory(root)) return;
fs::recursive_directory_iterator it(root);
fs::recursive_directory_iterator endit;
while(it != endit)
{
if(fs::is_regular_file(*it) && it->path().extension() == ext) ret.push_back(it->path().filename());
++it;
}
}
Finally compare the filenames with the one you want to run and execute it.
The problem can be solved by many other methods too but I think it will be good to start and you can always improve your code.
References:
How to get list of files with a specific extension in a given folder
http://www.boost.org/
How do I get a list of files in a directory in C++?
Hope this helps. If you need any further help feel free to ask!
I am running an exe that reads text from a file, which is saved in the same directory as the exe.
I am using the _tfopen function, that returns errno 2, which means that the file is missing.
As is already said, the text file is in the same directory as the exe, so Im using only filename of the text file and not the whole path (even though ive tried to use the absolute filepath...).
I am running the exe from a different computer, not the one I am developing on (The release version).
Another application that using the same file, also in the same directory, works perfectly.
Why does the exe cant find the text file?
FILE* fileData;
if ((fileData = _tfopen(_T("Data.txt"), _T("r"))) == NULL)
return false;
You might want to try this: have your program call GetCurrentDirectory() and output the result somewhere to that you can confirm that the program's current directory is truly what you think it is. You could use OutputDebugString() if you are running under a debugger or MessageBox() if not.
When I need to be sure I'm opening a co-located file, I call GetModuleFileName( NULL, szExeFqn, sizeof(szExeFqn)) to get the FQN of the EXE file, strip off the EXE file name and add on the name of the file I need. That way, I'm not making any assumptions that might be false -- after all, it is trivial to have a shortcut set the default directory for a program different from the directory containing the EXE file.
Also, if you run your program from a command line by entering the full path to your program, then the program's current directory is the one you were in when you ran it, not the one where the EXE was found. That's also true if your program is found by searching the PATH environment variable (yes, it still exists in Windows.)
Here's an example of what I've used for more than a decade to do what you've described:
char szHelpFileName[_MAX_FNAME];
char *cp;
GetModuleFileName( NULL, szHelpFileName, sizeof(szHelpFileName) );
cp = strrchr( szHelpFileName, '\\' );
if( cp )
{
cp++; // Point to the char just following the final slash.
}
else
{ // No backslash, is there a colon?
cp = strrchr( szHelpFileName, ':' );
if( cp )
{
cp++; // Point to the char just following the colon.
}
else
{ // I give up. I'll have no path information.
cp = szHelpFileName;
}
}
strcpy( cp, "program.hlp" );
The final result is the name of a help file that is co-located with the EXE. Unless the help file is missing (or its permissions have been scrogged somehow) this always works. I've never had it follow the "paranoia" path where the comment says "I give up."
Usually operating systems open files with relative address based on the current directory, rather than the executable location.
So for example if your executable is in /path/to/exec/executable and you invoke it from /path/to/invoke, it will try to open Data.txt as if it was /path/to/invoke/Data.txt.
You can take a look at this question and its answers to find out how to find the path to executable in Windows. Or this answer for various other operating systems.
It should work even without specifying the full path. Do you launch the executable from Visual Studio? If yes, make sure that the Data.txt file is inside the project directory where the *.vcxproj file or the *.sln file is.
I'm a .net developer mostly, doing something small in C++ so im having a little trouble.
I'm loading another C++ dll using hInst = LoadLibrary(TEXT("mydll.dll")); and I came to realize that this looks for the dll I'm trying to load in 'C:\' or in 'system32'.
Can someone show me how to load the dll from the current directory (without knowing what the current directory is ahead of time) ??
I know I should be using something like GetFullPathName but I'm having a little trouble getting it to work on my own...
The process current directory can be acquired using the function GetCurrentDirectory():
TCHAR bufCurrentDirectory[MAX_PATH + 1] = { 0 };
DWORD dwNumCharacters = ::GetCurrentDirectory(MAX_PATH, bufCurrentDirectory);
if(dwNumCharacters == 0) error();
Now the path to the process's current directory is in bufCurrentDirectory, unless the function failed. Just append "\\mydll.dll" onto the path, and you have an absolute path to the DLL.
Since the current directory of a process is somewhat variable, it may be better to use the path of the executable. To get the path of the current executable, you can do:
TCHAR bufExePath[MAX_PATH + 1] = { 0 };
DWORD dwNumCharacters = ::GetModuleFileName(NULL, bufExePath, MAX_PATH);
if(dwNumCharacters == 0) error();
Now bufExePath contains the entire path to the exe, including "\\my.exe". Replace my.exe with mydll.dll, and you'll have the absolute path to the DLL. I would recommend this method over the GetCurrentDirectory() method due to security concerns.
I believe loading from current directory is the default and first search. See the MSDN reference
The first directory searched is the
directory containing the image file
used to create the calling process
(for more information, see the
CreateProcess function). Doing this
allows private dynamic-link library
(DLL) files associated with a process
to be found without adding the
process's installed directory to the
PATH environment variable
http://msdn.microsoft.com/en-us/library/ms684175(v=vs.85).aspx
Use GetCurrentDirectory.
Where should I store the application installation folder for application to reffer ?
I believe what you're looking for is the GetModuleFileName function, which you can use like so:
// get the full path to the current executable
wchar_t fullPath[MAX_PATH];
GetModuleFileName(NULL, fullPath, MAX_PATH);
// cut the string at the last slash, because we just want the directory
// not the actual executeable file name.
TCHAR *lastSlash = wcsrchr(fullPath, L'\\');
lastSlash = 0;
// directory where the executable is location is fullPath
This will work regardless of the current working directory and in general, this is how I do all "relative path" stuff (that is, I never actually use relative paths, they're always absolute paths, based off the value returned from the function above).
You can use the registry for storing installation folders.
::GetModuleFileName(NULL, out_lpPathName, in_size) will give you full path of your executable file.
ApplicationData folder, even not admin access can help to access you install data. use SHGetSpecialFolderPath with CISDL CSIDL_APPDATA
In the registry. To be specific, under HKEY_LOCAL_MACHINE\SOFTWARE\YourCompanyName\YourApplicationName\ if you installed your app for all users (i.e. in \Program Files), and under HKEY_CURRENT_USER\SOFTWARE\YourCompanyName\YourApplicationName\ if you installed it for a single user only.