我在努力奔跑
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; }\"");
它似乎在我的纯 CLR 应用程序中工作正常,但当我尝试在 Win32 应用程序中执行它时。我收到回复说
foreach-object{ is not recognized as a batch command
我不确定为什么管道在一个而不是另一个中破坏了字符串,但我希望它能在我的 Win32 应用程序中工作,这样我就可以链接必要的 DLL。
最佳答案
作为documentation状态:
The _popen function creates a pipe and asynchronously executes a spawned copy of the command processor with the specified string command.
因此,在这种情况下,您的 Win32 代码实际上启动了一个 cmd.exe
的实例。然后将您的字符串传递给它。
|
对cmd.exe
有特殊意义.因为涉及到将命令输入 cmd.exe
的管道, 它实际上最终解释了 |
作为command redirection operator (即使它在您输入字符串的引号内)。它获取左侧命令的输出并将其发送到右侧命令的输入。因此,在您的情况下,您实际上是在尝试执行命令:
powershell.exe -Command "$computers = Get-WsusComputer -All; $computers
并将其输出发送到此命令的输入:
foreach-object{ Write-Output $_.FullDomainName; }"
这就是为什么您会收到有关 foreach-object{
的错误的原因是一个未知的命令。
要执行您正在尝试的操作,请尝试转义 |
字符,以便在解析期间将其视为普通字符:
exec("powershell.exe -Command \"$computers = Get-WsusComputer -All; $computers ^| foreach-object{ Write-Output $_.FullDomainName; }\"");
查看此页面了解更多详情:
Syntax : Escape Characters, Delimiters and Quotes
Escape Character
^ Escape character.
Adding the escape character before a command symbol allows it to be treated as ordinary text. When piping or redirecting any of these characters you should prefix with the escape character:
& \ < > ^ |
e.g. ^\ ^& ^| ^> ^< ^^
或者,考虑使用 CreateProcess()
直接代替 _popen()
.您可以运行 cmd.exe
使用您的命令字符串作为命令行参数而不是管道输入,那么您不必转义 |
引号内的字符(但你必须自己转义额外的引号):
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()), ...);
要读取输出,您可以告诉 CreateProcess()
重定向启动进程的 STDOUT
来自 CreatePipe()
的匿名管道句柄然后你可以使用 ReadFile()
读取它:
Creating a Child Process with Redirected Input and Output
至于为什么在 CLR 中一切正常,我不知道。我只能推测 CLR 可能使用与 cmd.exe
不同的命令处理器。 , 它以不同的方式解析您的命令字符串。
关于c++ - 代码适用于 CLR 项目但不适用于 Win32,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34425167/