How to build a DLL at runtime? - c++

Problem Description
I have an application that loads a dll at runtime. I want to allow a user to change code in that dll while the app is running. When the user clicks the "compile" button in the app it would free all the data from the dll. After freeing up the dll the app would then rebuild the dll. Essentially acting as a
Run time compiled program.
Ideal Implementation
void ReCompile()
{
//hDLL contains dll that was already loaded.
FreeLibrary(hDLL);
//code to rebuild MyDll.DLL would go here.
LPCWSTR dll = L"MyDll.dll";
hDLL = LoadLibrary(dll);
}
This currently works i just need to know how to rebuild the dll through code so it feels much more smooth and intuitive.
Current Implementation
void Free()
{
FreeLibrary(hDLL);
}
//I go into my other visual studio that's running and press the build button myself.
void ReloadDll()
{
LPCWSTR dll = L"MyDll.dll";
hDLL = LoadLibrary(dll);
}

Credit goes to TheUndeadFish.
void ReCompile()
{
//hDLL contains dll that was already loaded.
FreeLibrary(hDLL);
//my solution
system("msbuild \"D:\\Neumont\\Imagine\\RenderEngine\\Imagine.sln\" /property:Configuration=Debug /property:platform=Win32 ");
//general purpose
system("msbuild <path to your sln> /property:Configuration=build /property:platform=YourPlatform");
LPCWSTR dll = L"MyDll.dll";
hDLL = LoadLibrary(dll);
}
You need to add msbuild path to your enviorment variables. Mine was located in C:\Program Files (x86)\MSBuild\14.0\Bin. you might have to run vcvars32.bat
video of building DLL at runtime in action https://youtu.be/mFSv0tf6Vwc

Related

Visual Studio (Resetting C++ project)

I've never used C++ in Visual Studio but do some work with C# and VB.
I have a simple x86 C++ project that loads a 32bit DLL then uses a function from it.
It was working fine, then I changed some settings (SDK version, toolset, C++ language standard) and now I get "The specified module could not be found." when I try and load the DLL.
I've reset C++ in the "Import and export settings wizard" and then reinstalled all of Visual Studio but I can't seem to find a way to get the project back to working with this DLL. Dumpbin shows me that all the dependencies it needs are in SYSWOW64 :/
I've made copies of the DLL and put them everywhere I can think of, but I get the same problem. It loads with C# but I have some memory access issues passing strings to one of the functions.
Anyone had an issue like this before?
//Get current exe path and add DLL filename.
char cDLLPath[MAX_PATH + 1];
TCHAR bufCurrentDirectory[MAX_PATH + 1] = { 0 };
DWORD dwNumCharacters = ::GetCurrentDirectory(MAX_PATH, bufCurrentDirectory);
if (dwNumCharacters == 0)
{
printf("Error getting executable path\n");
exit(0);
}
snprintf(cDLLPath, MAX_PATH + 1, "%s\\MyDLL.dll", bufCurrentDirectory);
HINSTANCE myDll = LoadLibrary((LPCWSTR)cDLLPath);
//MyDLL is always NULL, error message is always "The specified module could not be found."
I've removed the path, tried current working folder, moved it to c:\windows\system32 etc
This function tells me the DLL path\filename are correct.
BOOL file_exists(const fs::path& file_path, fs::file_status s = fs::file_status{})
{
if (fs::status_known(s) ? fs::exists(s) : fs::exists(file_path)) return true;
else return false;
}
-Pook

Visual studio 2013 DLL Project: Dialog form not displayed while running the DLL

I have a Visual Studio 2013 C++ DLL project.
The build DLL works fine, except one point: There is a lack of interactive form which should open when DLL starts & it should be responsive to/from the DLL
I had referred to this link
I tried:
Right click on Project-> Select Add->Resource->Dialog
After that, a blank Dialog box appeared in the Visual Studio tab and it was listed in the Resources folder
I thought simply compiling the project would make the empty Dialog box display while running the DLL.
But even the empty Dialog box is not displayed when I run the DLL
Am I missing something here?
Also, would C++ be sufficient to add functionality to the form/Dialog? Or, any other language like C#?
(So that I may add event handling kind of functionality to that)
I suggest that you could use MFC to add functionality to the form/Dialog.
Here are the steps:
Create a MFC DLL named 'CTestDll', and select Regular DLL using shared MFC DLL
Then select Add->Resource->Dialog
Add code in CTestDll.cpp
#include "CTestDlg.h"
extern "C" __declspec(dllexport) void Show()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CTestDlg test;
test.DoModal();
}
Create a MFC App for testing. You could call it through the button click event.
void CMFCApplication3Dlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
typedef void (WINAPI *TESTDLL)();
HINSTANCE hInstance = LoadLibrary(_T("CTestDll.dll")); //
if (hInstance != NULL)
{
TESTDLL TestShow = (TESTDLL)GetProcAddress(hInstance, "Show");
if (TestShow != NULL)
{
TestShow();
}
FreeLibrary(hInstance);
}
}

Redirecting cout to stringstream from Debug build of DLL to Release build of EXE

I have a DLL streaming text to std::cerr. The EXE linking (via LoadLibrary()) to that DLL needs to get the text being streamed.
I am using VS90.
I use the following class in the EXE for the redirection:
struct cerr_redirect {
cerr_redirect( std::streambuf * new_buffer )
: old( std::cerr.rdbuf( new_buffer ) )
{ }
~cerr_redirect( ) {
std::cerr.rdbuf( old );
}
private:
std::streambuf * old;
};
This works fine as long as both DLL and EXE are build using the same configuration (either both Debug or both Release). However, when running a Release built EXE with a Debug built DLL, the redirection does not work and none of the cerr output made in the DLL gets to the EXE.
EDIT
The Runtime Library is linked dynamically. The Debug built DLL links against "Multi-threaded Debug DLL (/MDd)" while the Release built EXE links against "Multi-threaded DLL (/MD)".
I suspect this is the reason for this behavior; I believe std::cerr lives in the CRT. So when both DLL and EXE use the same CRT they share the same std::cerr, otherwise, they each have their own copy.
Could someone confirm if my understanding is correct?
If so, I think a solution to my problem is to define my own global stream in the EXE and let the DLL redirect cerr to it. Or is there a more elegant solution?

Multiple application entry points

Recently I was trying to add unit tests to an existing binary by creating a extra (DLLMain) entry point to an application that already has a main entry point (it is a console exe). The application seemed to compile correctly although I was unable to use it as a DLL from my python unit test framework, all attempts to use the exe as a dll failed.
Has anyone any ideas or experience in adding extra application entry point with any input as to why this would or wouldn't work?
There are some problems which you should solve to implement what you want:
The exe must have relocation table (use linker switch /FIXED:NO)
The exe must exports at least one function - it's clear how to do this.
I recommend use DUMPBIN.EXE with no some switches (/headers, /exports and without switches) to examine the exe headers. You can compare the structure of your application with Winword.exe or outlook.exe which exports some functions.
If all this will not helps, I'll try to write a test EXE application which can be loaded as an exe and post the code here.
UPDATED: Just now verified my suggestion. It works. File Loadable.c looks like following
#include <windows.h>
#include <stdio.h>
EXTERN_C int __declspec(dllexport) WINAPI Sum (int x, int y);
EXTERN_C int __declspec(dllexport) WINAPI Sum (int x, int y)
{
return x + y;
}
int main()
{
printf ("2+3=%d\n", Sum(2,3));
}
The only important linker switch is /FIXED:NO which one can find in advanced part of linker settings. The program can run and produced the output "2+3=5".
Another EXE loaded the EXE as a DLL and calls Sum function:
#include <windows.h>
#include <stdio.h>
typedef int (WINAPI *PFN_SUM) (int x, int y);
int main()
{
HMODULE hModule = LoadLibrary (TEXT("C:\\Oleg\\ExeAsDll\\Loadable.exe"));
PFN_SUM fnSum = (PFN_SUM) GetProcAddress (hModule, "_Sum#8");
int res = fnSum (5,4);
printf ("5+4=%d\n", res);
return 0;
}
The program also can run and produced the output "5+4=9".
I don't know for sure, but I would guess that Windows simply refuses to load an EXE in-process and a DLL as a new process, plain and simple.
These questions appear to contain more detail:
Can the DllMain of an .exe be called?
DllMain in an exe?
The simplest way to get both behaviours in one executable image is to design it as a DLL, then use rundll32.exe to execute it standalone. There's no need to write your own wrapper.

Calling functions in a DLL from C++

I have a solution in VS 2008 with 2 projects in it. One is a DLL written in C++ and the other is a simple C++ console application created from a blank project. I would like know how to call the functions in the DLL from the application.
Assume I am starting with a blank C++ project and that I want to call a function called int IsolatedFunction(int someParam)
How do I call it?
There are many ways to do this but I think one of the easiest options is to link the application to the DLL at link time and then use a definition file to define the symbols to be exported from the DLL.
CAVEAT: The definition file approach works bests for undecorated symbol names. If you want to export decorated symbols then it is probably better to NOT USE the definition file approach.
Here is an simple example on how this is done.
Step 1: Define the function in the export.h file.
int WINAPI IsolatedFunction(const char *title, const char *test);
Step 2: Define the function in the export.cpp file.
#include <windows.h>
int WINAPI IsolatedFunction(const char *title, const char *test)
{
MessageBox(0, title, test, MB_OK);
return 1;
}
Step 3: Define the function as an export in the export.def defintion file.
EXPORTS IsolatedFunction #1
Step 4: Create a DLL project and add the export.cpp and export.def files to this project. Building this project will create an export.dll and an export.lib file.
The following two steps link to the DLL at link time. If you don't want to define the entry points at link time, ignore the next two steps and use the LoadLibrary and GetProcAddress to load the function entry point at runtime.
Step 5: Create a Test application project to use the dll by adding the export.lib file to the project. Copy the export.dll file to ths same location as the Test console executable.
Step 6: Call the IsolatedFunction function from within the Test application as shown below.
#include "stdafx.h"
// get the function prototype of the imported function
#include "../export/export.h"
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// call the imported function found in the dll
int result = IsolatedFunction("hello", "world");
return 0;
}
Can also export functions from dll and import from the exe, it is more tricky at first but in the end is much easier than calling LoadLibrary/GetProcAddress. See MSDN.
When creating the project with the VS wizard there's a check box in the dll that let you export functions.
Then, in the exe application you only have to #include a header from the dll with the proper definitions, and add the dll project as a dependency to the exe application.
Check this other question if you want to investigate this point further Exporting functions from a DLL with dllexport.
The following are the 5 steps required:
declare the function pointer
Load the library
Get the procedure address
assign it to function pointer
call the function using function pointer
You can find the step by step VC++ IDE screen shot at http://www.softwareandfinance.com/Visual_CPP/DLLDynamicBinding.html
Here is the code snippet:
int main()
{
/***
__declspec(dllimport) bool GetWelcomeMessage(char *buf, int len); // used for static binding
***/
typedef bool (*GW)(char *buf, int len);
HMODULE hModule = LoadLibrary(TEXT("TestServer.DLL"));
GW GetWelcomeMessage = (GW) GetProcAddress(hModule, "GetWelcomeMessage");
char buf[128];
if(GetWelcomeMessage(buf, 128) == true)
std::cout << buf;
return 0;
}
You can either go the LoadLibrary/GetProcAddress route (as Harper mentioned in his answer, here's link to the run-time dynamic linking MSDN sample again) or you can link your console application to the .lib produced from the DLL project and include the hea.h file with the declaration of your function (as described in the load-time dynamic linking MSDN sample)
In both cases, you need to make sure your DLL exports the function you want to call properly. The easiest way to do it is by using __declspec(dllexport) on the function declaration (as shown in the creating a simple dynamic-link library MSDN sample), though you can do it also through the corresponding .def file in your DLL project.
For more information on the topic of DLLs, you should browse through the MSDN About Dynamic-Link Libraries topic.
Might be useful: https://www.codeproject.com/Articles/6299/Step-by-Step-Calling-C-DLLs-from-VC-and-VB-Part-4
For the example above with "GetWelcomeMessage" you might need to specify "__stdcall" in the typedef field before the function name if getting error after calling imported function.
Presuming you're talking about dynamic runtime loading of DLLs, you're looking for LoadLibrary and GetProAddress. There's an example on MSDN.
When the DLL was created an import lib is usually automatically created and you should use that linked in to your program along with header files to call it but if not then you can manually call windows functions like LoadLibrary and GetProcAddress to get it working.