如何在C / C ++中使用Windows下包含空格的路径名调用popen()?

时间:2009-10-12 21:39:20

标签: c++ c popen quoting

我正在尝试使用mingw这样调用popen():

#define RUN_COMMAND "\"C:\\Program Files\\CA\\BrightStor ARCserve Backup\\ca_qmgr.exe\" \"-list\""
int main() {
    outputPointer = popen(RUN_COMMAND, "r");
    ...
}

但我无法让它发挥作用。 我认为这是一个引用噩梦......

5 个答案:

答案 0 :(得分:6)

这个解决方案的灵感来自Kaz的回复

事实证明,popen函数剥离了整个事物的引号,例如。 "C:/Program Files"变为C:/Program Files"Ab cd.exe" "ef gh"变为ab cd" "ef gh。你可以通过在整个事物周围添加引号来解决这个问题,例如。 ""ab cd.exe" "ef gh""按预期变为"ab cd.exe" "ef gh"

答案 1 :(得分:4)

看看What is the equivalent to posix popen in the win32 api。很久以前,我放弃了在Windows下使用_popen()的尝试。纯WIN32解决方案执行得更加可靠。

如果mingw将您的参数传递给sh -c而不是cmd.exe /c,那么您可能希望将这些反斜杠更改为正斜杠。像下面这样的东西可以解决问题。

"\"C:/Program Files/CA/BrightStor ARCserve Backup/ca_qmgr.exe\" -list"

答案 2 :(得分:4)

这个问题证明是可以解决的。 (虽然,与Windows中的大多数内容一样,不是100%)。

popen函数打开一个系统命令,这意味着几乎可以肯定只是取字符串参数并将其插入cmd.exe /c <here>

在Windows命令提示符下使用cmd.exe /c进行一些交互式实验后,我们找到了一种运行路径名中包含空格的程序的方法。

天真尝试引号,不,

C:\>cmd /c "foo bar"
'foo' is not recognized as an internal or external command,
operable program or batch file.

我们可以用旋律来逃避引号吗?

C:\>cmd /c ^"foo bar^"
'foo' is not recognized [...]

空间怎么样?

C:\>cmd /c foo^ bar
'foo' is not recognized [...]

引用空间怎么样?

C:\>cmd /c foo" "bar
'foo" "bar' is not recognized as an internal or external command,
operable program or batch file.

啊哈!这很有希望!它真的试图运行foo bar吗?我们来看看:

C:\>copy con "foo bar.bat"
echo i am foo bar
^Z
        1 file(s) copied.

C:\>cmd /c foo" "bar

C:\>echo i am foo bar
i am foo bar

啊哈!我们的批处理文件名称中包含空格!

所以,现在我在Visual Studio 2008中尝试以下内容:

#include <stdio.h>

int main()
{
    FILE *in = _popen("C:\\Program\" \"Files\\Internet\" \"Explorer\\iexplore.exe", "r");

    if (in) {
        char line[200];
        printf("successfully opened!\n");
        if (fgets(line, 200, in))
            fputs(line, stdout);
        _pclose(in);
    }

    return 0;
}

它启动Internet Explorer就好了,然后在fgets中阻塞,直到你退出浏览器(由于没有输出而无法读取任何内容)。

它在使用Microsoft C运行时库的MinGW中工作;事实上,我提出了这个解决方案,用于修复使用MinGW移植到Windows的编程语言库中的错误。

注意事项:

这个转义技巧不会逃避前导空格。它似乎适用于尾随空格。两者都不是问题;我们通常不会看到以空格开头或结尾的路径名,更不用说可执行路径名了。

我也找不到一种方法来逃避可能作为路径的一部分出现的嵌入式双引号,同时处理空格。在创建像C:\Program Files\Bob's so-called "editor"\bedit.exe之类的东西之前,人们应该三思而后行。

答案 3 :(得分:1)

我刚刚面对这个问题,并尝试了Kaz的解决方案但没有成功。我解决它的方法只是更改目录,执行_popen而不使用可执行文件的路径,然后更改回原始目录。

char cwd[MAX_PATH];
_getcwd(cwd, MAX_PATH);

if (_chdir("C:\\Program Files\\CA\\BrightStor ARCserve Backup") >= 0)
{
    outputPointer = _popen("ca_qmgr.exe \"-list\"", "r");
    _chdir(cwd);
}

答案 4 :(得分:-1)

根据popen的手册页:

  

命令参数是指向a的指针   以null结尾的字符串,包含   shell命令行。这个命令是   使用-c标志传递给/ bin / sh;   解释,如果有的话,是   由shell执行。

所以你想要的是转义sh的字符串来解析。 您不需要转义-list参数,并且可以尝试转义空格而不是引用整个程序名称。我这里没有Windows系统进行测试,但我建议

#define RUN_COMMAND "C:\\Program Files\\CA\\BrightStor\\ ARCserve\\ Backup\\ca_qmgr.exe -list"
int main() {
    outputPointer = popen(RUN_COMMAND, "r");
    ...
}