Change text file on runtime in resource.rc winapi c++ - c++

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().

Related

C++ Win32 - Getting App Name using PID and Executable Path

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.

Parse .ini file from resource during runtime using C++/boost

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

MFC file creation not working properly with pugixml

I'm trying to create an xml file using pugixml. The code is;
//Open the save as diolog
TCHAR szFilters[]= _T("Files (*.abc)|*.abc|All Files (*.*)|*.*||");
// Create an SaveAs dialog; the default file name extension is ".abc".
CFileDialog fileDlg(FALSE, _T("abc"), NULL,
OFN_OVERWRITEPROMPT |OFN_CREATEPROMPT| OFN_PATHMUSTEXIST, szFilters);
// Display the file dialog.
CString pathName;
CString fileName;
if(fileDlg.DoModal() == IDOK)
{
pathName = fileDlg.GetPathName();
fileName = fileDlg.GetFileName();
::CreateFile(pathName,GENERIC_WRITE,0,NULL,CREATE_NEW, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
} //File is created in explorer
else
return;
//[code_modify_add
// add node with some name
pugi::xml_document xmlDoc;
pugi::xml_parse_result result = xmlDoc.load_file(fileName);
The problem is result always gives out a 'file_not_found' status, but I can see that the file is created in windows explorer. When I try to select the same file during the execution of the program it still returns 'file_not_found'.
However if I close the program and run again and then select the file, result returns true.
I noticed that while the program is executing I cannot open the newly created file, but when the program is closed I can open it.
What could be the matter with it?
Thanks.
You are creating a file and leaving it open write only with a share mode of zero (meaning it can not be shared) and throwing away its handle and then trying to reopen the file for reading with the xml parser.
You probably want to CloseHandle() on the return value for ::CreateFile()
HANDLE hFile = ::CreateFile(pathName,GENERIC_WRITE,0,NULL,CREATE_NEW, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
if (hFile == INVALID_HANDLE_VALUE) {
// Call GetLastError() to figure out why the file creation failed.
}
else
{
CloseHandle(hFile);
}

Trying to make an XML reader work in C ++

I am trying to read some XML code from a website, and am having a bit of trouble figuring out where my errors are. Using the code from this extremely useful post, I am trying to read a file that I have saved to my desktop ("H:\MyName\Desktop\secLendingXML.cfm.xml"). The code is below:
#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#import <msxml6.dll> rename_namespace(_T("MSXML"))
int main(/*int argc, char* argv[]*/)
{
HRESULT hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
try
{
MSXML::IXMLDOMDocument2Ptr xmlDoc;
hr = xmlDoc.CreateInstance(__uuidof(MSXML::DOMDocument60), NULL, CLSCTX_INPROC_SERVER);
// TODO: if (FAILED(hr))...
if (xmlDoc->load(_T("H:\MyName\Desktop\secLendingXML.cfm.xml")) != VARIANT_TRUE)
{
printf("Unable to load input.xml\n");
}
else
{
printf("XML was successfully loaded\n");
xmlDoc->setProperty("SelectionLanguage", "XPath");
MSXML::IXMLDOMNodeListPtr wheels = xmlDoc->selectNodes("/Car/Wheels/*");
printf("Car has %u wheels\n", wheels->Getlength());
MSXML::IXMLDOMNodePtr node;
node = xmlDoc->createNode(MSXML::NODE_ELEMENT, _T("Engine"), _T(""));
node->text = _T("Engine 1.0");
xmlDoc->documentElement->appendChild(node);
hr = xmlDoc->save(_T("output.xml"));
if (SUCCEEDED(hr))
printf("output.xml successfully saved\n");
}
}
catch (_com_error &e)
{
printf("ERROR: %ws\n", e.ErrorMessage());
}
CoUninitialize();
}
system("PAUSE");
return 0;
}
The message "Unable to load input.xml" always shows, so I know I'm not having an error, but that the code is unable to load my XML file.
Do I need to save the XML file in a different location? Is the ".cfm" before the ".xml" screwing with the reading process?
To give an idea of my intended direction, I want to be able to load the XML file from the New York Fed website and read it into some sort of data file where I can automate the data retrieving process. That way, whenever the website is updated, I will automatically be notified, and it will be reflected by the change in the data file that I will have saved somewhere on my computer. If anyone also wants to help with how I go about that part - poll intervals, tracking website changes, etc. - that would also be appreciated.
Thank you for any and all help.
Do you need to escape the backslashes in your path string? e.g.
xmlDoc->load(_T("H:\\MyName\\Desktop\\secLendingXML.cfm.xml")

how to use a resource file (txt - tab delimited) as a data source for win32 application

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