以表格forms强制Powershell脚本的输出

是否有强制输出表格forms的PowerShell v3脚本? 即使输出对象中只有6个字段(表格forms的get-process输出8个字段),我的脚本仍然以线性forms输出服务列表。 这是我的代码:

<# .SYNOPSIS Gets a list of services on a given computer that are supposed to automatically start but are not currently running. .PARAMETER ComputerName The computer name(s) to retrieve the info from. .PARAMETER IgnoreList The path and filename of a text file containing a list of service names to ignore. This file has to list actual service names and not display names. Defaults to "StoppedServices-Ignore.txt" in the current directory. .PARAMETER StartServices Optional switch that when specified will cause this function to attempt to start all of the services it finds stopped. .EXAMPLE Get-StoppedServices -ComputerName Computer01 -IgnoreList '.\IgnoredServices.txt' -StartServices .EXAMPLE Get-StoppedServices –ComputerName Computer01,Computer02,Computer03 .EXAMPLE "Computer01" | Get-StoppedServices .EXAMPLE Get-StoppedServices –ComputerName (Get-Content ComputerList.txt) .EXAMPLE Get-Content ComputerList.txt | Get-StoppedServices -IgnoreList '.\IgnoredServices.txt' -StartServices #> Function Get-StoppedServices { [CmdletBinding()] param( [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [String[]]$ComputerName, [string]$IgnoreList, [switch]$StartServices ) PROCESS { # Load the list of services to ignore (if specified). if ($IgnoreList) { if (Test-Path $IgnoreList) { $ignore = import-csv -header Service $IgnoreList Write-Verbose "Ignoring the following services:" Write-Verbose $ignore.ToString() } else { Write-Warning "Could not find ignore list $IgnoreList." } } # Get a list of stopped services that are set to run automatically (ie: that should be running) foreach ($c in $ComputerName) { Write-Verbose "Getting services from $($c.Name)" if (Test-Connection -ComputerName $c -Count 1 -Quiet) { Try { $serv += get-wmiobject -query "Select __Server,Name,DisplayName,State,StartMode,ExitCode,Status FROM Win32_Service WHERE StartMode='Auto' AND State!='Running'" -computername $c -erroraction stop } catch { Write-Warning "Could not get service list from $($c)" } } } # Create the resulting list of services by removing any that are in the ignore list. $results = @() foreach ($s in $serv) { Write-Verbose "Checking if $($s.name) in ignore list." if ($ignore -match $s.name) { Write-Verbose " *Service in ignore list." } else { Write-Verbose " Service OK." $obj = New-Object -typename PSObject $obj | Add-Member -membertype NoteProperty -name ComputerName -value ($s.PSComputerName) -passthru | Add-Member -membertype NoteProperty -name ServiceName -value ($s.Name) -passthru | Add-Member -membertype NoteProperty -name DisplayName -value ($s.DisplayName) -passthru | Add-Member -membertype NoteProperty -name Status -value ($s.Status) -passthru | Add-Member -membertype NoteProperty -name State -value ($s.State) -passthru | Add-Member -membertype NoteProperty -name ExitCode -value ($s.ExitCode) $results += $obj } } # Try and start each of the stopped services that hasn't been ignored. if ($StartServices) { foreach ($s in $results) { Write-Verbose "Starting '$($s.DisplayName)' ($($s.name)) on '$($s.ComputerName)..." Try { Get-Service -Name $s.name -ComputerName $s.ComputerName -erroraction stop | Start-service -erroraction stop } Catch { Write-Warning "Could not start service $($s.name) on $($s.ComputerName)." } } } # Output the list of filtered services to the pipeline. write-output $results } } 

当一个或多个对象冒泡到主机时,PowerShell将查看该对象所具有的属性数量。

如果一个对象的types可以被parsing为相应的Format.ps1xml文件(我们将在一分钟后回到这个文件),那么将使用该文档中描述的格式约定 – 否则,这取决于对象的属性数量。


如果对象的属性less于5个,则默认使用Format-Table作为输出格式:

 PS C:\> New-Object psobject -Property ([ordered]@{PropA=1;PropB=2;PropC=3;PropD=4}) PropA PropB PropC PropD ----- ----- ----- ----- 1 2 3 4 

如果一个对象有更多的属性,它默认为Format-List (这就是你所经历的):

 PS C:\> New-Object psobject -Property ([ordered]@{PropA=1;PropB=2;PropC=3;PropD=4;PropE=5}) PropA : 1 PropB : 2 PropC : 3 PropD : 4 PropE : 5 

现在,从Get-ServiceGet-Process cmdlet返回的对象似乎被格式化为一个好的,上下文相关的,多于5列的表的原因是,PowerShell能够find一个特定于types的格式化文档为他们。

这些格式文件都位于PowerShell安装目录中,您可以通过以下方式find默认的文件:

 Get-ChildItem $PSHome *.Format.ps1xml 

如果您想创build自己的格式文件,请参阅Get-Help about_Format.ps1xml


PowerShellbuild立对象types和定义格式视图之间的链接的方式是检查隐藏的pstypenames属性:

 PS C:\> $obj.pstypenames System.Management.Automation.PSCustomObject System.Object 

PowerShell只是通过这个祖先的types列表来查看它是否有相应的格式化视图。

这意味着你可以欺骗PowerShell来格式化一个对象,就好像它是另一种types一样,而不需要真正干涉底层的.NETtypes系统。

为了说明这一点,我们来创build一个人造服务控制器 – 一个看起来像Get-Service可能返回的对象,但实际上并不是:

 PS C:\> $FauxService = New-Object psobject -Property @{ >>> "Name" = "FakeService3000" >>> "Status" = "Faking" >>> "DisplayName" = "TrustworthyService" >>> "TrueName" = "Really a fake" >>> "Author"="Clever Genius" >>> } PS C:\> $FauxService Status : Faking Name : FakeService3000 Author : Clever Genius DisplayName : TrustworthyService TrueName : Really a fake 

如上所述,PowerShell显示Format-List的输出,因为我们的psobject有5个属性。

现在,我们尝试注入一个types名称:

 PS C:\> $FauxService.pstypenames.Insert(0,"System.ServiceProcess.ServiceController") PS C:\> $FauxService Status Name DisplayName ------ ---- ----------- Faking FakeService3000 TrustworthyService 

瞧!