Well, the title say which is my problem
my .cpp code is:
GetPrivateProfileString("Server","MainDns","ServerDns",
g_DataBaseDns,sizeof(g_DataBaseDns),".\\Server.ini");
when I use:
GetPrivateProfileString("Server","MainDns","ServerDns",
g_DataBaseDns,sizeof(g_DataBaseDns),"..\\Server.ini");
and Put the ini file in the back folder: works normally!
What am I doing wrong?
You need to first call GetFullPathName() to obtain an absolute path, which is required according to the documentation for GetPrivateProfileString():
The name of the initialization file. If this parameter does not contain a full path to the file, the system searches for the file in the Windows directory.
For example:
TCHAR sAbsolutePathBuffer[2048] = _T("");
if (GetFullPathName(TEXT("Server.ini"), sizeof(sAbsolutePathBuffer)/sizeof(TCHAR), sAbsolutePathBuffer, NULL))
{
GetPrivateProfileString(TEXT("Server"), TEXT("MainDns"), TEXT("ServerDns"),
g_DataBaseDns, sizeof(g_DataBaseDns), sAbsolutePathBuffer);
}
Related
I wish my app to write a file in a specified location, and therefore create the appropriate directory if needed.
The create dir operation isn't a problem for me, but I need the dir path.
I could extract if from the file path, but maybe is there a quick/concise/convenient way of doing the full operation?
I repeat, I'm not searching the basic makedir function, but one which would take the filename of a possibly non-existing file, or a simple qt function to extract the dir path string from the file path string, so I dont' have to write a func for such a basic task.
Use the following code:
const QString filePath = "C:/foo/bar/file.ini";
QDir().mkpath(QFileInfo(filePath).absolutePath());
This code will automatically create the path to the specified (nonexistent) file.
QFileInfo::absolutePath() extracts the absolute path to the specified file.
QDir::mkpath() creates the previously extracted path.
If you have a full path to the file and need to extract the folder path, you can do it this way:
QFile file(full_path_to_the_file);
QFileInfo info(file);
QString directoryPath = info.absolutePath();
//now you can check if the dir exists:
if(QDir(directoryPath).exists())
//do stuff
Depending on what exactly you need, you may prefer to use QFileInfo::canonicalPath() instead of absolutePath
Alternatively, you may also use QFileInfo::absoluteDir:
QFile file(full_path_to_the_file);
QFileInfo info(file);
if(info.absoluteDir().exists())
//do stuff
I'm creating a dll on c++. It is a Visual Studio project. The dll reads some data from ini file. I have decided to use GetPrivateProfileString function. It works almost completely. It does not see file in current directory. How can I provide this parameter (variable called path)?
How can I pass last parameter (path)
Code:
LPCTSTR path = L"\\test.ini";
TCHAR protocolChar[32];
int a = GetPrivateProfileString(_T("Connection"), _T("Protocol"), _T(""), protocolChar, 32, path);
String from test.ini:
[Connection]
Protocol = HTTP
I also tried this:
LPCTSTR path = L"test.ini";
But it did not help me
LPCTSTR path = _T(".\\test.ini");
. symbolises current directory. Hope this will work for you.
WCHAR cfg_IniName[256];
GetCurrentDirectory (MAX_PATH, cfg_IniName );
wcscat ( cfg_IniName, L"\\test.ini" );
way to get full path
I'm trying to download a file from the internet to my temp directory.
This is what I have so far:
HRESULT hr;
LPCTSTR Url = _T("linkhere"), File = _T("C:\\test.exe");
hr = URLDownloadToFile (0, Url, File, 0, 0);
This is working fine.
How do I save the file to the temp directory (using GetTempPath)
Since the directory that's used to store temporary files is configurable, you shouldn't hardcode its path into the application. Instead, use GetTempPath() to ask for the path and then use the result as a prefix, meaning you can simply append "temp.exe" to it.
(Btw, you can use "/" instead "\", since constantly having to escape backslashes is both tedious and error prone. For example, instead of "some\random\path\", you write "some/random/path/").
I am attempting to open a .chm file(A windows help file) at a specific page/topic by using a system call in C++.
I can successfully open the .chm file to the start page through the following code, but how can I open a .chm file to a specific page/topic inside the help file?
system("start c:/help/myhelp.chm");
PS: I know system is evil/discouraged but the system part is not really relevant its the command line arguments I pass with the .chm file(that will specify what page I want to open) that I am trying to determine.
Ok the arguments are like so:
system(" /Q /E:ON /C HH.EXE ms-its:myChm.chm::myPageName.htm");
There is an API in the Windows SDK called HtmlHelp in the HtmlHelp.h file. You can call like so:
HtmlHelp(GetDesktopWindow(), L"C:\\helpfile\\::/helptopic.html", HH_DISPLAY_TOPIC, NULL);
The Microsoft Docs - HtmlHelpA function provides more information about the function. HtmlHelp() will normally resolve to HtmlHelpA() or HtmlHelpW() depending on whether Unicode compiler option is set or not.
See as well Microsoft Docs - HTML Help API Overview.
Another option - use ShellExecute. The Microsoft help is not easy to use. This approach is much easier and in line with your question. Here is a quick routine to open a help file and pass an ID number. I have just set up some simple char’s so you can see what is going on:
void DisplayHelpTopic(int Topic)
{
// The .chm file usually has the same name as the application - if you don’t want to hardcode it...
char *CmndLine = GetCommandLine(); // Gets the command the program started with.
char Dir[255];
GetCurrentDirectory (255, Dir);
char str1[75] = "\0"; // Work string
strncat(str1, CmndLine, (strstr(CmndLine, ".exe") - CmndLine)); // Pull out the first parameter in the command line (should be the executable name) w/out the .exe
char AppName[50] = "\0";
strcpy(AppName, strrchr(str1, '\\')); // Get just the name of the executable, keeping the '\' in front for later when it is appended to the directory
char parms[300];
// Build the parameter string which includes the topic number and the fully qualified .chm application name
sprintf(parms,_T("-mapid %d ms-its:%s%s.chm"), Topic, Dir, AppName);
// Shell out, using My Window handle, specifying the Microsoft help utility, hh.exe, as the 'noun' and passing the parameter string we build above
// NOTE: The full command string will look like this:
// hh.exe -mapid 0 ms-its:C:\\Programs\\Application\\HelpFile.chm
HINSTANCE retval = ShellExecute(MyHndl, _T("open"), _T("hh.exe"), parms, NULL, SW_SHOW);
}
The topics are numbered within your .chm file. I set up a #define for each topic so if I had to change the .chm file I could just change the include file to match and not have to worry about searching through the code for hardcoded values.
Do I always have to specify absolute path for objects instantiated from std::fstream class? In other words, is there a way to specify just relative path to them such as project path?
You can use relative paths as well. But they are relative to the environment you call your executable from.
This is OS dependent but all the major systems behave more or less the same AFAIK.
Windows example:
// File structure:
c:\folder\myprogram.exe
c:\myfile.txt
// Calling command from folder
c:\folder > myprogram.exe
In the above example you could access myfile.txt with "c:/myfile.txt" or "../myfile.txt". If myprogram.exe was called from the root c:\ only the absolute path would work, but instead "myfile.txt" would work.
As Rob Kennedy said in the comments there's really nothing special about paths regarding fstream. But here is a code example using a relative path:
#include <fstream>
int main() {
std::ifstream ifs("../myfile.txt");
... // Do something sensible with the file
}
If you have an .exe file running from C:\Users\Me
and you want to write a file to C:\Users\Me\You\text.txt,
then all what you need to do is to add the current path operator ., so:
std::ifstream ifs(".\\you\\myfile.txt");
will work
You can use relative paths. They're treated the same as relative paths for any other file operations, like fopen; there's nothing special about fstream in that regard.
Exactly how they're treated is implementation-defined; they'll usually be interpretted relative to your process's current working directory, which is not necessarily the same as the directory your program's executable file lives in. Some operating systems might also provide a single working directory shared by all threads, so you might get unexpected results if a thread changes the working directory at the same time another thread tries to use a relative path.
Say you have a src folder directly under your project directory and the src folder contains another tmp_folder folder which contains a txt file named readMe.txt. So the txt file can be read in this way
std::ifstream fin("../src/tmp_folder/readMe.txt");
The behaviour is OS specific. Therefore, the best way to handle this IMHO is to make it somebody else's problem. Read the path to the file to open as a string from the user (e.g: command line argument, config file, env variable etc..) then pass that string directly to the constructor of fstream. Document that this is how your program behaves.
I wrote more about path manipulation here: https://stackoverflow.com/a/40980510/2345997
You can specify a path relative to current directory. On Windows you may call GetCurrentDirectory to retrieve current directory or call SetCurrentDirectory to set current directory. There are also some CRT functions available.
On linux also:
// main.cpp
int main() {
ifstream myFile("../Folder/readme.txt");
// ...
}
Assuming the folder structure is something like this:
/usr/Douments/dev/MyProject/main.cpp
/usr/Documents/dev/MyProject/Folder/readme.txt
What I ended up using was a relative path as identified on How to open a file with relative path in C++? which ended up being:
myFile.open("../Release/frequency.dat", ios::in);
*changing myFile to whatever your variable is.