How do I reference a file location in C++? - 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.

Related

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.

Files being created in the wrong folder

To give a little context: I'm writing a program that uses text files and BMP files. For the text files I was provided with a class to manage them and I'm using EasyBMP for the BMP manipulation.
The problem I have is the files are being created in the wrong folder unless I provide the full path.
Example:
#include "EasyBMP.h"
int main(){
BMP picture;
picture.SetSize(640,480);
picture.WriteToFile("picture.BMP");
return 0;
}
Expected result: 640x480 BMP file created somewhere in my project folder (C:\Users[user]\Documents\C++\TP 1)
Actual result: 640x480 BMP file created in Eclipse folder (C:\Users[user]\Documents\Eclipse)
The same happens with any other file I write to disk.
It used to work fine on a different project so I'm guessing there's something silly I'm missing somewhere but I haven't been able to find a solution.
EDIT: The exact same code works fine on a different project.
If you don't specify a full pathname, files are stored in the process's current folder. You can change that in Eclipse (tell if which folder to run from when you run the process).
If you always want the files to be stored where your EXE is, or somewhere around the EXE, you can find the folder yourself(the first argument to main is the location of the EXE file).
The program will write the file in the working directory. That's because you used a relative path and relative paths are relative to the working directory.
Either specify a full path in your code, or ensure that the working directory is set to your desired value when running the program.

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);

Application path location in MS windows

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.