在弹出窗口中列出服务和状态

时间:2017-08-21 15:53:02

标签: powershell popup

我有一个停止和启动服务的脚本。但是,我遇到了一些服务未正确停止的问题,需要用户干预服务器。在脚本的启动服务部分运行之前,我使用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)

2 个答案:

答案 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)

应该给你这样的东西:

Service list (space-separated columns) in GUI dialog

为了获得至少有些可呈现的结果,我建议使用自定义格式字符串:

PS C:\> $s3 = $s | ForEach-Object {"{0}`t{1}`t{2}" -f $_.StartType,$_.Status,$_.DisplayName} | Out-String
PS C:\> [Windows.Forms.Messagebox]::Show($s3)

这应该会产生更多可见的输出:

Service list (tab-separated columns) in GUI dialog

以上内容利用了StartTypeStatus属性的值不会变化太大的事实,因此可以通过分离值来合理地对齐列使用制表符。如果您必须在左侧具有服务名称,则格式化会变得复杂得多,因为您需要根据名称中字符的数量和宽度插入可变数量的选项卡。我打算把它作为读者的练习。

底线:将您的代码更改为以下内容:

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")