启动其他可执行文件的最便捷的方法

时间:2019-05-29 18:22:26

标签: c++ exec c++17 executable

编辑:我将仅将systemstd::filesystem::path一起使用,因为它可移植且非常简单。由于我的程序可能不需要任何管理员权限,因此我相信这不会以麻烦而告终。


经过大量研究和大量尝试,我发现了如何直接从C ++启动另一个程序。不幸的是,有很多不同的方法可以执行此操作,例如,丑陋的system,旧posix spawn和特定于平台的WinAPI。

我真的很想让我的可执行文件尽可能地可移植。由于缺乏安全性,我无法使用system,可以吗? WinAPI仅可在Windows上运行,但我最喜欢的spawn一堆功能也不起作用,至少在Windows 10下无法响应。

那么从C ++运行程序的最好,最便携的方法是什么?有一个多功能的功能吗?还是应该运行预处理程序并检查Win-OS或Non-Win-OS?

欢迎使用任何代码段!

2 个答案:

答案 0 :(得分:2)

  

启动其他可执行文件的最便捷的方式

C ++标准库只有std::systemwhich

  

使用参数command调用主机环境的命令处理器(例如/bin/sh、cmd.exe、command.com)。返回实现定义的值(通常是被调用程序返回的值)。

它在所有符合标准的系统上都可用,但是shell语法将由实现定义。只需使用可执行文件的路径即可移植。

但是它有潜在的缺点:

  • 如果您不想要子代,则无法避免。
  • 您无法避免执行外壳程序,如果涉及到用户定义的输入,则外壳程序有可能注入命令。

POSIX标准指定exec which is

  

exec系列功能应将当前过程映像替换为新的过程映像。

这是一个较低级的函数,可以像system一样使用,但是如果需要,您需要自己创建一个子流程。

但是并非所有操作系统都支持POSIX标准,尤其是Windows并不支持。 Windows显然在其POSIX兼容性层中有_execv(请注意POSIX函数以下划线作为前缀),但是它有一个局限性:

  

此API不能在Windows运行时中执行的应用程序中使用。

此外,如果您希望产生一个子流程并保持原始流程运行,则没有标准的方法可以在标准C ++中创建子流程。

POSIX指定fork(和spawn,它们结合了forkexec)。 Windows有自己的API。


因此,鉴于缺乏通用标准,可移植地启动另一个可执行文件(可能在子进程中)的方法是使用预定义的宏来检测目标系统,并针对所需的每个API分别实现功能支持。

如果没有缺点,请使用std::system

答案 1 :(得分:1)

以自己的便携式方式进行操作:

#include <cstdlib>
#include <iostream>
#include <string_view>
#include <thread>

auto mysystem(const std::string_view cmdline, bool detach = false) {
    std::thread retval = std::thread([cmdline] { std::system(cmdline.data()); });
    if(detach) retval.detach();
    return retval;
}

int main() {
    auto t = mysystem("find /");
    t.join();
    // or
    mysystem("find /", true); // to detach the thread and therefore process
}