我正在开发一个在开展业务的过程中使用一个或多个帮助程序可执行文件的库。我当前的实现要求用户在已知位置的系统上安装帮助程序可执行文件。为使库正常运行,帮助应用程序必须位于正确的位置并且版本正确。
我想删除以上述方式配置系统的要求。
有没有办法捆绑库中的帮助程序可执行文件,以便它可以在运行时解压缩,安装在临时目录中,并在一次运行期间使用?在运行结束时,可以删除临时可执行文件。
我考虑过自动生成一个包含unsigned char数组的文件,该数组包含可执行文件的文本。这将在编译时完成,作为构建过程的一部分。在运行时,此字符串将写入文件,从而创建可执行文件。
是否可以在不将可执行文件写入磁盘(可能是某种RAM磁盘)的情况下执行此类任务?我可以设想某些病毒扫描程序和其他安全软件反对这种操作。我还应该担心其他问题吗?
该库正在使用C / C ++开发,以便在Windows和Linux上进行跨平台使用。
答案 0 :(得分:6)
“一个聪明的人解决了一个问题 明智的人避免它。“ - 阿尔伯特爱因斯坦
根据这句话的精神,我建议您将此可执行文件与最终应用程序捆绑在一起。
只需2美分。
答案 1 :(得分: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系统上非常标准,它可以在Windows上使用Cygwin或MinGW,或者Vim也可以在标准安装程序中使用它。这是一种将二进制数据包含在已编译代码中的极为跨平台的方法。
另一种方法是使用objcopy
将数据附加到可执行文件的末尾 - 您可以获取objcopy
的IIRC并将其用于Windows上的PE。
我喜欢的一种方法是将原始数据直接附加到可执行文件的末尾。在可执行文件中,您搜索文件的末尾,并读入一个数字,指示附加的二进制数据的大小。然后你向后搜索那么多字节,并fread
该数据并将其复制到文件系统,在那里你可以把它当作可执行文件。顺便提一下the way that many, if not all, self-extracting executables are created。
如果您附加二进制数据,它可以同时使用Windows PE文件和* nix ELF文件 - 它们都不会读取可执行文件的“限制”。
当然,如果你需要附加多个文件,你可以将一个tar / zip文件附加到你的exe文件中,或者你需要一个更先进的数据结构来读取附加的文件。
在添加可执行文件之前,您可能还需要UPX。
您可能也对LZO library感兴趣,据说这是解压缩速度最快的压缩库之一。他们有一个MiniLZO库,可以用于非常轻量级的解压缩器。但是,LZO库是GPL许可的,因此可能意味着您不能将其包含在源代码中,除非您的代码也是GPL。另一方面,有商业许可证。
答案 2 :(得分:1)
与使用unsigned char *数组略有不同的方法是将整个可执行二进制文件作为dll的资源。在运行时,您可以将二进制数据保存为本地临时文件并执行应用程序。我不确定是否有办法在内存中执行可执行文件。
答案 3 :(得分:1)
使库正常运行 帮助应用程序必须正确 位置
在Windows上,它是Program Files目录还是System32目录?
这可能是个问题。安装应用程序时,尤其是在企业环境中,它通常发生在具有管理权限的上下文中。在Vista和更高版本启用UAC(默认设置)时,必须写入某些目录。只要有人记得,大多数Unix风味都有明智的限制。
因此,如果您尝试在主机应用程序调用库时执行此操作,那么可能不在具有足够权限来安装文件的上下文中,因此您的库会在主机应用程序上设置约束。
(如果主机应用程序无法将进程升级到管理级别,那么将排除另一件事是注册表更改或各种Unices上的配置文件更新。)
说了这么多,你说你正在考虑将帮助程序解压缩到一个临时目录中,所以也许这一切都没有用。
答案 4 :(得分:1)
Qt有一个很好的方法来实现这一目标:QResource
“Qt资源系统是一种独立于平台的机制,用于在应用程序的可执行文件中存储二进制文件。”
你没有说你目前是否正在使用Qt,但是你确实说“C ++用于在Windows和Linux上跨平台使用”,所以即使你没有使用它,你也可以考虑开始。
答案 5 :(得分:0)
Windows中有一种方法可以从内存中运行可执行文件而无需将其写入磁盘。问题在于,由于现代安全系统(DEP),这可能不适用于所有系统,几乎所有反恶意软件扫描程序都会检测到它并警告用户。
我的建议是简单地将可执行文件打包到您的发行版中,这当然是实现此目的的最可靠方法。
答案 6 :(得分:0)
好吧,我的第一个想法是:这个帮助程序可执行文件在你的库代码本身中做了什么,可能在必要时使用辅助线程。这可能需要考虑。
但至于实际的问题......如果你的“库”实际上被捆绑为dll(甚至是exe),那么至少Windows对于在你的库中嵌入文件提供了相对简单的支持。
允许将版本信息和图标嵌入可执行文件之类的资源机制也可以允许任意数据块。由于我不知道你正在使用什么开发环境,我不能确切地说如何做到这一点。但粗略地说,你需要创建一个类型为“FILE”的自定义资源或类似的东西,并将它指向你想要嵌入的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);
(填写您自己想要的路径,文件名,当然还有任何适当的错误检查)
之后,helper exe作为普通的exe文件存在,因此您可以像往常那样执行它。
要在使用后删除文件,您应该调查CreateFile
的标记,尤其是FILE_FLAG_DELETE_ON_CLOSE
。在将MoveFileEx
标志与为新文件名传递的NULL组合时,您可能还会考虑使用MOVEFILE_DELAY_UNTIL_REBOOT
。当然,如果可以告诉可执行文件何时结束,您可以随时在自己的代码中删除它。
我对Linux可执行文件知之甚少,所以我不知道那里是否有类似的功能。
如果Linux没有提供任何方便的机制和/或如果这个想法不适合你在Windows中的需求,那么我想你从helper exe的内容生成一个unsigned char数组的想法将是次佳的将exe嵌入库中的方法。