简体   繁体   English

代码适用于CLR项目,但不适用于Win32

[英]Code works in CLR project but not Win32

I am trying to run 我正在尝试跑步

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; }\"");

It seems to work fine in my pure CLR application but when I try to do it in a Win32 Application. 在我的纯CLR应用程序中,它似乎工作正常,但是当我尝试在Win32应用程序中进行此操作时。 I get a response saying that 我得到回应说

foreach-object{ is not recognized as a batch command

I am not sure why the pipe is breaking the string in one but not the other but I would like for this to work in my Win32 application so I can link necessary DLLs. 我不确定为什么管道在其中一个而不是另一个中破坏了字符串,但是我希望在我的Win32应用程序中使用它,以便可以链接必要的DLL。

As the documentation states: 文档所述:

The _popen function creates a pipe and asynchronously executes a spawned copy of the command processor with the specified string command . _popen函数创建一个管道,并使用指定的字符串命令异步执行命令处理器的衍生副本。

So, in this case, your Win32 code is actually launching an instance of cmd.exe and then piping your string to it. 因此,在这种情况下,您的Win32代码实际上是启动cmd.exe的实例,然后将字符串传递到该实例。

| has special meaning to cmd.exe . cmd.exe具有特殊含义。 Because piping is involved to get the command into cmd.exe , it actually ends up interpreting the | 因为涉及到将命令传递到cmd.exe管道,所以实际上最终解释了| as a command redirection operator (even though it is inside of quotes in your input string). 作为命令重定向运算符 (即使它在输入字符串中的引号内)。 It takes the output from the command on the left side and sends it to the input of the command on the right side. 它从左侧的命令获取输出,然后将其发送到右侧的命令输入。 So, in your case, you are actually trying to execute the command: 因此,在您的情况下,您实际上是在尝试执行以下命令:

powershell.exe -Command "$computers = Get-WsusComputer -All; $computers

and send its output to the input of this command: 并将其输出发送到此命令的输入:

foreach-object{ Write-Output $_.FullDomainName; }"

And that is why you get an error about foreach-object{ being an unknown command. 这就是为什么您会收到关于foreach-object{是未知命令的错误的原因。

To do what you are attempting, try escaping the | 要执行您要尝试的操作,请尝试转义| character so it is treated as a normal character during parsing: 字符,因此在解析期间将其视为普通字符:

exec("powershell.exe -Command \"$computers = Get-WsusComputer -All; $computers ^| foreach-object{ Write-Output $_.FullDomainName; }\"");

See this page for more details: 请参阅此页面以获取更多详细信息:

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: & \\ < > ^ | 当管道或重定向这些字符中的任何一个时,应在前缀前面加上转义字符: & \\ < > ^ |

  eg ^\\ ^& ^| ^> ^< ^^ 

Alternatively, consider using CreateProcess() directly instead of _popen() . 或者,考虑直接使用CreateProcess()而不是_popen() You can run cmd.exe with your command string as a command-line parameter instead of piped input, then you don't have to escape the | 您可以使用命令字符串作为命令行参数(而不是管道输入)运行cmd.exe ,这样就不必转义| character inside of quotations (but you would have to escape the extra quotes themselves): 引号内的字符(但您必须自己转义多余的引号):

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()), ...);

To read the output, you can tell CreateProcess() to redirect the launched process's STDOUT handle to an anonymous pipe from CreatePipe() and then you can read from it using ReadFile() : 要读取输出,可以告诉CreateProcess()将启动的进程的STDOUT句柄从CreatePipe()重定向到匿名管道,然后可以使用ReadFile()从中读取:

Creating a Child Process with Redirected Input and Output 创建具有重定向输入和输出的子进程

As to why everything works correctly in CLR, I do not know. 至于为什么一切都可以在CLR中正常工作,我不知道。 I can only surmise that maybe CLR is using a different command processor than cmd.exe , and it is parsing your command string differently. 我只能推测,也许CLR使用的命令处理器不同于cmd.exe ,并且它解析命令字符串的方式也有所不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM