I am trying get path of the exe file at the same folder where this program will been. but i couldnt figure out how to do, i did something like this but it only gets the current programs path, and i dont know how to replace filenames between my program and the program i want to get path.
so simply can you help me about get the path of an exe (i know the name of that exe ) at the same folder where this program will been...
char fullp[MAX_PATH];
char selfp[MAX_PATH] = "..//myprogram.exe";
char otherprogram[MAX_PATH] = "//test.exe";
DWORD szPath;
szPath = GetModuleFileName(NULL, selfp, sizeof(selfp));
The Win32 API has a whole bunch of Path Handling functions available.
For instance, once you have obtained the calling process's full path from GetModuleFileName(), you can use PathRemoveFileSpec() to remove the filename leaving just the folder path:
char selfdir[MAX_PATH] = {0};
GetModuleFileNameA(NULL, selfdir, MAX_PATH);
PathRemoveFileSpecA(selfdir);
And then use either PathAppend() or PathCombine() to append a different filename to that path:
char otherprogram[MAX_PATH] = {0};
lstrcpyA(otherprogram, selfdir);
PathAppendA(otherprogram, "test.exe");
char otherprogram[MAX_PATH] = {0};
PathCombineA(otherprogram, selfdir, "test.exe");
OP is most of the way there. Here is an example of how to get the rest of the way.
To simplify the solution, I'm leaving char arrays as far behind as possible and using std::string.
#include <iostream>
#include <string>
#include <windows.h>
int main()
{
char selfp[MAX_PATH];
std::string otherprogram = "Failed to get path";
DWORD szPath;
szPath = GetModuleFileName(NULL, selfp, MAX_PATH);
if (szPath != 0) // successfully got path of current program
{
// helper string to make life much, much easier
std::string helper = selfp;
//find last backslash in current program path
size_t pos = helper.find_last_of( "\\" );
if (pos != std::string::npos) // found last backslash
{
// remove everything after last backslash. This should remove
// the current program's name.
otherprogram = helper.substr( 0, pos+1);
// append new program name
otherprogram += "test.exe";
}
}
std::cout << otherprogram << std::endl;
}
Related
This question already has answers here:
Getting user temporary folder path in Windows
(9 answers)
Closed 1 year ago.
I am trying to create a simple console app, that just cleans %temp% files.
So, how can I find the username and system disk to input it in directory of temp files?
This is a string variable, where I plan to store the %temp% directory:
string tempDir = sysDisk << ":/Users/" << userName << "AppData/Local/Temp/"
You are going about this all wrong. You don't need to retrieve the system disk or username at all. Especially since the location of the %temp% folder is user-defined, so there is no guarantee that it is even located at the path you are trying to create. And also that the location of Windows' USERS and TEMP folders have changed over time, and so may change again in the future.
The correct solution is to ask the OS exactly where the user's actual %temp% folder is currently located.
For instance, by using either:
std::getenv()
#include <cstdlib>
std::string tempDir = std::getenv("TEMP");
std::filesystem::temp_directory_path()
#include <filesystem>
std::string tempDir = std::filesystem::temp_directory_path().string();
Or, using Win32 API functions:
GetTempPath()
#include <windows.h>
char path[MAX_PATH] = {};
DWORD len = GetTempPath(path, MAX_PATH);
std::string tempDir(path, len);
GetEnvironmentVariable()
#include <windows.h>
char path[MAX_PATH] = {};
DWORD len = GetEnvironmentVariable("TEMP", path, MAX_PATH);
std::string tempDir(path, len);
ExpandEnvironmentStrings()
#include <windows.h>
char path[MAX_PATH] = {};
DWORD len = ExpandEnvironmentStrings("%TEMP%", path, MAX_PATH);
std::string tempDir(path, len-1);
// This would be useful when dealing with individual filenames, eg:
// ExpandEnvironmentStrings("%TEMP%\filename.ext", path, MAX_PATH);
The code below demonstrates how stat and GetFileAttributes fail when the path contains some strange (but valid) ASCII characters.
As a workaround, I would use the 8.3 DOS file name. But this does not work when the drive has 8.3 names disabled.
(8.3 names are disabled with the fsutil command: fsutil behavior set disable8dot3 1).
Is it possible to get stat and/or GetFileAttributes to work in this case?
If not, is there another way of determining whether or not a path is a directory or file?
#include "stdafx.h"
#include <sys/stat.h>
#include <string>
#include <Windows.h>
#include <atlpath.h>
std::wstring s2ws(const std::string& s)
{
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}
// The final characters in the path below are 0xc3 (Ã) and 0x3f (?).
// Create a test directory with the name à and set TEST_DIR below to your test directory.
const char* TEST_DIR = "D:\\tmp\\VisualStudio\\TestProject\\ConsoleApplication1\\test_data\\Ã";
int main()
{
std::string testDir = TEST_DIR;
// test stat and _wstat
struct stat st;
const auto statSucceeded = stat(testDir.c_str(), &st) == 0;
if (!statSucceeded)
{
printf("stat failed\n");
}
std::wstring testDirW = s2ws(testDir);
struct _stat64i32 stW;
const auto statSucceededW = _wstat(testDirW.data(), &stW) == 0;
if (!statSucceededW)
{
printf("_wstat failed\n");
}
// test PathIsDirectory
const auto isDir = PathIsDirectory(testDirW.c_str()) != 0;
if (!isDir)
{
printf("PathIsDirectory failed\n");
}
// test GetFileAttributes
const auto fileAttributes = ::GetFileAttributes(testDirW.c_str());
const auto getFileAttributesWSucceeded = fileAttributes != INVALID_FILE_ATTRIBUTES;
if (!getFileAttributesWSucceeded)
{
printf("GetFileAttributes failed\n");
}
return 0;
}
The problem you have encountered comes from using the MultiByteToWideChar function. Using CP_ACP can default to a code page that does not support some characters. If you change the default system code page to UTF8, your code will work. Since you cannot tell your clients what code page to use, you can use a third party library such as International Components for Unicode to convert from the host code page to UTF16.
I ran your code using console code page 65001 and VS2015 and your code worked as written. I also added positive printfs to verify that it did work.
Don't start with a narrow string literal and try to convert it, start with a wide string literal - one that represents the actual filename. You can use hexadecimal escape sequences to avoid any dependency on the encoding of the source code.
If the actual code doesn't use string literals, the best resolution depends on the situation; for example, if the file name is being read from a file, you need to make sure that you know what encoding the file is in and perform the conversion accordingly.
If the actual code reads the filename from the command line arguments, you can use wmain() instead of main() to get the arguments as wide strings.
Hi i am trying to make a GUI for image compare software. The idea is to choose a picture with OPENFILENAME, then get its address with ofn.lpstrFile then make a histogram for that image. So i use:
return(ofn.lpstrFile);
I can cout the address or write it to an .xml file and the address is correct, but when i am trying to do the histogram it gives me all zeros. Behaves like the address was invalid.
Any ideas ?
my code :
string path=browse(); //getting the string from ofn.lpstrFile
path.c_str();
replace(path.begin(), path.end(), '\\', '/'); //converting backslash to slash also may be the problem
HistCreation(path,root_dir);
and
void HistCreation(string path,string root_dir) {
Mat img;
img = imread(path); // here if i manually enter the address everything works fine, if I insert the path then loads empty image
.
.
.
I also tried
char * cstr = new char[path.length() + 1];
std::strcpy(cstr, path.c_str());
Did not work either
std::string returns the string and that's all you need. This is example to open a bitmap file.
(Edit)
#include <iostream>
#include <string>
#include <windows.h>
std::string browse(HWND hwnd)
{
std::string path(MAX_PATH, '\0');
OPENFILENAME ofn = { sizeof(OPENFILENAME) };
ofn.hwndOwner = hwnd;
ofn.lpstrFilter =
"Image files (*.jpg;*.png;*.bmp)\0*.jpg;*.png;*.bmp\0"
"All files\0*.*\0";
ofn.lpstrFile = &path[0];
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn))
{
//string::size() is still MAX_PATH
//strlen is the actual string size (not including the null-terminator)
//update size:
path.resize(strlen(path.c_str()));
}
return path;
}
int main()
{
std::string path = browse(0);
int len = strlen(path.c_str());
if (len)
std::cout << path.c_str() << "\n";
return 0;
}
Note, Windows uses NUL-terminated C-strings. It knows the length of the string by looking for the zero at the end.
std::string::size() is not always the same thing. We can call resize to make sure they are the same thing.
You shouldn't need to replace \\ with /. If your library complains about \\ then replace as follows:
Example:
...
#include <algorithm>
...
std::replace(path.begin(), path.end(), '\\', '/');
Use std::cout to examine the output instead of guessing if it worked or not. In Windows program you can use OutputDebugString or MessageBox to see what the string is.
HistCreation(path, root_dir);
I don't know what root_dir is supposed to be. If HistCreation fails or it has the wrong parameter then you have a different problem.
I need a way to move a file to another directory without having to specify the file name in the destination directory.
TCHAR szFileName[MAX_PATH];
GetModuleFileName(NULL, szFileName, MAX_PATH);
wchar_t* Favfolder = 0;
SHGetKnownFolderPath(FOLDERID_Favorites, 0, NULL, &Favfolder);
wstringstream ss(szFileName);
wstringstream ff(Favfolder);
rename(ss.str(), ff.str()); //Won't work
If I use rename, ff.str()doesn't include the file name, so it won't work.
The proper way to do it would be to write:
rename(C:\\Users\\blah\\blah\\filename.exe, C:\\Users\\blah\\newdir\\filename.exe);
What I'm doing is:
rename(C:\\Users\\blah\\blah\\filename.exe, C:\\Users\\blah\\newdir);
But I can't figure out a way to include the filename.exe in the second example.
I assume that you are using wstring, not a wstringstream.
Use find_last_of(link) to find the position of last \ in the ss.
Get the filename by substr(link).
Paste the filename at the end of ff.
EDIT:
Function which do all the work:
int move(const string &oldPath, const string &newDir)
{
const size_t pos = oldPath.find_last_of('\\');
const string newPath = newDir + '\\' + (pos == string::npos ? oldPath : oldPath.substr(pos));
return rename(oldPath.c_str(), newPath.c_str());
}
Unfortunately, rename doesn't support wchar_t so I did have to use a string, not a wstring
I'm using something like this:
std::string tempDirectory = "./test/*";
WIN32_FIND_DATA directoryHandle;
memset(&directoryHandle, 0, sizeof(WIN32_FIND_DATA));//perhaps redundant???
std::wstring wideString = std::wstring(tempDirectory.begin(), tempDirectory.end());
LPCWSTR directoryPath = wideString.c_str();
//iterate over all files
HANDLE handle = FindFirstFile(directoryPath, &directoryHandle);
while(INVALID_HANDLE_VALUE != handle)
{
//skip non-files
if (!(directoryHandle.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
//convert from WCHAR to std::string
size_t size = wcslen(directoryHandle.cFileName);
char * buffer = new char [2 * size + 2];
wcstombs(buffer, directoryHandle.cFileName, 2 * size + 2);
std::string file(buffer);
delete [] buffer;
std::cout << file;
}
if(FALSE == FindNextFile(handle, &directoryHandle)) break;
}
//close the handle
FindClose(handle);
which prints the names of each file in the relative directory ./test/*.
Is there any way to determine the absolute path of this directory, just like realpath() does on Linux without involving any 3rd party libraries like BOOST? I'd like to print the absolute path to each file.
See the GetFullPathName function.
You can try GetFullPathName
Or you can use SetCurrentDirectory and GetCurrentDirectory. You might want to save the current directory before doing this so you can go back to it afterwards.
In both cases, you only need to get the full path of your search directory. API calls are slow. Inside the loop you just combine strings.