C++ 代码可以在CLR项目中工作,但不能在Win32中工作

C++ 代码可以在CLR项目中工作,但不能在Win32中工作,c++,visual-studio,winapi,C++,Visual Studio,Winapi,我想跑 std::string exec(const char* cmd) { std::shared_ptr<FILE> pipe(_popen(cmd, "r"), _pclose); if (!pipe) return "ERROR"; char buffer[128]; std::string result = ""; while (!feof(pipe.get())) { if (fgets(buffer, 128,

我想跑

std::string exec(const char* cmd) {
    std::shared_ptr<FILE> pipe(_popen(cmd, "r"), _pclose);
    if (!pipe) return "ERROR";
    char buffer[128];
    std::string result = "";
    while (!feof(pipe.get())) {
         if (fgets(buffer, 128, pipe.get()) != NULL)
            result += buffer;
    }
    return result;
}

string domainNameList = exec("powershell.exe -Command \"$computers = Get-WsusComputer -All; $computers | foreach-object{ Write-Output $_.FullDomainName; }\"");
我不知道为什么管道会在其中一个断开字符串,而在另一个断开字符串,但我希望在我的Win32应用程序中能够实现这一点,以便我可以链接必要的DLL

如缔约国所述:

\u popen函数创建一个管道,并使用指定的字符串命令异步执行生成的命令处理器副本

因此,在本例中,Win32代码实际上启动了
cmd.exe
的一个实例,然后通过管道将字符串连接到该实例

|
cmd.exe
有特殊意义。由于将命令放入
cmd.exe
,需要使用管道,因此它实际上会将
|
解释为一个字符串(即使它位于输入字符串中的引号内)。它获取左侧命令的输出,并将其发送到右侧命令的输入。因此,在您的情况下,您实际上是在尝试执行命令:

powershell.exe -Command "$computers = Get-WsusComputer -All; $computers
并将其输出发送到此命令的输入:

foreach-object{ Write-Output $_.FullDomainName; }"
这就是为什么您会得到一个关于
foreach对象{
是未知命令的错误

要执行您正在尝试的操作,请尝试转义
|
字符,以便在解析期间将其视为普通字符:

exec("powershell.exe -Command \"$computers = Get-WsusComputer -All; $computers ^| foreach-object{ Write-Output $_.FullDomainName; }\"");
有关更多详细信息,请参阅本页:

转义字符

^  Escape character.
在命令符号之前添加转义字符可以将其视为普通文本。 当管道传输或重定向这些字符时,应以转义字符作为前缀:
&\<>^ |

 e.g.  ^\  ^&  ^|  ^>  ^<  ^^ 
要读取输出,您可以告诉
CreateProcess()
CreatePipe()
将启动进程的
STDOUT
句柄重定向到匿名管道,然后使用
ReadFile()
从中读取:


至于为什么在CLR中一切都正常工作,我不知道。我只能猜测,可能CLR使用的是与
cmd.exe
不同的命令处理器,它以不同的方式解析您的命令字符串。

您能提供此函数的示例调用吗?@andlabs我有字符串exec(…)函数,我用最后一行从main调用。domainNameList=exec(“powershell.exe-Command…对,因为我认为错误来自powershell本身…您使用的是与上面发布的
exec()
的CLR实现相同的代码,还是使用了不同的
exec()
实现?
 e.g.  ^\  ^&  ^|  ^>  ^<  ^^ 
std::basic_string<TCHAR> cmd = TEXT("cmd.exe /C \"powershell.exe -Command \"\"$computers = Get-WsusComputer -All; $computers | foreach-object{ Write-Output $_.FullDomainName; }\"\"\"");
CreateProcess(NULL, const_cast<TCHAR*>(cmd.c_str()), ...);