I have an .ini file which is located inside the resource as an RCDATA.
I load it from the resource during runtime, and I am able to get it as a very long string.
I am interested of loading the .ini file (from the resource at runtime) and parse it as an .ini file using Boost or Win32 API but the question is how do I do it ?
It seems that it is possible of doing such thing using QT.
I have tried loading the resource file and assigning read_ini() the binary data/string file but it doesn't iterate over it afterwards.
Is it possible of doing such thing ?
Code snip:
HRSRC myResource = FindResource(NULL, MAKEINTRESOURCE(101), RT_RCDATA);
unsigned int myResourceSize = SizeofResource(NULL, myResource);
HGLOBAL myResourceData = LoadResource(NULL, myResource);
char* pMyBinaryData = (char*)LockResource(myResourceData);
char *text = (char*)malloc(myResourceSize + 1);
memcpy(text, pMyBinaryData, myResourceSize);
text[myResourceSize] = 0;//last char array is null
FreeResource(myResourceData);
The way I extract the text inside the .txt/.ini file.
I suppose you might be looking for
std::istringstream iss(the_large_string_value);
boost::property_tree::ptree pt;
boost::property_tree::read_ini(iss, pt);
Of course, you can read (really large) resources as a stream. Boost IOstreams has an array_source that can help there.
The simplest thing here would be
std::string the_large_resource_string_value(pMyBinaryData, myResourceSize);
Related
I'd like to get the name of an application on Windows.
Currently I'm using EnumProcesses() to enumerate all processes and receive a list of PIDs.
Then I'm looping through all PIDs, each iteration looks like this, when aProcess[i] is the current PID:
HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, aProcesses[i]);
std::string processName = get_process_name(proc);
My get_process_name(proc) function uses GetModuleFileNameEx to get the executable path and GetProcessImageFileName in order to retrieve the name of the executable file.
What I want to retrieve is basically the App Name, as it is displayed in the Windows Task Manager.
I've looked throughout Win32 API's documentation and could not find a clue on how to achieve this.
I've tried looking for other ways such as Windows Shell tasklist but it outputs different things, for example- Google Chrome:
Image Name: chrome.exe PID: 84 Session Name: Console
I'd really appreciate any thought on the matter, whether it be the Win32 API or some other way I can implement through C++ code.
You can do this with GetFileVersionInfoA and VerQueryValueA.
You just need to follow the example given in the VerQueryValueA document.
Here is my sample:
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
int main()
{
HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION , FALSE, 2140); //Modify pid to the pid of your application
if (!handle) return 0;
wchar_t pszFile[MAX_PATH] = L"";
DWORD len = MAX_PATH;
QueryFullProcessImageName(handle, 0, pszFile, &len);
UINT dwBytes, cbTranslate;
DWORD dwSize = GetFileVersionInfoSize(pszFile, (DWORD*)&dwBytes);
if (dwSize == 0) return 0;
LPVOID lpData = (LPVOID)malloc(dwSize);
ZeroMemory(lpData, dwSize);
if (GetFileVersionInfo(pszFile, 0, dwSize, lpData))
{
VerQueryValue(lpData,
L"\\VarFileInfo\\Translation",
(LPVOID*)&lpTranslate,
&cbTranslate);
wchar_t strSubBlock[MAX_PATH] = { 0 };
wchar_t* lpBuffer;
for (int i = 0; i < (cbTranslate / sizeof(struct LANGANDCODEPAGE)); i++)
{
StringCchPrintf(strSubBlock,50,
L"\\StringFileInfo\\%04x%04x\\FileDescription",
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage);
VerQueryValue(lpData,
strSubBlock,
(void**)&lpBuffer,
&dwBytes);
std::wcout << lpBuffer << std::endl;
}
}
if(lpData) free(lpData);
if (handle) CloseHandle(handle);
return 0;
}
And it works for me:
I think what you want are the "version" resources embedded in the PE file (the executables.)
You seem to be familiar with using Win32 API, so I'm just going to give you some hints.
You have to use LoadLibraryEx to load the EXE file (the Ex suffix is to enable passing the LOAD_LIBRARY_AS_DATAFILE flag,) and then call EnumResourceTypes (also see EnumResourceNames) to enumerate all the resource types/resources in the file, and find what you are looking for and then extract the data with LoadResource. The resource type you want is RT_VERSION.
I'm sure I'm omitting a lot of details (as per usual for Win32 programming,) and there might not be a need for enumeration at all; in which case you may want to call FindResource or FindResourceEx directly (if there is a fixed name for this particular resource.)
As further clarification, this gives you the date you see if you right-click on the EXE file (not the shortcut) in Windows Explorer and select "Properties", then go to the "Details" tab. If that information is indeed what you want (e.g. the "File description" field) then the above method should give you the data.
How can I open a file in UWP application?
My application will have additional files (e.g. Text file)
I want my program to be able to access this file. So how can I do it?
1.) Make sure that the file that you are trying to open is placed in Application local folder(Folder name "LocalState")
Use the below code to find the local folder path.
using namespace Windows::Storage;
using namespace Streams;
textBlock1->Text = ApplicationData::Current->LocalFolder->Path;
This will display local folder path in text block name textBlock1.
2.) To open the file name "Sample.txt"
using namespace Windows::Storage;
using namespace Streams;
String^ localfolder = ApplicationData::Current->LocalFolder->Path;
std::wstring basePath(localfolder->Data());
std::wstring fileName(L"\\Sample.txt");
basePath = basePath + fileName;
const wchar_t* fullpath = basePath.c_str();
size_t size = wcslen(fullpath) * 2 + 2;
char * StartPoint = new char[size];
size_t c_size;
wcstombs_s(&c_size, StartPoint, size, fullpath, size);
FILE *fp_testFile = NULL;
errno_t err;
err = fopen_s(&fp_testFile, StartPoint, "rb");
if (err == 0)
{
OutputDebugStringW(L"opened");
}
else
{
OutputDebugStringW(L"open failed");
}
The string conversion part is really confusing for me.
I also don't know how not to manually place the file in the local folder.
I tried added the file under Solution explorer -> Assets. But the file is not included to the local folder after deployed
I have a win32 console application in C++, Visual Studio 2012. I cannot get the config parameter from the ini file. I tried different possibilities with file path,like placing the .ini file in source folder, write the full path to is, placing in the folder with generated .exe file. The output on the console after executing of the .exe file is 0 or (null) for string in every case. What I am doing wrong? How can I read the parameters?
v1:
LPCTSTR path = L".\\config.ini";
TCHAR protocolChar[32];
int port = GetPrivateProfileString(_T("PORT"), _T("SETTINGS"), _T(""), protocolChar, 32, path);
printf("***%d***\n", port);
v2:
int port = GetPrivateProfileInt(_T("PORT"), _T("SETTINGS"), 0, _T("config.ini"));
config.ini contains:
[SETTINGS]
USER_NUM_MAX = 256 ; Maximum number of users
PORT = 8080;
Oups, under Windows hitting a ini file in not that easy. In both tries (v1 and v2), you look for the file in current directory and then in Windows directory but not in the directory where the executable file is.
The easy way is to put all ini files under Windows directory. If you find cleaner to have the ini file along with the exe one, you have some more work to do :
find the executable file full path
replace the exe end with ini
use that full path to get access to your private ini file
To get the name of the executable file, simply use GetModuleFileName with a NULL HMODULE :
LPCTSTR getExecPath() {
DWORD len = 64;
for (;;) {
LPTSTR fileName = new TCHAR[len];
if (len == ::GetModuleFileName(NULL, fileName, len)) {
delete fileName;
len *= 2;
}
else {
return fileName;
}
}
}
or if you prefere to directly get the ini file name :
LPCTSTR getIniName() {
DWORD len = 4;
for (;;) {
LPTSTR fileName = new TCHAR[len];
if (len == ::GetModuleFileName(NULL, fileName, len)) {
delete fileName;
len *= 2;
}
else {
::lstrcpy(fileName + lstrlen(fileName) - 3, "ini");
return fileName;
}
}
}
and to not forget to delete the file name when done since it is allocated with new ...
Edit per comment :
For reference, the windows directory may depend on windows version. But it can always be retrieved by the API function GetWindowsDirectory. Extract from the reference page :
UINT WINAPI GetWindowsDirectory(
_Out_ LPTSTR lpBuffer,
_In_ UINT uSize
);
Parameters
lpBuffer [out] A pointer to a buffer that receives the path. This path does not end with a backslash unless the Windows directory is the root directory. For example, if the Windows directory is named Windows on drive C, the path of the Windows directory retrieved by this function is C:\Windows. If the system was installed in the root directory of drive C, the path retrieved is C:.
uSize [in] The maximum size of the buffer specified by the lpBuffer parameter, in TCHARs. This value should be set to MAX_PATH.
Return value
If the function succeeds, the return value is the length of the string copied to the buffer, in TCHARs, not including the terminating null character.
If the length is greater than the size of the buffer, the return value is the size of the buffer required to hold the path.
If the function fails, the return value is zero. To get extended error information, call GetLastError. *
I faced this problem when I updated from VS2010 to VS2012.
On VS 2010 I simply called the function with the file name of the .ini-file as argument for lpFileName (see MSDN Documentation).
This was not working for VS 2012 any more, so I changed to go for the complete path like this:
char directoryPath[MAX_PATH];
char readParameter[MAX_STR_LEN];
GetCurrentDirectory( directoryPath, MAX_PATH );
string directoryPathAsString(directoryPath);
directoryPathAsString = directoryPathAsString + "\\" + filename;
GetPrivateProfileString("section","parameter","0",readParameter,MAX_STR_LEN, directoryPathAsString.c_str());
I would like to read from file in resource file. That's ok like so:
char LineBuffer[255];
HRSRC hRes = FindResource(0, MAKEINTRESOURCE(ID_TEXT_FILE), "0");
if(hRes != NULL)
{
HGLOBAL hData = LoadResource(0, hRes);
if(hData != NULL)
{
sprintf(LineBuffer, "%s", LockResource(hData));
}
}
But I want to change the text in the txt file stored in resource. I have read something about it and everyone uses BeginUpdateResource(); UpdateResource(); EndUpdateResource(); but I don't get it. Any help would be appreciated :) A code snippet would be awesome. Thanks in advance ;-)
A running process cannot alter its own resources. You have to use a separate application to update the resources of the main application while it is not running. Only then can you use (Begin/End)UpdateResource().
i am working on a win32 app. i am currently using the text file which has tab delimited data as a source. i want to embed this as a resource so that i need not worry about shipping this file along with .exe file.
can anyone tell me how to do it?
Windows binary can have resources embedded in them. Most resources are of predetermined type (e.g. a menu, an icon or a bitmap) but you can also embed arbitrary binary data (e.g. a text file). The proper syntax is hard to figure out just from reading msdn docs.
This snippet shows how to embed a binary resource from a file.
First you need to define a resource identifier in a header file (e.g. resource.h) that will be used by both C compiler and resource compiler:
#define MY_RESOURCE 300
Then you need to add to your resource file (e.g. resource.rc):
MY_RESOURCE RCDATA "file-with-data.txt"
And finally, this is how you can get to this data:
void WorkOnResource(void)
{
HGLOBAL res_handle = NULL;
HRSRC res;
char * res_data;
DWORD res_size;
// NOTE: providing g_hInstance is important, NULL might not work
res = FindResource(g_hInstance, MAKEINTRESOURCE(MY_RESOURCE), RT_RCDATA);
if (!res)
return;
res_handle = LoadResource(NULL, res);
if (!res_handle)
return;
res_data = (char*)LockResource(res_handle);
res_size = SizeofResource(NULL, res);
/* you can now use the resource data */
}
Define the resource ID, add this to the .rc file:
ID_CUSTOM1 ANYTHINGGOESHERE "filename.txt"
Read it at runtime with code like this:
HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(ID_CUSTOM1), L"ANYTHINGGOESHERE");
HGLOBAL hMem = LoadResource(hInst, hRes);
DWORD size = SizeofResource(hInst, hRes);
char* resText = (char*)LockResource(hMem);
char* text = (char*)malloc(size + 1);
memcpy(text, resText, size);
text[size] = 0;
FreeResource(hMem);
// use text...
why not use a header file and put all your data in a static array. That way you don't have to parse a text file or worry about deployment
If you are looking for the "correct" way to do this then I would suggest adding your text file as a resource (as a string table or binary) and using LoadString or FindResource to access it.
in Visual Studio, you can add text as a resource just like any other resource.
In the resource.rc file of your project:
IDR_MYRESOURCE MYCUSTOMRESOURCETYPE "path_to_file.txt"
in the resource.h file:
#define IDR_MYRESOURCE 104
(or you can add these through the resource editor by selecting "Add Resource", then "New")
To load the resource in code:
HRSRC hRes = FindResource( 0, "#104", "MYCUSTOMRESOURCETYPE" );
HGLOBAL hData = LoadResource( 0, hRes );
LPVOID data = LockResource( hData );
Now data points to the text, and can be casted to string.
edit
hmm looks like everyone was posting the same answer at the same time ;P