如何在Qt程序中嵌入二进制可执行文件(在运行时执行)?

时间:2009-12-21 18:22:59

标签: qt qprocess

我正在使用Qt编写一个跨平台的C ++程序,我想在程序中打包/嵌入一些二进制可执行文件。该程序应该能够在运行时执行这些二进制文件。

我想,我需要使用start()和“:/ ...”表示法来使用QResource和QProcess,但我似乎没有让进程运行。有什么我想念的吗?它应该像这样工作吗?二进制文件是否需要设置为可执行文件?

背景:我正在编写一个使用Git的工具,我不想让最终用户手动安装Git。

(在Mac OS X上试试,BTW。)

更新

我使用以下代码(C ++,Mac OS X上的Qt):

QString program = ":/git";
QStringList arguments;
arguments << "help" << "commit";
myProcess->start(program, arguments);

Git可执行文件位于项目路径中,我的resources.qrc像这样引用它:

<qresource prefix="/">
    <file>git</file>
</qresource>

我没有收到错误,但程序没有执行。将program设置为不存在的文件时,行为是相同的。用git的绝对路径替换":/git"非常有效。

4 个答案:

答案 0 :(得分:9)

您无法直接从资源执行程序。

如果您在资源中有一个程序并且想要执行它,那么首先必须从资源中读取它,将其写入文件,使文件可执行,然后执行它。

另外,当您说您没有收到错误时,这可能意味着您没有正确检查错误。

答案 1 :(得分:3)

迟了几年,但问题仍然存在。我想在嵌入rclone时遇到同样的问题。

.pro文件中,添加

# From http://stackoverflow.com/a/37561981
defineReplace(copyToDir) {
    files = $$1
    DIR = $$2
    LINK =

    for(FILE, files) {
        LINK += $$QMAKE_COPY $$shell_path($$FILE) $$shell_path($$DIR) $$escape_expand(\\n\\t)
    }
    return($$LINK)
}

defineReplace(copyToBuilddir) {
    return($$copyToDir($$1, $$OUT_PWD))
}

# Copy the binary files dependent on the system architecture
win32 {
    message("Windows")
    QMAKE_POST_LINK += $$copyToBuilddir($$PWD/rclone/windows/rclone.exe)
}else: unix:!macx {
    message("Linux")
    QMAKE_POST_LINK += $$copyToBuilddir($$PWD/rclone/linux/rclone)
}else: macx: {
    # Here we want to place the binaries inside the application bundle, so the 
    # QMAKE_POST_LINK approach will not work because it places them in the same
    # directory as the bundle and not inside it. Instead, use QMAKE_BUNDLE_DATA.
    message("macOS")
    MediaFiles.files += $$PWD/rclone/macOS/rclone
    MediaFiles.path = Contents/MacOS
    QMAKE_BUNDLE_DATA += MediaFiles
}

请注意每个平台的差异如何,但总的来说方法是相同的。

qmake会将此文件复制到目标目录,只需将进程调用到本地相对目录即可访问它们。

在下面的代码中,我从QML调用可执行文件,它在C ++中也会非常相似:

var rcloneCommand
if (Qt.platform.os === "windows") {
    console.log("Windows")
    rcloneCommand = "rclone.exe"
} else {
    console.log("OSX/Linux")
    rcloneCommand = "./rclone"
}
qProcess.start(rcloneCommand, ["--config", "rclone.conf", "-v", "copy", "--stats", "1s", source, destination]);

答案 2 :(得分:2)

我不认为资源会起作用。进程由操作系统创建,资源由应用程序处理。

一种可能的解决方案是在应用程序目录中的某处捆绑其他可执行文件,并从该路径执行它们。

答案 3 :(得分:0)

所以问题似乎不是从资源中提取git可执行文件而不是执行它?

git程序正确生成don磁盘,你可以查看它的权限吗?