我的目标是只有一个可执行文件.
>是否可以将托管的.exe合并到非托管的.exe中?
有很多关于相反的事情的信息(将非托管代码合并到托管项目中),但我无法找到任何关于朝另一个方向发展的事情.
背景:
它适用于系统要求/兼容性检查程序.
我在.NET 2中使用C#编写了大部分内容.
但是,只有在确定系统至少安装了.NET 2时,此部分才会运行.
这就是“DotNetVersionIdentifier.exe”发挥作用的地方.
无论是否安装了.NET Framework,它都将运行unmanaged code.如果安装了.NET 2.0或更高版本,我已修改代码以运行我的C#程序,而不是显示已安装的.NET版本的对话框,或者报告自定义消息.
>我想在C可执行文件中打包C#程序,这样我只需要分发一个.exe
我尝试过使用ILMerge,但由于我的非托管代码无法编译为中级语言,因此崩溃了……
我可以将我的C#项目添加到C解决方案中,但它仍然可以编译为两个单独的可执行文件.
这种方法:How to Append Data to the End of an .EXE File听起来像一个迷人的,但过时的黑客.
这个想法似乎可能有用:How to embed an exe inside another exe as a resource and then launch it我现在正在研究它.
最佳答案 我设法通过使用Resources,
as outlined here来实现我的目标.
这就是我如何使它发挥作用. (我是C的新手,如果你看到任何愚蠢,请告诉我)
>将托管代码编译为单个文件
>将托管代码可执行文件重命名为.txt
>创建一个新的Visual C Win32控制台应用程序
>添加新项目 – 资源文件(.rc)
>打开资源文件,添加资源,选择导入,输入“TEXT”作为类型
>修改“DWORD大小”以匹配托管.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上运行:
>确保Platform目标是Win32
>将配置属性>常规>平台工具集设置为“Visual Studio 2013 – Windows XP(x120_xp)”
>将配置属性> C/C++>代码生成>运行时库设置为“多线程(/ MT)