如何在 C++ 中将一个 exe 文件作为资源嵌入到另一个 exe 文件中?
How to embed an exe file into another exe file as a resource in C++?
我正在尝试使用预构建的 .exe 文件作为我的 C++ 项目中的资源,搜索后我完成了以下步骤:
步骤 1
新建一个C++工程,在Source.cpp文件中放入如下代码
#include<iostream>
#include<Windows.h>
#include<fstream>
#define IDB_EMBEDEXE 52
using namespace std;
int main() {
int count = 2;
HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(IDB_EMBEDEXE), __TEXT("BINARY"));
HGLOBAL hGlobal = LoadResource(NULL, hResource);
size_t exeSiz = SizeofResource(NULL, hResource);
void* exeBuf = LockResource(hGlobal);
ofstream outfile((char*)exeBuf, ios::out | ios::binary);
if (!outfile)
exit(9);
outfile.write((char*)exeBuf, exeSiz);
system((char*)exeBuf);
return 0;
}
Step2新建资源文件(.rc)
1- 项目>添加新项目
2- 从 Installed>Visual C++>Resource 选择 Resource File (.rc) 让我们将其命名为 Resource.rc
Step3编辑刚刚创建的头文件resource.h Step2,在头文件中加入如下行:
#define IDB_EMBEDEXE 52
Step4 通过右击编辑 Resource.rc 文件>打开>源代码(文本)编辑器,在第一个 #include
语句之后添加以下代码(即在 #include "resource.h"
之后
#define IDB_EMBEDEXE 52
IDB_EMBEDEXE BINARY "C:\Users\Almohandis\source\repos\Project7\sum2num.exe"
完全按照这些步骤执行后,我仍然在 cmd 中收到以下错误(而不是在 Visual Studio 中):
'MZ' is not recognized as an internal or external command,
operable program or batch file.
程序以代码0结束
我认为调用 system()
是什么导致了问题,尤其是我传递的参数。
注意sum2num.exe文件的二进制表示以MZ....
开头
如果您的 #define
已经在 resource.h
中,则无需在您的源代码中复制它。只需在您的代码中使用 #include "resource.h"
。
无论如何,您应该使用 pre-defined RCDATA
资源类型,而不是创建自定义 BINARY
类型。
也就是说,您对 ofstream
和 system()
的使用都是错误的。您正在向他们传递资源的原始二进制数据,但他们期望的是文件路径。您正在使用 .rc
文件中的文件路径来指定将其二进制数据复制到资源中的文件。正如您所期望的那样,该资源不包含该文件路径。
试试这个:
resource.h
...
#define IDB_EMBEDEXE 52
...
Resource.rc
#include "resource.h"
...
IDB_EMBEDEXE RCDATA "C:\Users\Almohandis\source\repos\Project7\sum2num.exe"
...
Source.cpp
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
#include "resource.h"
using namespace std;
int main() {
HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(IDB_EMBEDEXE), RT_RCDATA);
if (!hResource)
return 1;
HGLOBAL hGlobal = LoadResource(NULL, hResource);
if (!hGlobal)
return 2;
DWORD exeSiz = SizeofResource(NULL, hResource);
if (!exeSiz)
return 3;
void* exeBuf = LockResource(hGlobal);
if (!exeBuf)
return 4;
char tempPath[MAX_PATH] = {};
if (!GetTempPathA(MAX_PATH, path))
return 5;
string fullPath = string(tempPath) + "sum2num.exe";
ofstream outfile(fullPath.c_str(), ios::binary);
if (!outfile.is_open())
return 6;
int res = (outfile.write((char*)exeBuf, exeSiz)) ? 0 : 7;
outfile.close();
if (res == 0) {
system(fullPath.c_str());
}
remove(fullPath.c_str());
return res;
}
我正在尝试使用预构建的 .exe 文件作为我的 C++ 项目中的资源,搜索后我完成了以下步骤:
步骤 1 新建一个C++工程,在Source.cpp文件中放入如下代码
#include<iostream>
#include<Windows.h>
#include<fstream>
#define IDB_EMBEDEXE 52
using namespace std;
int main() {
int count = 2;
HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(IDB_EMBEDEXE), __TEXT("BINARY"));
HGLOBAL hGlobal = LoadResource(NULL, hResource);
size_t exeSiz = SizeofResource(NULL, hResource);
void* exeBuf = LockResource(hGlobal);
ofstream outfile((char*)exeBuf, ios::out | ios::binary);
if (!outfile)
exit(9);
outfile.write((char*)exeBuf, exeSiz);
system((char*)exeBuf);
return 0;
}
Step2新建资源文件(.rc)
1- 项目>添加新项目
2- 从 Installed>Visual C++>Resource 选择 Resource File (.rc) 让我们将其命名为 Resource.rc
Step3编辑刚刚创建的头文件resource.h Step2,在头文件中加入如下行:
#define IDB_EMBEDEXE 52
Step4 通过右击编辑 Resource.rc 文件>打开>源代码(文本)编辑器,在第一个 #include
语句之后添加以下代码(即在 #include "resource.h"
#define IDB_EMBEDEXE 52
IDB_EMBEDEXE BINARY "C:\Users\Almohandis\source\repos\Project7\sum2num.exe"
完全按照这些步骤执行后,我仍然在 cmd 中收到以下错误(而不是在 Visual Studio 中):
'MZ' is not recognized as an internal or external command, operable program or batch file.
程序以代码0结束
我认为调用 system()
是什么导致了问题,尤其是我传递的参数。
注意sum2num.exe文件的二进制表示以MZ....
如果您的 #define
已经在 resource.h
中,则无需在您的源代码中复制它。只需在您的代码中使用 #include "resource.h"
。
无论如何,您应该使用 pre-defined RCDATA
资源类型,而不是创建自定义 BINARY
类型。
也就是说,您对 ofstream
和 system()
的使用都是错误的。您正在向他们传递资源的原始二进制数据,但他们期望的是文件路径。您正在使用 .rc
文件中的文件路径来指定将其二进制数据复制到资源中的文件。正如您所期望的那样,该资源不包含该文件路径。
试试这个:
resource.h
...
#define IDB_EMBEDEXE 52
...
Resource.rc
#include "resource.h"
...
IDB_EMBEDEXE RCDATA "C:\Users\Almohandis\source\repos\Project7\sum2num.exe"
...
Source.cpp
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
#include "resource.h"
using namespace std;
int main() {
HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(IDB_EMBEDEXE), RT_RCDATA);
if (!hResource)
return 1;
HGLOBAL hGlobal = LoadResource(NULL, hResource);
if (!hGlobal)
return 2;
DWORD exeSiz = SizeofResource(NULL, hResource);
if (!exeSiz)
return 3;
void* exeBuf = LockResource(hGlobal);
if (!exeBuf)
return 4;
char tempPath[MAX_PATH] = {};
if (!GetTempPathA(MAX_PATH, path))
return 5;
string fullPath = string(tempPath) + "sum2num.exe";
ofstream outfile(fullPath.c_str(), ios::binary);
if (!outfile.is_open())
return 6;
int res = (outfile.write((char*)exeBuf, exeSiz)) ? 0 : 7;
outfile.close();
if (res == 0) {
system(fullPath.c_str());
}
remove(fullPath.c_str());
return res;
}