[英]How can I execute scripts in a code created powershell shell that has Write-Host commands in it?
I have a script that I am writing which relies on functions in an imported module.我正在编写一个脚本,它依赖于导入模块中的函数。 This script takes a while due to IO (web requests) and I would like to parallize it for hundreds of thousands of iterations of a script block.
由于 IO(网络请求),这个脚本需要一段时间,我想将它并行化为脚本块的数十万次迭代。
After attempting several different methods (with little success due to restrictions with Start-Job
and other things) the current implementation relies on pre-creating a pool of powershell "shells" created via $shell = [Powershell]::Create()
.在尝试了几种不同的方法(由于
Start-Job
和其他事情的限制而收效甚微)之后,当前的实现依赖于预先创建一个通过$shell = [Powershell]::Create()
的 powershell “shell”池。
One of the module methods I have to call to bootstrap the shell (so it's in a correct state) has a call to Write-Host
in it.我必须调用其中一个模块方法来引导 shell(因此它处于正确状态)在其中调用了
Write-Host
。 When I call $shell.Invoke()
the following error occurs:当我调用
$shell.Invoke()
时,会发生以下错误:
Write-Host: A command that prompts the user failed because the host program or the command type does not support user interaction.
Write-Host:提示用户失败的命令,因为宿主程序或命令类型不支持用户交互。 Try a host program that supports user interaction, such as the Windows PowerShell Console or Windows PowerShell ISE, and remove prompt-related commands from command types that do not support user interaction, such as Windows PowerShell workflows.
Try a host program that supports user interaction, such as the Windows PowerShell Console or Windows PowerShell ISE, and remove prompt-related commands from command types that do not support user interaction, such as Windows PowerShell workflows.
Now, since the module is custom I can remove the Write-Host
calls, but that reduces user friendliness when it is run directly by end users.现在,由于模块是自定义的,我可以删除
Write-Host
调用,但这会降低最终用户直接运行时的用户友好性。 I can create a switch
parameter that does not execute Write-Host if the parameter is true, but to do that down the line is a good bit of work (feasible, but I'd rather not).如果参数为真,我可以创建一个不执行 Write-Host 的
switch
参数,但要做到这一点是一项很好的工作(可行,但我宁愿不这样做)。
Is there any way I can get Write-Host
to not error out in this scenario?有什么方法可以让
Write-Host
在这种情况下不出错? I don't actually care about the input in this scenario, I just don't want the errors.我实际上并不关心这种情况下的输入,我只是不想要错误。
The fastest way to get this to work is to define a dummy write-host
function in your script, or to simply define it in the runspace independently before running your script.让它工作的最快方法是在脚本中定义一个虚拟的
write-host
函数,或者在运行脚本之前简单地在运行空间中单独定义它。
$ps.addscript("function write-host {}").invoke()
$ps.commands.clear()
# now you can invoke scripts that use write-host
# feel free to implement a write-host that writes to a log file
Simple as that.就那么简单。 The reason you're getting that error is because programmatic invocation like that does not expect user interaction.
您收到该错误的原因是因为这样的程序调用不期望用户交互。 There are ways to make this work but it employs different APIs.
有很多方法可以使这项工作发挥作用,但它使用不同的 API。
If you need the output, you can use:如果需要输出,可以使用:
$ps.addscript("function write-host($out) {write-output $out}").invoke()
$ps.commands.clear()
尝试将您的 WMF 版本更改为 5.1 - https://www.microsoft.com/en-us/download/details.aspx?id=54616
If you want to keep using the Pipeline class, you can use the Command.MergeMyResults
[method][1].如果您想继续使用管道 class,您可以使用
Command.MergeMyResults
[方法][1]。 For example, to redirect all type of streams to pipeline output:例如,要将所有类型的流重定向到管道 output:
private string RunScript(string scriptText) {
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript("Write-Host Test");
pipeline.Commands[pipeline.Commands.Count-1]
.MergeMyResults(PipelineResultTypes.All, PipelineResultTypes.Output)
Collection < PSObject > results = pipeline.Invoke();
runspace.Close();
foreach(PSObject obj in results) {
Console.WriteLine(obj.ToString());
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.