将托管程序合并到非托管的 C++ 可执行文件中

4
我的目标是只有一个可执行文件。
  • 能否将托管的.exe合并到非托管的.exe中?

有很多关于将非托管代码合并到托管项目中的信息,但我没有找到任何关于反向操作的内容。

背景:

这是一个系统要求/兼容性检查器。
我使用.NET 2中的C#编写了大部分内容。
但是,只有在确定系统至少安装了.NET 2时,此部分才会运行。
这就是"DotNetVersionIdentifier.exe"发挥作用的地方。
它的非托管代码将在不安装.NET Framework的情况下运行。我已经修改了代码,如果安装了.NET 2.0或更高版本,则运行我的C#程序,否则报告自定义消息。

  • 我希望将C#程序打包到C++可执行文件中,这样我只需要分发一个单独的.exe文件。

我尝试使用ILMerge,但由于我的非托管代码无法编译为中间语言,它会崩溃...

ILMerge doesn't accept unmanaged code...

我可以将我的C#项目添加到C++解决方案中,但它仍会编译为两个独立的可执行文件。
这种方法:如何向.EXE文件末尾添加数据听起来像是一种迷人但过时的黑客技巧。
这个想法似乎可行:如何将一个exe嵌入到另一个exe中作为资源,然后启动它,我正在研究它。

你在SO上需要什么类型的帮助?确实,你可以将文件作为资源添加到托管或本机应用程序中,保存它并按照你所建议的链接运行。 - Alexei Levenkov
我还没有让它正常工作,所以我只是试探一下是否可能有另外/更好的方法。 - Scott Solmer
对我来说还不是很清楚... Resources 是实现你所要求的标题的简单直接的方式(如果适用于你的情况-你自己决定)... 链接的文章看起来很合理...“我应该手动检测 .Net 2.0 是否已安装”这个问题是不切题的,因为它是基于观点的。 - Alexei Levenkov
好的,我还在努力。当我开始这个冒险时,它似乎并不是很简单。这个问题并不要求意见。我有一个明确的问题,正在寻求解决方案。 - Scott Solmer
@AlexeiLevenkov,事实证明使用资源确实有效。Kumar博客上的伪代码需要进行大量调整才能使其正常工作。此外,他描述了手动将文件添加为资源,这在我的VS中导致了问题。我已发布了我的结果。 - Scott Solmer
1个回答

2

我通过使用资源(按照这里的说明)实现了我的目标。

以下是我如何使其工作的步骤。(我对C++比较新,如果你发现任何愚蠢的地方,请告诉我。)

  • 将托管代码编译为单个文件
  • 将托管代码可执行文件重命名为.txt文件
  • 创建一个新的Visual C++ Win32控制台应用程序
  • 添加新项-资源文件(.rc)
  • 打开资源文件,添加资源,选择导入,输入“TEXT”作为类型
  • 修改"DWORD size"以匹配托管.txt文件的大小

其余的可以通过代码转储来解释。
希望这能对某些人有所帮助(像我这样的C++新手...)

#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 - 这是在使用VS2013的GUI导入资源时,自动生成的,连同对Recource.rc的修改一起生成。

//{{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/C++>代码生成>运行库 设置为 "多线程(/MT)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接