Embedding DLL and binary files in the Win32 Executable

By Akbar 3 min read 18 comments

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?

Feedback & Comments

18 Responses

  1. serup

    Howto remove dll after use from inside your program which initially extracted the dll file :

    ***
    //+ REMOVE THE DLL AFTER THE PROGRAM ENDS (DLL WILL NOT BE POSSIBLE TO REMOVE BEFORE IT HAS BEEN UNLOADED, THUS THIS BULKY SOLUTION)
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );

    // Start the child process.
    if( !CreateProcess( NULL, // No module name (use command line).
    TEXT(“remove_dll.bat”), // Command line.
    NULL, // Process handle not inheritable.
    NULL, // Thread handle not inheritable.
    FALSE, // Set handle inheritance to FALSE.
    0, // No creation flags.
    NULL, // Use parent’s environment block.
    NULL, // Use parent’s starting directory.
    &si, // Pointer to STARTUPINFO structure.
    &pi ) // Pointer to PROCESS_INFORMATION structure.
    )
    {
    printf( “CreateProcess failed (%d).n”, GetLastError() );
    return;
    }
    //-

    ***
    The bat file looks like this
    DEL
    DEL

  2. serup

    How is it possible for me to unload the dll after my program has used it ?

    – First I extract it
    – Then I use it.
    – Then my program is shutting down and trying to delete my extracted dll file, however it is somehow still in used, hence not possible to delete

    How is it possible for me to unload the dll first ?

  3. serup

    Even if I add the GENERIC_EXECUTE in CreateFile, the resulting file when extracted is not the same as the original one being embedded ??
    thus the dll will not work !!
    Code is in a MFC project, otherwise exactly the same as described here – Any suggestions to solving this ?

  4. syedgakbar

    Dave,

    Sorry for the late reply. I was busy with something else. Regarindg your problem, please make sure that the line you added in the resource file has correct double quotes character (if you copied these directly from the web-page, they might not be double quotes characters (due to encoding difference). Basically, try this:

    IDR_PKEY_DLL BINARY MOVEABLE PURE “resProject.dll”

    Hope this helps.

  5. Hi,

    Just tried this, but windres doesn’t like it:

    compiling: resource.rc
    windres.exe: resource.rc:17: syntax error

    In my header, I have:

    #define IDR_PKEY_DLL 102

    And in the resource file I have:

    IDR_PKEY_DLL BINARY MOVEABLE PURE ”resProject.dll”

    Any suggestions? – I’m guessing it wants a type? (CURSOR, BITMAP etc?)

  6. Matt Blackler

    Thanks for this, you’ve saved me hours of frustration. I’ll just add that if you embed the resource using visual studio, _T(“BINARY”) in the above code should be replaced with _T(“resourceType”) where resourceType is the name of the folder-like thing in the resource editor created when you add the resource.

Leave a Reply