我目前正在编写一个脚本来从域中的计算机收集大量信息。 正如我想显示它已经走了多远(任务可能会运行几个小时或几分钟),我想使用写入进度。 工作正常,直到我开始通过pipe道传递计算机列表,而不是“正常”的参数..
考虑这个代码:
Function Test-SomethingOnAllComputers { [CmdletBinding()] param ( [parameter( valuefrompipeline=$true, ValueFromPipelineByPropertyName=$true)] [Alias("DNSHostName") [string[]]$ComputerName ) BEGIN { ## Do some init. stuff Write-progress -PercentComplete 0 -Status "Init..." $i = 1 } PROCESS { # Do something with each computername passed in. Write-Progress -PercentComplete ($Input.Count/$i*100) -Status "Doing stuff to $ComputerName" } END { Write-Progress -PercentComplete 100 -status "Done with all objects in the pipeline. Finalizing..." # Clean up and complete the job.. Write-Progress -PercentComplete 100 - Status "Finished.." -Completed } }
用法: Get-ADComputer -Filter {Name -like "Prod*"} | Test-SomethingOnAllComputers Get-ADComputer -Filter {Name -like "Prod*"} | Test-SomethingOnAllComputers
我在这里得到两个问题/问题:
我从Get-ADComputer得到的数据是DNSHostName,而不是ComputerName(因此是别名),但是当我在PROCESS部分中引用ComputerName时,它看起来并不像它。 如果我将参数更改为DNSHostName,我会得到正确的值。 所以我猜想我只是在这里与pipe道失去了一些非常相关的东西。
Get-ADComputer -Filter { Name -like "Prod*"} | % {[string[]]$_.DNSHostName}| Test-SomethingOnAllComputers
感谢jbsmith清理这个
我无法获得传递给pipe道的对象的总数。 有没有办法做到这一点,没有循环,但整个input对象pipe道?
我会让其他人来处理你的第二个问题 – 我不知道有一个好的方法来做这件事,同时保留了很容易pipe理你的function的能力。
这似乎不是一个普遍的pipe道错误,而是一个AD Cmdlet的怪癖和从Active Directory加载的属性的填充方式。
如果你将整个计算机对象作为Object (在你的参数块中使用[Object []]进行转换),并用$_.psobject.Properties检查对象的属性,你应该在内部看到Object传递给Test-cmdlet将所有AD属性存储在一个名为Properties (名称混淆的Yay)的单个数组属性中,而将对象传递给Get-Member时看到的“属性”实际上是dynamic的,并从此数组中填充。
确保DNSHostName属性填充并在pipe道计算机对象时工作的更好方法是:
Get-ADComputer -Filter * | Select-Object -Property DNSHostName | Test-SomethingOnAllComputers
要么
Get-ADComputer -Filter * | Select-Object -Property * | Test-SomethingOnAllComputers
如果你愿意的话,这应该强制这些属性持久化,就像你的foreach例子一样。
关于Write-Progress ,问题是,当从另一个Cmdlet进行pipe道连接时,无法知道在开始处理第一个块时需要多less个对象。
如果要使用Write-Progress -PercentCompleted ,则需要先将所有计算机加载到集合中,然后运行Test- cmdlet,从而有效地Write-Progress -PercentCompleted了stream水线工作:
$Computers = Get-ADComputer -Filter * |Select-Object -ExpandProperty DNSHostName Test-SomethingOnAllComputers -ComputerName $Computers
然后在Begin块里有这样的东西:
$ComputerCount = $ComputerName.Count $i = 0
现在你应该可以做到
$i++ Write-Progress -Activity "Doing Stuff" -Status "Doing stuff to $ComputerName" -PercentComplete $($i/$ComputerCount * 100)
不要用stream水线input做这件事,因为$ComputerCount是零,只有Chuck Norris能被零除