GetModuleFileName fill an adress and not the executable name [duplicate] - c++

This question already has answers here:
How I can print the wchar_t values to console?
(8 answers)
cout a string gets the address instead of value [duplicate]
(1 answer)
how to print tchar in c++
(2 answers)
Closed 2 years ago.
I want to get the current executable application name of my windows console application.
According to this answer, the solution should be to use GetModuleFileNameA function.
The problem is the function doesn't fill the name of the executable but fill the address :
#include <iostream>
#include <tchar.h>
#include <windows.h>
int main()
{
TCHAR szFileName[MAX_PATH];
GetModuleFileName(NULL, szFileName, MAX_PATH);
std::cout << "My executable name is : " << szFileName << std::endl;
system("pause");
}
Output : My executable name is : 0077F9DC
Some one could fix my code ?

This is the complete code of the extraction current executable name :
#include <iostream>
#include <string>
#include <windows.h>
int main()
{
wchar_t szFileName[MAX_PATH];
// don't forget to check return values when calling winapi functions
GetModuleFileNameW(NULL, szFileName, MAX_PATH);
std::wstring filePath(szFileName);
std::size_t indexLastCharSlash = filePath.find_last_of(L"/\\");
std::wstring fileName = filePath.substr(indexLastCharSlash + 1);
std::wcout << fileName << std::endl;
system("pause");
}

Related

Problem joining char* to filesystem::path.filename() or char[260]

I Know similar questions have been asked before but none of them Helped in my case.
Basically I want dstPath = %AppData% + "CURRENT EXE NAME"
but problem is with different string types and string concantation
SIMPLIFIED CODE :-
#include <stdio.h>
#include <string>
#include <filesystem>
#include <Shlwapi.h>
#include <Windows.h>
using namespace std;
int main()
{
TCHAR selfPath[MAX_PATH];
TCHAR dstPath[MAX_PATH];
if (GetModuleFileName(NULL, selfPath, MAX_PATH) == 0) // Getting exe File Location
printf("Error : %ul\n", GetLastError());
filesystem::path p(selfPath);
dstPath = strcat(getenv("APPDATA"), p.filename().string().c_str()); // Here Comes The Error
printf("Src : %s\n", selfPath);
printf("Dst : %s\n", dstPath);
return 0;
}
COMPILER COMMAND :-
g++ -Os -s -o ./builds/gcc-rat-x64.exe ./source/rat.cpp -std=c++17 -m64 -lshlwapi
COMPILER ERROR :-
error: incompatible types in assignment of 'char*' to 'TCHAR [260]' {aka 'char [260]'}
80 | dstPath = strcat(getenv("APPDATA"), p.filename().string().c_str());
You cannot assign to arrays. You should use strcpy() to copy C-style strings.
strcpy(dstPath, getenv("APPDATA"));
strcat(dstPath, p.filename().string().c_str());
Or the concatination can be done in one line via snprintf():
snprintf(dstPath, sizeof(dstPath), "%s%s", getenv("APPDATA"), p.filename().string().c_str());
Finally, TCHAR and GetModuleFileName can refer to UNICODE version of the API, according to the compilation option. Using ANSI version (char and GetModuleFileNameA) explicitly is safer to work with std::string and other APIs that require strings consists of char.
You are trying to use strcat to concatenate two strings and store the result in another one, but it does not work that way. The call strcat (str1, str2) adds the content of str2 at the end of str1. It also returns a pointer to str1 but I don't normally use it.
What you are trying to do should be done in three steps:
Make sure that dstPath contains an empty string
Concatenate to dstPath the value of the environment variable APPDATA
Concatenate to dstPath the value of filename
Something like this:
dstPath[0] = '\0';
strcat(dstPath, getenv("APPDATA"));
strcat(dstPath, p.filename().string().c_str());
You should also add checks not to overflow dstPath...
First off, you are mixing TCHAR and char APIs in a way you should not be. You really should not be using TCHAR at all in modern code. But, if you are going to use TCHAR, then at least use TCHAR- based functions/macros, like _tprintf() instead of printf(), _tcscat() instead of strcat(), etc.
The compiler error is because you are trying to assign the char* pointer returned by strcat() to your dstPath TCHAR[] array. You can't assign a pointer to an array like that. You should strcpy() the result of getenv() into dstPath first, and then strcat() your filename onto the end of it, eg:
#include <string>
#include <filesystem>
#include <Windows.h>
#include <Shlwapi.h>
#include <stdio.h>
#include <tchar.h>
TCHAR* _tgetenv(const TCHAR *varname)
{
#ifdef _UNICODE
return _wgetenv(varname);
#else
return getenv(varname);
#endif
}
std::basic_string<TCHAR> path2TStr(const std::filesystem::path &p)
{
#ifdef _UNICODE
return p.wstring();
#else
return p.string();
#endif
}
int main()
{
TCHAR selfPath[MAX_PATH];
TCHAR dstPath[MAX_PATH];
if (GetModuleFileName(NULL, selfPath, MAX_PATH) == 0) // Getting exe File Location
{
printf("Error : %ul\n", GetLastError());
return 0;
}
std::filesystem::path p(selfPath);
_tcscpy(dstPath, _tgetenv(_T("APPDATA")));
_tcscat(dstPath, path2TStr(p.filename()).c_str());
_tprintf(_T("Src : %s\n"), selfPath);
_tprintf(_T("Dst : %s\n"), dstPath);
return 0;
}
However, you really should be using SHGetFolderPath(CSIDL_APPDATA) or SHGetKnownFolderPath(FOLDERID_RoamingAppData) instead of using getenv("APPDATA").
And since you are using the <filesystem> library anyway, you really should just use std::filesystem::path for all of your path handling. It has operator/= and operator/ to concatenate path segments, and an operator<< for printing paths to a std::ostream, like std::cout. Don't use strcat() for concatenating path segments, it won't handle directory separators correctly, at least.
Try this instead:
#include <iostream>
#include <string>
#include <filesystem>
#include <stdexcept>
#include <Windows.h>
#include <Shlobj.h>
std::filesystem::path getSelfPath()
{
WCHAR wPath[MAX_PATH] = {};
if (!GetModuleFileNameW(NULL, wPath, MAX_PATH)) // Getting exe File Location
{
DWORD err = GetLastError();
throw std::runtime_error("Error : " << std::to_string(err));
}
return wPath;
}
std::filesystem::path getAppDataPath()
{
WCHAR wPath[MAX_PATH] = {};
HRESULT hRes = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wPath); // Getting APPDATA Folder Location
if (hRes != S_OK)
throw std::runtime_error("Error : " << std::to_string(hRes));
return wPath;
}
int main()
{
try
{
auto selfPath = getSelfPath();
auto dstPath = getAppDataPath() / selfPath.filename();
std::cout << "Src : " << selfPath << "\n";
std::cout << "Dst : " << dstPath << "\n";
}
catch (const std::exception &e)
{
std::cerr << e.what() << "\n";
}
return 0;
}

How to get a registry read function to work properly? (c++)

When I compile and run the following code snippet (in visual studio 2019),
it runs but returns an incorrect value of
Key Value: 000000D1E14FF920 and actual bytes read was: 12
instead of
Key Value: 18363 and actual bytes read was: 6
here is the code
#include <Windows.h>
#include <iostream>
#include <string>
#include <tchar.h>
wchar_t value[255];
DWORD BufferSize = sizeof(value);
RegGetValue(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\"), _T("CurrentBuildNumber"), RRF_RT_ANY, NULL, (PVOID)&value, &BufferSize);
std::cout << "Key Value: " << value << " and actual bytes read was: " << BufferSize << std::endl;
I tried multiple methords of fixing this problem but I couldnt get it to work properly with visual studio (probably because it uses unicode)
You are mixing char and TCHAR APIs. It is clear that RegGetValue() is returning a Unicode wide string, because 12 bytes is correct for a 6-character null-terminated wchar_t string. So TCHAR is mapping to wchar_t in your build, and thus RegGetValue() is calling RegGetValueW(). You are trying to print out that wide string using std::cout, which does not support wchar_t strings, so you are actually calling the void* overload of std::basic_osteam::operator<<. That is why you are seeing a memory address being printed out.
To deal with TCHAR correctly, try this instead:
#include <Windows.h>
#include <iostream>
#include <string>
#include <tchar.h>
#ifdef UNICODE
#define tcout std::wcout
#else
#define tcout std::cout
#endif
TCHAR value[255] = {};
DWORD BufferSize = sizeof(value);
RegGetValue(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\"), _T("CurrentBuildNumber"), RRF_RT_REG_SZ, NULL, &value, &BufferSize);
tcout << _T("Key Value: ") << value << _T(" and actual bytes read was: ") << (BufferSize / sizeof(TCHAR)) << std::endl;
However, you really should forget that TCHAR exists, it has no place in modern coding anymore. Just go full Unicode only:
#include <Windows.h>
#include <iostream>
#include <string>
WCHAR value[255] = {}
DWORD BufferSize = sizeof(value);
RegGetValueW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\", L"CurrentBuildNumber", RRF_RT_REG_SZ, NULL, &value, &BufferSize);
std::wcout << L"Key Value: " << value << L" and actual bytes read was: " << (BufferSize / sizeof(WCHAR)) << std::endl;

Get exe name that is currently running (Not the path) [duplicate]

This question already has answers here:
Get path of executable
(25 answers)
Get a file name from a path
(24 answers)
Closed 2 years ago.
hey so i wanted to get name of the exe that is currently running
here is what ive tried doing
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
char filename[ MAX_PATH ];
DWORD size = GetModuleFileNameA( NULL, filename);
if (size)
cout << "EXE file name is: " << filename << "\n";
else
cout << "Could not fine EXE file name.\n";
return 0;
}
but it gets the path of the exe too but i only need the exe name any help?
The first command line argument is the name of the current program
#include <iostream>
#include <string>
#include <windows.h>
#include <algorithm>
int main(int argc, char** argv)
{
if (argc > 0)
std::cout << argv[0] << std::endl;
else {
//some other method has to be used, use OP's suggestion
char filename[ MAX_PATH ];
DWORD size = GetModuleFileNameA( NULL, filename, MAX_PATH);
if (!size) {
std::cout << "Could not fine EXE file name.\n";
return -1;
}
//Remove everything before the last "\"
std::string name = filename;
auto it = std::find(name.rbegin(), name.rend(), '\\'); //escape the escape character
if (it != name.rend()) {
name.erase(name.begin(), it.base());
}
std::cout << filename << std::endl;
}
}

How to pass variable to windows.h function text()?

First off, I googled the hell out of this then searched the forums. In my ignorance of how the TEXT() function operates I cannot find an efficient way to search for an answer.
I writing a piece of code to search for a file that relies on inputting the directory you want to search. However, when I pass anything but a literal value to the function, like displayContent(_TEXT("c:\")), the software does not execute properly. It does not search for anything. Inserting breakpoints doesn't tell much, as the software closes anyways.
I would like to pass a variable to the the displayContent function by placing TEXT(variable) inside its argument like displayContent(_TEXT(*ptrDir)) but that is not compiling. Furthermore, when I simply place ptrDir inside of the argument of displayContent the software compiles but does not execute properly, as it asks for the directory to search but does not actually search it.
What's happening here? There has to be a way to pass a variable to displayContent that includes a string that's recieved from the user.
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include "Strsafe.h"
#include <string>
using namespace std;
typedef wchar_t WCHAR;
#define CONST const
typedef CONST WCHAR* LPCWSTR;
int displayContent(LPCWSTR lpszPath, int level = 0) {
wcout << lpszPath << endl;
getchar();
getchar();
WIN32_FIND_DATA ptrFileData;
HANDLE hFile = NULL;
BOOL bGetNext = TRUE;
wchar_t lpszNewPath[MAX_PATH];
if (lstrlen(lpszPath) > MAX_PATH)
return -1;
StringCchCopy(lpszNewPath, MAX_PATH, lpszPath);
StringCchCat(lpszNewPath, MAX_PATH, _TEXT("*.*"));
hFile = FindFirstFile(lpszNewPath, &ptrFileData);
while (bGetNext)
{
for (int i = 0; i < level; i++)
wcout << "-";
if (ptrFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY
&& lstrlen(ptrFileData.cFileName) > 2)
{
wchar_t lpszFirstTimePath[MAX_PATH];
StringCchCopy(lpszFirstTimePath, MAX_PATH, lpszPath);
StringCchCat(lpszFirstTimePath, MAX_PATH, ptrFileData.cFileName);
StringCchCat(lpszFirstTimePath, MAX_PATH, _TEXT("\\"));
wcout << ">" << ptrFileData.cFileName << endl;
displayContent(lpszFirstTimePath, level + 2);
}
else
{
wcout << ">" << ptrFileData.cFileName << endl;
}
bGetNext = FindNextFile(hFile, &ptrFileData);
}
FindClose(hFile);
return 0;
}
int main(int argc, char* argv[])
{
WCHAR directory;
LPCWSTR ptrDir;
ptrDir = &directory;
cout << "Enter directory you wish to search: " << endl;
//cin >> directory;
directory = 'c:\\' ;
ptrDir = &directory;
displayContent(_TEXT(*ptrDir));
getchar();
getchar();
return 0;
}
The _TEXT (and equivalently, _T) macro is strictly for literals (string literals or character literals). It expands to L for a Unicode build, and to nothing for a narrow-character build. So, for a string like (say) "hello", you'll get L"hello" for a Unicode build and "hello" for a narrow-character build. This gives you a wide literal in a Unicode build and a narrow literal otherwise.
If you have a string in a variable, you can convert between wide and narrow characters with the MultiByteToWideChar and WideCharToMultibyte functions.
In this case, doing a conversion on the contents of a variable isn't really needed though. After eliminating some unnecessary complexity, and using a few standard library types where they make sense, I end up with code something like this:
#include <iostream>
#include <tchar.h>
#include <string>
#define UNICODE
#include <windows.h>
int displayContent(std::wstring const &path, int level = 0) {
WIN32_FIND_DATA FileData;
if (path.length() > MAX_PATH)
return -1;
std::wstring new_path = path + L"\\*.*";
HANDLE hFile = FindFirstFile(new_path.c_str(), &FileData);
do {
if ((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (FileData.cFileName[0] == L'.'))
continue;
std::wcout << std::wstring(level, L'-') << L">" << FileData.cFileName << L"\n";
if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
displayContent(path + L"\\" + FileData.cFileName, level + 2);
} while (FindNextFile(hFile, &FileData));
FindClose(hFile);
return 0;
}
int main(int argc, char* argv[]) {
wchar_t current_dir[MAX_PATH];
GetCurrentDirectory(sizeof(current_dir), current_dir);
displayContent(current_dir);
return 0;
}
[Note: I've also changed it to start from the current directory instead of always starting at the root of the C drive, but if you want to change it back, that's pretty trivial--in fact, it simplifies the code a bit more).

Full path of executable file in Windows, c++ [duplicate]

This question already has answers here:
Wide character output result [closed]
(2 answers)
Closed 8 years ago.
I just want to get full path of my executable file written on console, but the variable path just stores numbers how can i convert it to string (I know this code only outputs memory location of path)?
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
int main() {
WCHAR path[MAX_PATH];
GetModuleFileName(NULL, path, 500);
cout << "File path is: " << path << endl;
}
There are a couple of problems with your code:
You're passing the wrong size parameter to GetModuleFilename - the buffer size is supposed to be the size in TCHARs, which would be MAX_PATH in your case, not 500. That's a buffer overflow waiting to happen as 500 > MAX_PATH
You're using the narrow stream for your output, that can't print a wide string so you're seeing the address instead. To print wide characters, you need to use std::wcout instead.
As already noted in the comments, you may want to use wcout to print a WCHAR string.
You may want to consider a function like this to wrap the GetModuleFileName() call in a convenient C++ way:
#include <stdexcept> // For std::runtime_error
#include <string> // For std::wstring
#include <Windows.h> // For Win32 API
// Represents an error in a call to a Win32 API.
class win32_error : public std::runtime_error
{
public:
win32_error(const char * msg, DWORD error)
: std::runtime_error(msg)
, _error(error)
{ }
DWORD error() const
{
return _error;
}
private:
DWORD _error;
};
// Returns the full path of current EXE
std::wstring GetPathOfExe()
{
// Get filename with full path for current process EXE
wchar_t filename[MAX_PATH];
DWORD result = ::GetModuleFileName(
nullptr, // retrieve path of current process .EXE
filename,
_countof(filename)
);
if (result == 0)
{
// Error
const DWORD error = ::GetLastError();
throw win32_error("Error in getting module filename.",
error);
}
return filename;
}
Note that if you want the size in WCHARs of a raw string buffer, you may want to use _countof().
wchar are 16bit and you are using cout and that output stream expect 8bit char that's why you get weird number on the output
when you have to use wchar use wcout and take care of the kind of string you use!
#include <iostream>
#include <string>
#include <windows.h>
std::wstring app_path() {
std::wstring path;
path.resize(MAX_PATH, 0);
auto path_size(GetModuleFileName(nullptr, &path.front(), MAX_PATH));
path.resize(path_size);
return path;
}
int main() {
auto path(app_path());
std::wcout << L"File path is: " << path << std::endl;
}
Try this one!