c++ - 代码适用于 CLR 项目但不适用于 Win32

标签 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, 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/

相关文章:

javascript - 如果检测到错误,则禁用从 typescript 生成 JavaScript

actionscript-3 - 在 flex 中调用 Win32 API 来设置 Window Display Affinity

c++ - 如何构造字符数组

C++:用于高效插入和检索自定义数据的数据结构

c++ - std::function 如何使指向成员函数的指针起作用?

java.lang.UnsatisfiedLinkError : Error looking up function 'GetModuleFileNameEx' 错误

c++ - 为什么父窗口没有收到来自子组合框的通知?

c++ - 在 DLL 中线程化,其中 DLL 必须在子线程完成之前返回

visual-studio - 在VS2015中调试Powershell无法可视化XML对象

c# - 我可以在 Visual Studio 命令行参数中使用用户的环境变量吗?