有没有将 PowerShell v3 脚本的输出强制为表格形式?我的脚本以线性形式输出服务列表,即使输出对象中只有 6 个字段(get-process 以表格形式输出 8 个字段)。这是我的代码:
<#
.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
}
}
Run Code Online (Sandbox Code Playgroud)
当一个或多个对象冒泡到主机时,PowerShell 会查看该对象具有的属性数量。
如果一个对象的类型可以解析为相应的Format.ps1xml文件(我们将在一分钟内回到这个),将使用该文档中描述的格式约定 - 否则,这取决于对象具有的属性数量。
如果一个对象的属性少于 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
Run Code Online (Sandbox Code Playgroud)
如果一个对象有更多的属性,它默认为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
Run Code Online (Sandbox Code Playgroud)
现在,从Get-Service或Get-Processcmdlet返回的对象似乎格式化为一个很好的、上下文相关的、多于 5 列的表的原因是 PowerShell 能够为它们找到特定于类型的格式化文档。
这些格式化文件都位于 PowerShell 安装目录中,您可以使用以下命令找到默认文件:
Get-ChildItem $PSHome *.Format.ps1xml
Run Code Online (Sandbox Code Playgroud)
看看Get-Help about_Format.ps1xml您是否要创建自己的格式文件。
PowerShell 在对象类型和定义的格式视图之间建立链接的方式是检查隐藏pstypenames属性:
PS C:\> $obj.pstypenames
System.Management.Automation.PSCustomObject
System.Object
Run Code Online (Sandbox Code Playgroud)
PowerShell 只是钻取这个祖先的类型列表,看看它是否有对应的类型的格式视图。
这意味着您可以欺骗 PowerShell 将对象格式化为另一种类型,而无需实际干预底层 .NET 类型系统。
为了说明这一点,让我们创建一个虚假的服务控制器——一个看起来像是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
Run Code Online (Sandbox Code Playgroud)
如上所述,PowerShell 显示了 的输出,Format-List因为我们psobject有 5 个属性。
现在,让我们尝试注入一个类型名称:
PS C:\> $FauxService.pstypenames.Insert(0,"System.ServiceProcess.ServiceController")
PS C:\> $FauxService
Status Name DisplayName
------ ---- -----------
Faking FakeService3000 TrustworthyService
Run Code Online (Sandbox Code Playgroud)
瞧!
| 归档时间: |
|
| 查看次数: |
1118 次 |
| 最近记录: |