c++ - 如何避免 Windows _exec* 和 _spawn* 函数在空格处拆分参数?

标签 c++ windows

在 C++ Windows 控制台程序中使用 _execv() 函数时,我发现参数以空格分隔,每个子字符串在执行程序的参数列表中成为一个单独的参数。据推测,直到找到该程序后才会发生这种情况,因为即使程序路径参数包含空格也能找到它。

我写了两个程序来演示这个问题。 _spawnv() 也会发生同样的事情,如果我修改调用程序以使用 wchar_t 数组和 _wexecv()。

我在 Windows 10 上使用 Visual Studio 2017 将示例构建为 x86 或 x64 Windows 控制台应用程序项目。如何在使用其中一个函数时避免此问题?

// Calling program

#include "pch.h"
#include <iostream>
#include <process.h>

int main()
{
    const char program[] = "C:\\Users\\dummy\\Documents\\Visual Studio 2017\\Projects\\execTest\\x64\\Debug\\testCalled.exe";
    const char* arguments[] = { program, "Hello   World!", nullptr };   // Note the multiple spaces

    for (int a = 0; sizeof(arguments) / sizeof(*arguments) > a && arguments[a]; ++a) {
        std::cerr << "Caller: " << a << " = " << arguments[a] << '\n';
    }
    std::wcerr << '\n';

    auto rc = _execv(program, arguments);

    perror("Exec fail ");
    std::cerr << "return code " << rc <<'\n';
    return rc;
}

// Called program

#include "pch.h"
#include <iostream>

int main( int argc, char** argv)
{
    for (int a = 0; a < argc; ++a) {
        std::cerr << "Called: " << a << " = " << argv[a] << '\n';
    }
    return 0;
}

Output:
Caller: 0 = C:\Users\dummy\Documents\Visual Studio 2017\Projects\execTest\x64\Debug\testCalled.exe
Caller: 1 = Hello   World!

Called: 0 = C:\Users\dummy\Documents\Visual
Called: 1 = Studio
Called: 2 = 2017\Projects\execTest\x64\Debug\testCalled.exe
Called: 3 = Hello
Called: 4 = World!

最佳答案

在类 Unix 系统上,execve 是允许程序用另一个程序删除自身的系统调用,它接收单独参数,而exec 家族函数直接调用。

在 Windows 上,系统 API 定义了 CreateProcess 函数,该函数使用新程序的名称或路径(如 execve 所做的那样)和构建的单个命令行通过加入exec的参数。

这意味着您必须将包含空格的参数括在显式双引号中。所以 Windows 的方式确实是:

const char* arguments[] = { program, "\"Hello   World!\"", nullptr };

C 标准没有定义 execv 函数,它只在 Posix 和 Windows 中定义,尽管试图兼容不是 Posix 系统,所以警告是可以预料的...

关于c++ - 如何避免 Windows _exec* 和 _spawn* 函数在空格处拆分参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53218984/

相关文章:

c++ - 将无符号整数输入属性传递给顶点着色器

windows - 在 Windows 上构建 openssl-sys crate 时出错

c# - VS2013专业本地64位调试MSVSMON问题

windows - 调用 tcp [::1]:6397: connectex: 无法建立连接,因为目标机器主动拒绝它

java - 如何在 Windows 中从 Java 创建非只读目录

c++ - 我可以使用 ReadProcessMemory 在 Windows 中读取进程的程序内存吗?

c++ - 关于 float 关系运算符否定的断言

c++ - 有没有一种方法可以对此进行迭代,所以我不必添加每个函数?

c++ - 信息隐藏VS封装

c++ - 结构成员地址之间的差异作为编译时间常数