Application path location in MS windows - c++

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.

Related

How do I reference a file location in C++?

I'm trying to reference some images so that this bit of code can work on any PC, not just my own.
pictureBox1->ImageLocation = "C:\\Users\\W10\\Desktop\\pacanelematii\\cireasamtii.png";
It's a small project in c++, using windows forms in visual studio. Can't get the referencing to work.
From what I understood in should look something like "..Debug\pacanelematii\portocalamatii.png"
or "..pacanelematii\portocalamatii.png", but neither is working. I'm thinking that once the file path is referenced to the .exe, I can easily copy the whole folder of the .exe and send the app to anyone willing to try it out. I copied the "pacanelematii" folder to "Debug"
At the start of your program, you should set the current working directory to the folder containing the executable. With the Win32 API, you would do it like this:
wchar_t path[MAX_PATH];
GetModuleFileNameW(NULL, path, MAX_PATH);
PathCchRemoveFileSpec(path, MAX_PATH);
SetCurrentDirectory(path);
Then, make sure the image is placed in the directory of the executable, and simply use its relative path.
For example, you could place it into a folder Images next to the executable, and use it as Images/imagename.png.

what is the proper method of using resource files in MFC project?

i have made a MFC-based game and my project includes images and sounds. Now i want to create an installer setup in order to distribute it.
i have used the resources by providing their exact path in e.g
img->Load(L"C:\\Users\\Ad33l's\\Desktop\\block mania\\block mania\\res\\db.png");
MCIWndCreate(NULL, NULL,WS_POPUP|MCIWNDF_NOPLAYBAR|MCIWNDF_NOMENU,L"C:\\Users\\Ad33l's\\Desktop\\block mania\\block mania\\res\\tick.wav");
1.Can someone tell me any way to avoid Hard-coding the actual resource path as these resource files will not be present at this same exact path in other computers ?
2.Also guide me to handle these resource files during the creation of standalone SETUP (i am using advance installer )
(as an actual answer).
Do not use absolute path, always use relative path; relative to your EXE file is one solution.
The EXE path can be found using GetModuleFileName.
char appPath[MAXFILENAMELEN];
GetModuleFileName(NULL, appPath, MAXFILENAMELEN);
(addendum) appPath name is misleading, it contains the full name of the application; you need to extract the path from the full application name.
We do something like this:
(edit to make it compilable in unicode)
TCHAR applicationPath[MAX_PATH];
GetModuleFileName(NULL, applicationPath, MAX_PATH);
CString sSoundFile(applicationPath);
PathRemoveFileSpec(sSoundFile.GetBuffer());
sSoundFile.ReleaseBuffer();
From there, you can do something like (pseudocode-ish):
img.Load( appPath + "//Images//db.png" );
You can have a variable that saves the directory they want to install your program in. After they choose the directory they want to install it in, go off of that. Or you can also use system folders like the appdata folder
A first solution would be to configure your setup project to install the installation files under the DesktopFolder\block mania\block mania\res. Then, you can access within your application the current user Desktop location and append to it the remaining fix location (block mania\block mania\res).
Another solution would be to configure the setup project to create registries at install time which will store the paths of the installation files. Then, your application could read the installation paths from registry.
Finally you could also create at install time environment variables containing the paths of the installation file and, then use within your application the environment variables to access the installed files locations.

Opening a file in the current directory

I'm trying to load files, and previously I was using hardcoded file locations, (like "c:\location\file.txt") but now that a few friends are also using the file, I'd like to allow them to put the executable wherever they want.
my current code looks like:
ifstream myfile;
myfile.open("c:\\client\\settings.cfg");
I'm trying to change it so that the user puts their executable into whatever folder they want, and then they create a folder and put their settings file into it and the exe will load that with their settings.
ifstream myfile;
myfile.open("\\settings\\settings.cfg");
I have some basic error handling in place, and now the program always errors out saying that it can't find the file.
The file structure looks like this:
[ART]
asset.png
[SETTINGS]
settings.cfg
client.exe
This seems like a really simple thing to do, but I can't find any way to do it. Every example and tutorial about reading and writing to files deals only with files in the executable's directory, or hardcoded into c:\folder...
Could anyone point me to how I do this?
The search path for most systems starts with the current working directory and then to a PATH environment variable. So, all you need to do is specify the file/folder without the absolute path markings and it will use the path relative to the working directory:
ifstream myfile;
myfile.open("settings\\settings.cfg");
// ^^ Note the lack of \\ to start the file path
Paths beginning with \ are always relative to the current drive's root directory. If the current drive is C:, then \settings\settings.cfg means C:\settings\settings.cfg.
Note that you can use / in order to avoid escaping everything. So you can use: settings/settings.cfg. This will be relative to the user's current directory. Note however, that this doesn't necessarily correspond to the directory where the executable resides. If you need the directory of the executable, then you need to use a Windows API function to get it:
#include <Windows.h>
// ...
HMODULE module = GetModuleHandleW(NULL);
WCHAR path[MAX_PATH];
GetModuleFileNameW(module, path, MAX_PATH);
Now if you want to open settings/settings.cfg relative to the directory of the executable, create a path that starts with path and append /settings/settings.cfg to it.

File I/O from current Windows position C++

I have not yet found a definitive answer about this. I am trying to have access to files in subfolders from my .EXE. When I have asked before, people tell me to use the absolute location i.e. "c:/game/info/" if I wanted to access something in /info/
But it is completely unreasonable for me or anyone to assume that someone is going to use their program from the same directory. What if the user only has a D drive? That sort of thing.
So my question is: how can I access a file in a subdirectory from my executable without relying on the entire path?
Your title says "Windows", so I'll give a WinAPI-specific answer.
On Windows, you can find your application directory with GetModuleFileName(NULL, ...), and PathRemoveFileSpec. Then PathAppend will make the full path to your data files.
Or you can store the data inside you .exe file as Win32 resources, so they never get separated.
Please note that this approach generally works only for read-only access to data files. If you try to write files in your application directory, you might be blocked by ACLs (depending on install location and local security settings of the computer).
Use GetModuleFileName (Retrieves the fully-qualified path for the file that contains the specified module. The module must have been loaded by the current process.)
char strExePath [MAX_PATH];
GetModuleFileName (NULL, strExePath, MAX_PATH);
You'll then need to extract the folder path (someone has already posted how to do that), and combine your path.
Make or use an installer that asks the user where to install the executable and writes that path to the registry in a well-known location for later reference.
if you use:
#include <fstream>
ifstream stream("file");
it will be working. "file" is file in directory with your exe. Of course if you want go up or down in folders hierarchy use "..\file" or "folder\file"

Opening a file with a certain program changes that programs working directory?

I have a file saved to my desktop, when I open it with my program the working directory changes to the desktop, this means my program can not load in some files it needs as it searches for these in the working directory. Is there a way I can stop the working directory from changing like this?
There's a flag you can set to avoid the current directory from changing called OFN_NOCHANGEDIR
http://msdn.microsoft.com/en-us/library/ms646839(v=vs.85).aspx
You can just save your working directory at startup and use absolute paths. In fact, it's better to always open files with absolute paths, unless you really want to rely on the current working directory.
You would be better off determining the processes location, then using it as the key for where to find the other files? There are many ways that programs can be launched, which effect the working directory.
See: The answer here for a good description of how to get the processes location and strip out the executable filename (look in the comments)
Essentially, you use:
GetModuleFileName or GetModuleFileNameEx.
and then:
PathRemoveFileSpec to remove the file name
Opening a file doesn't change your current directory. Perhaps you using the common open file dialog? Here is an article that will explain all about how that changes your current directory.
use SetCurrentDirectory to do that.
You can locate the executable by using GetModuleFileName
TCHAR szFileName[MAX_PATH];
GetModuleFileName( NULL, szFileName, MAX_PATH )
... then compute the correct directory
SetCurrentDirectory(path);