代码适用于 CLR 项目,但不适用于 Win32
Posted
技术标签:
【中文标题】代码适用于 CLR 项目,但不适用于 Win32【英文标题】:Code works in CLR project but not Win32 【发布时间】:2015-12-22 22:02:31 【问题描述】:我正在尝试运行
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。
【问题讨论】:
你能提供这个函数的示例调用吗? @andlabs 我有字符串 exec(...) 函数,我从 main 调用最后一行。 domainNameList = exec("powershell.exe -Command... 对,因为我认为该错误来自 powershell 本身...您是否使用上面在exec()
的 CLR 实现中发布的完全相同的代码?还是使用 exec()
的不同实现?
【参考方案1】:
正如documentation 所说:
_popen 函数创建一个管道并使用指定的字符串 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.
在命令符号前添加转义字符可以将其视为普通文本。 当管道或重定向任何这些字符时,您应该使用转义字符作为前缀:
& \ < > ^ |
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
不同,并且它以不同的方式解析您的命令字符串。
【讨论】:
以上是关于代码适用于 CLR 项目,但不适用于 Win32的主要内容,如果未能解决你的问题,请参考以下文章
Pygame:这个 spritesheet 代码适用于另一个项目,但不适用于这个项目。为啥?
代码适用于嵌入式Apache Tomcat 8但不适用于9。有什么改变?
PayPal IPN 适用于单个购物车项目,但不适用于多个购物车项目