Embedding DLL and binary files in the Win32 Executable

By Akbar

Embedding DLL and binary files in the Executable applications Though for most of the cases, it’s recommended keep the resources and other libraries separate from the main executable. This makes the main application executable size small, and thus that application will take less memory on load and will load/unload the external resources as required. Yet sometimes, it makes sense to append the external files as part of executable. A popular example of this is self extracting installer. The basic technique behind this whole process is simple. Here is what needs to be done:

Write a resource script file which provides path to the external files you want to append in the final resource object.

  • Use the Resource Compiler to build a RES file from the above script.
  • Bind the RES file with executable.
  • Call the APIs to extract and load the resources from the executable memory space at run-time.
  • First one to add a Resource Script file in the executable project. Here is a sample code to define the binary resource in
  • the resource script file
IDR_TBEHK_DEBUG BINARY MOVEABLE PURE "..debugTaskbarExtHk.dll"

Please note that “IDR_TBEHK_DEBUG” is user defined constant and must be declared before this line. Here is how I have defined this at top:

#define IDR_TBEHK_DEBUG130

There is catch here. Some of the files are conditional and thus we may need some checks on which version of file to include. One way of doing this is to use the standard C++ compiler directives (these syntax is almost same for Resource Compiler):

#ifdef _DEBUG
IDR_TBEHK_DEBUG BINARY MOVEABLE PURE "..debugTaskbarExtHk.dll"
#else// _DEBUG
IDR_TBEHK_RELEASE BINARY MOVEABLE PURE "..releaseTaskbarExtHk.dll"
#endif

But wait, we also need to define the value for the _DEBUG symbol (the one defined for C++ project will not work here, as this file is read by resource compiler and is a totally different context). In Visual Studio, you can easily define these Resource preprocessor directives in the project properties. Simply add “_DEBUG” for the DEBUG configuration and it will add the conditional embedding of the correct version.

Another simple option for including binary libraries is to change the project settings is to set a single output folder for both Debug and Release configurations and then just include that single file. Once the RC file is ready, it can be compiled to RES file using the Resource Compiler. Here is a sample command line for this: rc.exe /fo”Release/TaskbarExt.res” “.TaskbarExt.rc” If you are using Visual Studio, then it will automatically call this for you and will build the RES file and will also bind it with executable.

The next big part is finding and loading the resource from the executable. Here is a sample code to do this:

bool ExtractResource(const HINSTANCE hInstance, WORD resourceID, LPCTSTR szOutputFilename)
{
	bool bSuccess = false;
	try
	{
		// First find and load the required resource
		HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(resourceID), _T("BINARY"));
		HGLOBAL hFileResource = LoadResource(hInstance, hResource);
 
		// Now open and map this to a disk file
		LPVOID lpFile = LockResource(hFileResource);
		DWORD dwSize = SizeofResource(hInstance, hResource);
 
		// Open the file and filemap
		HANDLE hFile = CreateFile(szOutputFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		HANDLE hFilemap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwSize, NULL); LPVOID lpBaseAddress = MapViewOfFile(hFilemap, FILE_MAP_WRITE, 0, 0, 0);
 
		// Write the fileCopyMemory(lpBaseAddress, lpFile, dwSize);
 
		// Unmap the file and close the handles
 
		UnmapViewOfFile(lpBaseAddress);
		CloseHandle(hFilemap);
		CloseHandle(hFile);
	}
	catch(...)
	{
		// Ignore all type of errors
	}
return bSuccess;
}

Once you are done with resource, you can remove it by calling the DeleteFile API.
Simple is that! Isn’t it?

Tags: , , ,