我有一个停止和启动服务的脚本。但是,我遇到了一些服务未正确停止的问题,需要用户干预服务器。在脚本的启动服务部分运行之前,我使用if
语句检查列出的所有服务是否已停止,如果没有,脚本将弹出警报。
下面是执行此操作的脚本片段。我正在尝试列出弹出窗口中的服务状态和启动类型但由于某种原因我没有得到列表返回。使用当前注释掉的行我将返回服务名称,但它是一个字符串。
#$RunningServices = (Get-Service -ComputerName $targetServer | Where-Object {($_.Name -like '*serviceAgroup*'-or $_.Name -like '*serviceBgroup*') -and $_.Status -eq "Running"})
$RunningServices = (Get-Service -ComputerName $targetServer |
Where-Object {($_.Name -like '*serviceAgroup*' -or $_.Name -like '*serviceBgroup*') -and $_.Status -eq "Running"}) |
select DisplayName, Status, StartType |
sort DisplayName;
Format-Table;
$pop = New-Object -ComObject WScript.Shell
$pop.Popup("Log onto $targetserver and stop Running serviceAgroup and serviceBgroup.`r`n$RunningServices", 0, "Services have not stopped!", 1)
答案 0 :(得分:1)
您为变量$RunningServices
分配的输出结束于sort DisplayName
。输出未传递到Format-Table
。如果将带有对象(或对象数组)的变量放入字符串中,则对象将扩展为各自的字符串表示形式。
<强>演示:强>
PS C:\> $s = Get-Service | Select-Object -First 3 PS C:\> $s Status Name DisplayName ------ ---- ----------- Stopped AeLookupSvc Application Experience Stopped ALG Application Layer Gateway Service Stopped AppIDSvc Application Identity PS C:\> "$s" AeLookupSvc ALG AppIDSvc PS C:\> _
对于服务,字符串表示是Name
属性的值,如上所示。选择属性(没有属性Name
)后,结果应为空字符串:
PS C:\> $s = Get-Service | Select-Object DisplayName,Status,StartType -First 3 PS C:\> $s DisplayName Status StartType ----------- ------ --------- Application Experience Stopped Manual Application Layer Gateway Service Stopped Manual Application Identity Stopped Manual PS C:\> "$s" PS C:\> _
要将表格输出作为字符串输入,您必须不仅通过Format-Table
,而且还通过Out-String
管道对象列表。这是因为Format-Table
不生成字符串输出,而是生成格式对象列表。 Out-String
将这些转换为实际的字符串输出。
PS C:\> $s1 = $s | Format-Table PS C:\> "$s1" Microsoft.PowerShell.Commands.Internal.Format.FormatStartData Microsoft.PowerShe ll.Commands.Internal.Format.GroupStartData Microsoft.PowerShell.Commands.Interna l.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEnt ryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.P owerShell.Commands.Internal.Format.GroupEndData Microsoft.PowerShell.Commands.In ternal.Format.FormatEndData PS C:\> $s2 = $s | Format-Table | Out-String PS C:\> "$s2" DisplayName Status StartType ----------- ------ --------- Application Experience Stopped Manual Application Layer Gateway Service Stopped Manual Application Identity Stopped Manual
但即便如此,您的输出可能不会达到您的预期。与PowerShell控制台GUI对话框不同,使用比例字体,这意味着并非所有字符都具有相同的宽度。因为在使用等宽字体时,使用等宽字体看起来像正确的表格的东西很可能在使用比例字体时看起来相当变形。在GUI对话框中输出上述字符串,如下所示:
PS C:\> Add-Type -Assembly 'System.Windows.Forms' PS C:\> [Windows.Forms.Messagebox]::Show($s2)
应该给你这样的东西:
为了获得至少有些可呈现的结果,我建议使用自定义格式字符串:
PS C:\> $s3 = $s | ForEach-Object {"{0}`t{1}`t{2}" -f $_.StartType,$_.Status,$_.DisplayName} | Out-String PS C:\> [Windows.Forms.Messagebox]::Show($s3)
这应该会产生更多可见的输出:
以上内容利用了StartType
和Status
属性的值不会变化太大的事实,因此可以通过分离值来合理地对齐列使用制表符。如果您必须在左侧具有服务名称,则格式化会变得复杂得多,因为您需要根据名称中字符的数量和宽度插入可变数量的选项卡。我打算把它作为读者的练习。
底线:将您的代码更改为以下内容:
Add-Type -Assembly 'System.Windows.Forms'
$svc = Get-Service -ComputerName $targetServer | Where-Object {
($_.Name -like '*serviceAgroup*' -or $_.Name -like '*serviceBgroup*') -and
$_.Status -eq 'Running'
} | Select-Object DisplayName,Status,StartType
$str = $svc | Sort-Object DisplayName | ForEach-Object {
"{0}`t{1}`t{2}" -f $_.StartType,$_.Status,$_.DisplayName
} | Out-String
[Windows.Forms.Messagebox]::Show($str)
它应该(或多或少)做你想要的。
附录:向用户显示对象列表属性的更好选项是gridview:
$svc = Get-Service -ComputerName $targetServer | Where-Object {
($_.Name -like '*serviceAgroup*' -or $_.Name -like '*serviceBgroup*') -and
$_.Status -eq 'Running'
} | Select-Object DisplayName,Status,StartType
$svc | Out-GridView -Title 'Services'
答案 1 :(得分:0)
$($RunningServices.DisplayName -join "`r`n")