例如,我想在屏幕上显示输出并将其复制到剪贴板。
dir | tee con | clip
由于con
在PowerShell文件系统中无法识别为控制台,因此上述功能无效。
也可能出现以下情况,
Get-LongLongOutput |
tee con | # Monitor the intermediate output
Process-LongLongInput |
Process-LongLongInput2 |
.....
答案 0 :(得分:2)
您将要收集管道数据并将其单独发送到剪贴板,如@Mathias R. Jessen所建议的那样。这样做的原因是Clip
实际上是一个外部应用程序,而不是内置在PowerShell中的东西,除了将信息复制到剪贴板之外没有任何“输出”的情况下消耗传递给它的信息。
dir | tee -var data
$data | clip
这(由@Mathias R. Jessen建议)将显示您的内容,并将其复制到剪贴板。
或者,您可以在ForEach循环中使用Write-Host
将内容写入屏幕,并且仍然能够将它们传递到管道上clip
,但格式化它可能是不受欢迎的,大多数人建议尽可能避免使用write-host
。如果你想这样做,你可以使用类似的东西:
dir | ForEach-Object{
Write-Host $_
$_} | Clip
答案 1 :(得分:2)
我认为TheMadTechnician对你想做的事情有正确的想法。正如您所指出的,Write-Host
与让主机显示对象不同。您要查找的cmdlet是Out-Host
。所以修改TMT的建议:
Get-Process | ForEach-Object {
$_ | Out-Host
$_
} | clip
这样做的缺点是它会打印每个对象的标题,而不是组合它们,但我相信这是不可避免的,因为主机能够在不停止管道的情况下做到这一点的唯一方法是在最后它的。
这是一个你可以自己打电话的功能:
# Don't use this terrible name
Function MyTeeFine {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline=$true)]
$object
)
process {
$object | Out-Host
$object
}
}
# In action:
Get-Process | MyTeeFine | clip
Get-Process | MyTeeFine | ForEach-Object { Start-Sleep -Seconds 1 }
# ^ proof that the pipeline is still working object by object,
# displaying to host before each delay
答案 2 :(得分:1)
对于这种情况,我更喜欢使用自己的Invoke-Pipeline
cmdlet:
Add-Type -TypeDefinition @‘
using System;
using System.Management.Automation;
[Cmdlet(VerbsLifecycle.Invoke,"Pipeline")]
public sealed class InvokePipelineCmdlet:PSCmdlet,IDisposable {
private static readonly Type StopUpstreamCommandsExceptionType=typeof(FlowControlException).Assembly.GetType("System.Management.Automation.StopUpstreamCommandsException");
private ScriptBlock[] scriptBlocks;
private PSObject inputObject;
private int count;
private SteppablePipeline[] steppablePipelines;
public InvokePipelineCmdlet() { }
[Parameter(Mandatory=true,ValueFromRemainingArguments=true)]
public ScriptBlock[] Pipeline {
set {
scriptBlocks=value;
}
}
[Parameter(ValueFromPipeline=true)]
public PSObject InputObject {
get {
return null;
}
set {
inputObject=value;
}
}
protected override void BeginProcessing() {
count=scriptBlocks.Length;
steppablePipelines=new SteppablePipeline[count];
for(int i=0;i<count;++i) {
steppablePipelines[i]=scriptBlocks[i].GetSteppablePipeline(MyInvocation.CommandOrigin);
}
ProcessPipelineStep(PipelineStep.Begin);
}
protected override void ProcessRecord() {
ProcessPipelineStep(MyInvocation.ExpectingInput?PipelineStep.ProcessInput:PipelineStep.Process);
}
protected override void EndProcessing() {
ProcessPipelineStep(PipelineStep.End);
Dispose();
}
public void Dispose() {
if(steppablePipelines!=null) {
foreach(SteppablePipeline steppablePipeline in steppablePipelines) {
if(steppablePipeline!=null) {
steppablePipeline.Dispose();
}
}
steppablePipelines=null;
}
}
private void ProcessPipelineStep(PipelineStep step) {
if(steppablePipelines!=null) {
for(int i=0;i<steppablePipelines.Length;++i) {
if(steppablePipelines[i]!=null) {
try {
switch(step) {
case PipelineStep.Begin:
steppablePipelines[i].Begin(this);
break;
case PipelineStep.Process:
steppablePipelines[i].Process();
break;
case PipelineStep.ProcessInput:
steppablePipelines[i].Process(inputObject);
break;
case PipelineStep.End:
steppablePipelines[i].End();
break;
}
} catch(FlowControlException fce) {
if(StopUpstreamCommandsExceptionType.IsInstanceOfType(fce)) {
steppablePipelines[i]=null;
if(--count==0) {
EndProcessing();
throw (FlowControlException)Activator.CreateInstance(StopUpstreamCommandsExceptionType,this);
}
} else {
throw;
}
}
}
}
}
}
private enum PipelineStep {
Begin,
Process,
ProcessInput,
End
}
}
’@ -PassThru|Select-Object -First 1 -ExpandProperty Assembly|Import-Module
它允许将单个输入同时传递给多个命令,如下所示:
dir|Invoke-Pipeline {clip} <# copy to clipboard #> `
{Out-File out.txt} <# save to file #> `
{Out-File outall.txt -Append} <# append to some other file #> `
{Out-Host} <# display on console #>
使用您的示例方案,您可以执行以下操作:
Get-LongLongOutput |
Invoke-Pipeline {Out-Host} {Process-LongLongInput} |
Process-LongLongInput2 |
.....
或者你可以这样做:
Get-LongLongOutput |
Invoke-Pipeline {Out-GridView} {Process-LongLongInput} |
Invoke-Pipeline {Out-GridView} {Process-LongLongInput2} |
.....
因此您可以监控多个点的输出。