虽然 write-output 在类的方法中不起作用,但如果该方法返回一个然后在外部执行的脚本块,它确实起作用,如下所示:
#Cmdlet you can't edit that outputs whilst running
function foo {
write-output "Beginning complex operation!";
start-sleep 2;
write-output "Important information you would rather not have to wait for!";
start-sleep 2;
write-output "Operation finished!";
}
class IsClass{
static [ScriptBlock]bar(){
#create a ScriptBlock that the must be executed outside
return { foo };
}
}
& $([IsClass]::bar());
<#Output:
Beginning complex operation!
[two second wait]
Important information you would rather not have to wait for!
[two second wait]
Operation finished!
#>
这是一个相对 hacky 的解决方案。不过,据我所知,这是在 cmdlet 仍在运行时编写在静态方法中调用的 cmdlet 输出的唯一方法。write-host
如果您无权访问您在类中调用的 cmdlet,则不能在方法调用的 cmdlet 内部使用。
不使用脚本块的示例:
#Cmdlet you can't edit that outputs whilst running
function foo {
write-output "Beginning complex operation!";
start-sleep 2;
write-output "Important information you would rather not have to wait for!";
start-sleep 2;
write-output "Operation finished!";
}
#Class that uses the mentioned cmdlet
class IsClass{
static [void]bar(){
#Directly invoke the method
write-host $(foo);
}
}
[IsClass]::bar();
<#Output:
[Awkward 4 second pause]
Beginning complex operation! Important information you would rather not have to wait for! Operation finished!
还值得注意的是,第二种方法导致所有输出都显示在一行上。
您可能希望实际使用它的一个场景是,如果您正在编写一个使用命令行安装工具的脚本。安装使用您无法控制的 cmdlet,并且需要几分钟才能完成(例如使用巧克力安装软件)。这意味着如果 cmdlet 的进度发生更改(例如继续安装软件的依赖项),它无法将更改写入控制台,直到完全安装完成,从而使用户对当前正在发生的事情一无所知。
更新:在撰写本文时,我还遇到了许多关于脚本块内范围使用的问题,因为它们不共享创建它们的上下文的范围,只共享执行它们的范围。这在很大程度上使我在这里提到的许多内容无效,因为这意味着您不能引用该类的属性。
更新 2:除非您使用 GetNewClosure!
static [ScriptBlock]bar(){
#create a ScriptBlock that the must be executed outside
$that = $this;
return { $that.ClassVariable }.GetNewClosure();
}