2

我正在开发一个库,该库在开展业务的过程中使用一个或多个辅助程序可执行文件。我当前的实现要求用户在已知位置的系统上安装辅助可执行文件。为了使库正常运行,帮助应用程序必须位于正确的位置并且是正确的版本。

我想删除以上述方式配置系统的要求。

有没有办法将帮助程序可执行文件捆绑在库中,以便可以在运行时解压缩,安装在临时目录中,并在一次运行期间使用?在运行结束时,可以删除临时可执行文件。

我考虑过自动生成一个包含 unsigned char 数组的文件,该数组包含可执行文件的文本。这将在编译时作为构建过程的一部分完成。在运行时,此字符串将被写入文件,从而创建可执行文件。

是否可以在不将可执行文件写入磁盘(可能是某种 RAM 磁盘)的情况下完成这样的任务?我可以想象某些病毒扫描程序和其他安全软件会反对这种操作。还有其他我应该担心的问题吗?

该库是用 C/C++ 开发的,用于在 Windows 和 Linux 上跨平台使用。

4

7 回答 7

6

“聪明的人解决问题。聪明的人回避它。” - 艾尔伯特爱因斯坦

本着这句话的精神,我建议您简单地将这个可执行文件与最终应用程序捆绑在一起。

只是我的2美分。

于 2009-06-25T19:16:04.327 回答
2

您可以使用xxd将二进制文件转换为 C 头文件。

$ echo -en "\001\002\005" > x.binary

$ xxd -i x.binary 
unsigned char x_binary[] = {
  0x01, 0x02, 0x05
};
unsigned int x_binary_len = 3;

xxd在 *nix 系统上是相当标准的,它可以在带有 Cygwin 或 MinGW 的 Windows 上使用,或者 Vim 也将它包含在标准安装程序中。这是一种将二进制数据包含到编译代码中的极其跨平台的方式。

另一种方法是使用objcopy将数据附加到可执行文件的末尾——您可以获得 IIRC并将objcopy用于 Windows 上的 PE。

我喜欢的一种比这更好的方法是将原始数据直接附加到可执行文件的末尾。在可执行文件中,您查找文件末尾,并读入一个数字,指示附加二进制数据的大小。然后你向后寻找那么多字节和fread数据并将其复制到文件系统,在那里你可以将其视为可执行文件。顺便说一下,许多(如果不是全部)自解压可执行文件的创建方式

如果附加二进制数据,它适用于 Windows PE 文件和 *nix ELF 文件——它们都不会超过可执行文件的“限制”。

当然,如果您需要附加多个文件,您可以将 tar/zip 文件附加到您的 exe 中,或者您需要更高级的数据结构来读取附加的内容。

您可能还希望在附加可执行文件之前对其进行UPX 。

您可能还对LZO 库感兴趣,据报道它是解压缩速度最快的压缩库之一。他们有一个 MiniLZO 库,您可以将其用于非常轻量级的解压缩器。但是,LZO 库是 GPL 许可的,因此这可能意味着您不能将它包含在源代码中,除非您的代码也是 GPL 的。另一方面,有可用的商业许可证。

于 2009-09-18T17:18:59.287 回答
1

与使用 unsigned char* 数组略有不同的方法是将整个可执行二进制文件作为 dll 的资源。在运行时,您可以将二进制数据保存为本地临时文件并执行应用程序。不过,我不确定是否有办法在内存中执行可执行文件。

于 2009-06-25T16:08:14.240 回答
1

为了使库正常运行,帮助应用程序必须位于正确的位置

在 Windows 上,是 Program Files 目录还是 System32 目录?

这可能是个问题。安装应用程序时,尤其是在公司环境中,通常发生在具有管理权限的上下文中。在启用 UAC(默认)的 Vista 和更高版本上,这是写入某些目录所必需的。只要任何人都记得,大多数 Unix 风格都有类似的合理限制。

因此,如果您尝试在主机应用程序调用您的库时执行此操作,则可能没有足够的权限来安装文件,因此您的库会对主机应用程序施加限制。

(另一件将被排除的事情是注册表更改,或各种 Unices 上的配置文件更新,如果主机应用程序没有能力将进程提升到管理级别。)

说了这么多,您说您正在考虑将帮助程序解压缩到一个临时目录中,所以也许这一切都没有实际意义。

于 2009-06-25T19:42:53.617 回答
1

Qt 有一个很好的方法来实现这一点:QResource

“Qt 资源系统是一种独立于平台的机制,用于在应用程序的可执行文件中存储二进制文件。”

您没有说您当前是否使用 Qt,但您确实说“C++ for cross platform use on Windows and Linux”,所以即使您不使用它,您也可能要考虑开始。

于 2009-09-18T17:24:10.190 回答
0

Windows 中有一种方法可以从内存中运行可执行文件,而无需将其写入磁盘。问题在于,由于现代安全系统 (DEP),这可能不适用于所有系统,并且几乎所有反恶意软件扫描程序都会检测到它并警告用户。

我的建议是简单地将可执行文件打包到您的发行版中,这无疑是实现这一目标的最可靠方法。

于 2009-06-25T19:29:33.160 回答
0

好吧,我的第一个想法是:这个帮助程序可执行文件做了哪些在你的库代码本身中无法完成的工作,如果有必要,可能使用辅助线程。这可能是需要考虑的事情。

但至于实际问题......如果您的“库”实际上捆绑为 dll(甚至是 exe),那么至少 Windows 对在库中嵌入文件具有相对简单的支持。

允许将版本信息和图标等内容嵌入可执行文件的资源机制也可以允许任意数据块。由于我不知道您使用的是什么开发环境,因此我无法确切说明如何执行此操作。但粗略地说,您需要创建一个具有“文件”类型或类似类型的自定义资源,并将其指向您要嵌入的 exe。

然后,当你想提取它时,你会写类似

HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(IDR_MY_EMBEDDED_FILE), "FILE");
HGLOBAL hResourceData = LoadResource(NULL, hResource);
LPVOID pData = LockResource(hResourceData);
HANDLE hFile = CreateFile("DestinationPath\\Helper.exe", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwBytesWritten = 0;
WriteFile(hFile, pData, SizeofResource(NULL, hResource), &dwBytesWritten, NULL);
CloseHandle(hFile);

(填写您自己想要的路径、文件名,当然还有任何适当的错误检查)

之后,帮助程序 exe 以普通 exe 文件的形式存在,因此您可以按照通常的方式执行它。

要在使用后删除文件,您应该调查 的标志CreateFile,尤其是FILE_FLAG_DELETE_ON_CLOSE. 您还可以查看在MoveFileExMOVEFILE_DELAY_UNTIL_REBOOT标志与为新文件名传递的 NULL 组合时使用。当然,如果您知道可执行文件何时结束,您可以随时在自己的代码中删除它。

我对 Linux 可执行文件知之甚少,所以我不知道那里是否有类似的功能。

如果 Linux 没有提供任何方便的机制和/或如果这个想法不适合您在 Windows 中的需求,那么我想您从帮助程序 exe 的内容生成无符号字符数组的想法将是嵌入的下一个最佳方法库中的 exe。

于 2009-06-25T23:30:18.870 回答