Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
281 views
in Technique[技术] by (71.8m points)

c++ - Using an embedded .dll in an executable

Okay. So I know there's lots of questions about how to embed dlls inside exes, but my problem is rather different. (Specifically, I'm using the fmod library to play sounds in my program, and I'm embedding the fmod.dll, but that's beside the point.)

I am using Visual C++ 2010 Ultimate. I have successfully embedded the .dll inside the .exe. My resources.h file contains

#define IDR_DLL1  144

and my .rc file contains

IDR_DLL1  DLL  MOVEABLE PURE  "data\fmod.dll"

I have the following function in my code (that I totally stole from another stackoverflow question):

bool extractResource(const HINSTANCE hInstance, WORD resourceID, LPCTSTR szFilename)
{
bool bSuccess = false; 
try
{
    // Find and load the resource
    HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(resourceID), L"DLL");
    HGLOBAL hFileResource = LoadResource(hInstance, hResource);

    // 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(szFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwSize, NULL);            
    LPVOID lpAddress = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);            

    // Write the file
    CopyMemory(lpAddress, lpFile, dwSize);            

    // Un-map the file and close the handles
    UnmapViewOfFile(lpAddress);
    CloseHandle(hFileMap);
    CloseHandle(hFile);
    bSuccess = true;
}
catch(...)
{
    // Whatever
} 
return bSuccess;
}

and then, I call the following code first thing in my WinMain function:

int WINAPI WinMain(HINSTANCE h1, HINSTANCE h2, LPSTR l, int a)
{
    extractResource(h1, IDR_DLL1, L"fmod.dll");
    /* etc */
}

It works. It successfully extracts out the contents of the embedded fmod.dll, and saves it as a file in the same directory... only... when there already was an fmod.dll there beforehand. If fmod.dll was NOT already there, I just get a popup message that says

The program can't start because fmod.dll is missing from your computer. Try reinstalling the program to fix this problem.

...In other words, I can only overwrite an fmod.dll that was already there. For example, if I instead change my code to

extractResource(h1, IDR_DLL1, L"fmod2.dll");

it will write out the exact same file, with the exact same contents, titled fmod2.dll. I can at that point get rid of the original fmod.dll, and rename the newly created fmod2.dll to fmod.dll, and it will work.

   

So obviously, the issue is that it looks for the presence of an fmod.dll, BEFORE even hitting the entry point of my program. My program can't even execute any code before any fmod stuff is needed to actually be used. This seems... wildly unfair. What is the point of even being able to embed dlls then?

So then, my questions are

  1. Is it possible to use the .dll directly from inside the .exe, without unpacking it as a file? (My preferred method)

  2. If 1.) is not possible, then how can I at least modify my code to write out the file before its presence is checked for?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Well, the solution was surprisingly easy. I just followed DyP's suggestion on delay-loading the dll.

I just added one thing in my project properties, like so:

image

and that was it!

I love it when programming problems have easy solutions. :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...