Introduction
This article explains how to use plain text files such as *.XML and others inside the MS Visual Studio Resource Editor for your C++ applications. The benefits to do so are:
- You don't have to worry about external files such as XML files your application may use, if they become corrupted by a virus or an experimental user.
- Your external files are kept in one central location; inside your binary application file. You are not concerned over where the location of your external files are.
- During deployment, there is no concern over where to place your external files, like what the user's computer directory structure is and etc; again, they are included inside your EXE or DLL application.
Now let's take a look at some disadvantages:
- The size of your EXE/DLL file will increase in size to account for resource file(s) you added.
- If your resource file changes, you have to re-load your resource into the Resource Editor to make sure the changes are reflected, and then re-compile your EXE/DLL program.
- The more complex your resource file is, and how it is used in your application, will undoubtedly mean that your code to use the resource file will be complex, and difficult to code.
So as we can see, there are certain situations where this might not be the best solution for the goal at hand. Yet, this does supply a viable solution to other type of applications.
In our sample program, we have a standard XML template file where for any given application, we want to maybe replace a re-occurring substring of data with another. This goal can be accomplished in many ways such as using the XML technologies, string search and replace methods by using code loops and etc. However, we want to keep things as simple as possible and use the standard template library.
Using the standard template library allows our code to be small, compact and extremely portable to other solutions. In any case, the only un-portable code would be the loading and retrieving of the resource text file itself: which is the basis for this article.
Shall we begin?
We start inside Visual Studio, creating a new console application type project and inserting a custom resource into our Resource Editor as the pictures show below:


Once we have our resource file added, we start our code by including the files and declarations here:
#include "stdafx.h"
#include <windows.h>
#include <conio.h>
#include <io.h>
#include <sys/stat.h>
#include <string>
using namespace std;
Here is our main procedure and the source of the application:
int _tmain(int argc, _TCHAR* argv[])
{
if (argc <= 2 || argc > 3)
{
_tcprintf(_T("This Program's Expected Usage is:\n"
" %s PathDefault PathToWriteXmlFiles"), argv[0]);
return 1;
}
LPTSTR sArgv = argv[1];
LPTSTR sArgv2 = argv[2];
TCHAR sResName[5] = _T("#103");
TCHAR sRestype[13] = _T("TIMELISTINGS");
HRSRC hres = FindResource(NULL, sResName, sRestype);
if (hres == 0)
{
_tcprintf(_T("An Error Occurred.\n Could Not Locate Resource File."));
return 1;
}
HGLOBAL hbytes = LoadResource(NULL, hres);
LPVOID pdata = LockResource(hbytes);
LPBYTE sData = (LPBYTE)pdata;
LPTSTR sXml = (LPTSTR)sData;
size_t iArgLen = _tcslen(sArgv2);
size_t iLen = _tcslen(sXml);
string strXml = string(sXml);
LPTSTR sDefault = sArgv;
size_t iDefLen = _tcslen(sDefault);
size_t iPos = strXml.find(string(sDefault), 0);
size_t iSizeToWrite = (iDefLen > iArgLen ?
(iLen -(iDefLen - iArgLen) * 15) : iLen);
if (iPos > iLen || iPos < 0)
{
_tcprintf(_T("Could Not Find %s inside"
" the Xml Resource Structure"), argv[1]);
return 2;
}
strXml.replace(iPos ,iDefLen, sArgv2);
while (iPos < iLen )
{
iPos = strXml.find(string(sDefault), 0);
if (iPos > iLen)
break;
strXml.replace(iPos ,iDefLen, sArgv2);
}
LPTSTR sReplace = new TCHAR[_tcslen(sArgv2)];
_tcscpy(sReplace, sArgv2);
LPTSTR s9amFile = _tcsncat(sArgv2, _T("\\9AM.xml"),
iLen + 10);
int fh = _tcreat(s9amFile, _S_IWRITE );
if (fh == -1)
{
_tcprintf(_T("An Error Occurred.\n "
"9AM XML File Could Not Be Created."));
return 3;
}
int iBytesWritten = _write(fh, (LPVOID)strXml.c_str(),
iSizeToWrite);
if (iBytesWritten == 0)
{
_tcprintf(_T("An Error Occurred.\n 9AM XML"
" File Could Not Be Written To."));
_close(fh);
return 4;
}
_close(fh);
_tcscpy(sArgv2, sReplace);
LPTSTR s9pmFile = _tcsncat(sArgv2, _T("\\9PM.xml"),
iLen + 10);
fh = _tcreat(s9pmFile, _S_IWRITE );
if (fh == -1)
{
_tcprintf(_T("An Error Occurred.\n 9PM"
" XML File Could Not Be Created."));
return 3;
}
iBytesWritten = _write(fh, (LPVOID)strXml.c_str(),
iSizeToWrite);
if (iBytesWritten == 0)
{
_tcprintf(_T("An Error Occurred.\n "
"9PM XML File Could Not Be Written To."));
_close(fh);
return 4;
}
_close(fh);
_tcscpy(sArgv2,sReplace);
LPTSTR s3pmFile = _tcsncat(sArgv2, _T("\\3PM.xml"),
iLen + 10);
fh = _tcreat(s3pmFile, _S_IWRITE );
if (fh == -1)
{
_tcprintf(_T("An Error Occurred.\n 3PM"
" XML File Could Not Be Created."));
return 3;
}
iBytesWritten = _write(fh, (LPVOID)strXml.c_str(),
iSizeToWrite);
if (iBytesWritten == 0)
{
_tcprintf(_T("An Error Occurred.\n "
"3PM XML File Could Not Be Written To."));
_close(fh);
return 4;
}
_close(fh);
_tcprintf(_T("Program Completed Successfully."
"\n 3 Files were written to:\n%s\n%s\n%s\n"),
s9amFile, s3pmFile, s9pmFile);
return 0;
}
That's all folks for now.