Combining a managed program into an unmanaged C ++ executable

My goal is to have only one executable file.

  • Is it possible to combine a managed .exe file into an unmanaged .exe?

There is a lot of information on how to do something the other way around (merging unmanaged code into a managed project), but I could not find anything in the other direction.

Background:

This is for system requirements / compatibility checks.
I wrote the main part using C # in .NET 2.
However, this part will be executed only if it determines that at least .NET 2 is installed on the system.
That "DotNetVersionIdentifier.exe" comes into play.
This unmanaged code will run regardless of whether the .NET Framework is installed. Instead of showing a dialog box for installed versions of .NET, I changed the code to run my program in C # if .NET 2.0 or higher is installed, or it will report a special message.

  • I would like to pack a C # program inside a C ++ executable, so I only need to distribute one .exe

I tried to use ILMerge, but since my unmanaged code does not compile in the Intermediate Language, it crashes ...

ILMerge doesn't accept unmanaged code ...

I can add my C # project to a C ++ solution, but it still compiles into two separate executables.

This approach: How to add data to the end of a .EXE file sounds like a fascinating but outdated hack.

This idea seems that it can work: How to insert an exe inside another exe as a resource, and then run it , and I'm looking into it now.

+4
source share
1 answer

I managed to accomplish my goal using Resources, as described here .

. ( ++, , - )

  • .txt
  • Visual ++ Win32
  • - (.rc)
  • , , "", ""
  • "DWORD" .txt.

.
, - ( ++, ...)

#include "stdafx.h"
#include "resource.h"
#include "windows.h"
#include "iostream"
#include <string>
#include <sstream>

using namespace std;

namespace std
{
    HRSRC hrsrc = NULL;
    HGLOBAL hGlbl = NULL;
    BYTE *pExeResource = NULL;
    HANDLE hFile = INVALID_HANDLE_VALUE;
    DWORD size = 8192; //hardcoding the size of the exe resource (in bytes)
    HINSTANCE g_Handle = NULL;
    HINSTANCE hInstance = NULL; // Passing NULL uses the instance that started the process( CSMerged.exe ).

    template <typename T>
    string NumberToString(T pNumber)
    {
        ostringstream oOStrStream;
        oOStrStream << pNumber;
        return oOStrStream.str();
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    hrsrc = FindResource(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_TEXT1), _T("TEXT"));
    if (hrsrc == NULL)
    {
        cout << "hrsc is null! \n";
        cin.get(); // leave the console open.
        return FALSE;
    }

    hGlbl = LoadResource(hInstance, hrsrc);
    if (hGlbl == NULL)
    {
        cout << "hGlbl is null! \n";
        cin.get(); // leave the console open.
        return FALSE;
    }

    pExeResource = (BYTE*)LockResource(hGlbl);
    if (pExeResource == NULL)
    {
        cout << "pExeResource is null! \n";
        cin.get(); // leave the console open.
        return FALSE;
    }

    hFile = CreateFile(L"ManagedCode.exe", GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    if (hFile != INVALID_HANDLE_VALUE)
    {
        DWORD bytesWritten = 0;
        WriteFile(hFile, pExeResource, size, &bytesWritten, NULL);
        CloseHandle(hFile);
    }

    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    int ret = CreateProcess(L"ManagedCode.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

    if (ret == 1) { return 0; } // the process started successfully, so I'm done here.
    else
    {
        cout << "CreatePrecess returns " + NumberToString(ret) + ". \n";
        cin.get(); // leave the console open
    }

    return 0;
}

Resource.h  - Recource.rc, VS2013.

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Resource.rc
//
#define IDR_TEXT1                       101

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

, , Windows XP:

  • , Win32
  • > > "Visual Studio 2013 - Windows XP (x120_xp)"
  • > C/++ > a > " (/MT)
+2

All Articles