powershelldatagridviewdatagridviewtextboxcelldatagridviewrow

Counting Services on multiple servers


I'm still a beginner with powershell, but love to learn and research all the things it can do.

So with that, I am looking to create a script that will output to a datagridview table. I created a simple enough form that has a multi-line text box where you can enter in a list of servers and then just a simple "check" button that calls my function to actually query each server for their services and outputs that info into the datagridview below it.

That part was easy enough for me to create. My thing is, I want it to do the following":

Hope this make since. Can't really provide any code as I don't know how to properly write it! I'm thinking there is someway to generate the full list, then do a loop and count type thing, but not sure.

I thank you for any assistance with this. Been googling and reading up like crazy. Either not correct search criteria or something just isn't clicking for me.

Update - Adding in current script I have:

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 

$xForm = 800
$yForm = 800

$SVCForm = New-Object System.Windows.Forms.Form 
$SVCForm.Text = "Automatic Services Query"
$SVCForm.Size = New-Object System.Drawing.Size($xForm,$yForm)
$SVCForm.FormBorderStyle = "FixedSingle" 
$SVCForm.StartPosition = "CenterScreen"
$SVCForm.ControlBox = $true
$SVCForm.KeyPreview = $True
$SVCForm.ShowIcon = $false
$SVCForm.MinimizeBox = $True
$SVCForm.MaximizeBox = $false

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(365,720)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$x=$CancelButton.Text;$SVCForm.Close()})
$SVCForm.Controls.Add($CancelButton)

$ServerListGroup = New-Object System.Windows.Forms.GroupBox 
$ServerListGroup.Location = New-Object System.Drawing.Size(5,10)
$ServerListGroup.size = New-Object System.Drawing.Size(780,300)
$ServerListGroup.text = "Enter list of servers you want to check:"
$SVCForm.Controls.Add($ServerListGroup)

$ServerList = New-object System.Windows.Forms.TextBox
$ServerList.Location = New-object System.Drawing.Size(5,25)
$ServerList.Size = New-Object System.Drawing.Size(280,270)
$ServerList.Multiline = $True
$ServerList.ScrollBars = "Vertical"
#$ServerList.add_TextChanged({ONValButton})
$ServerListGroup.Controls.Add($ServerList)

$SVCButton = New-Object System.Windows.Forms.Button
$SVCButton.Location = New-Object System.Drawing.Size(505,140)
$SVCButton.Size = New-Object System.Drawing.Size(180,22)
$SVCButton.Text = "SVC Check"
$SVCButton.Enabled = $True
$SVCButton.Add_Click({SvcCheckCount})
$ServerListGroup.Controls.Add($SVCButton)


$SvcListGroup = New-Object System.Windows.Forms.GroupBox 
$SvcListGroup.Location = New-Object System.Drawing.Size(5,330)
$SvcListGroup.size = New-Object System.Drawing.Size(780,380)
$SvcListGroup.text = "Automatic Running/Not-Running Services are listed below:"
$SVCForm.Controls.Add($SvcListGroup)

#$SvcList = New-object System.Windows.Forms.TextBox
#$SvcList.Location = New-object System.Drawing.Size(5,25)
#$SvcList.Size = New-Object System.Drawing.Size(765,350)
#$SvcList.Multiline = $True
#$SvcList.ScrollBars = "Vertical"
#$SvcList.Readonly= $True
#$SvcListGroup.Controls.Add($SvcList)

$SvcGrid = New-Object System.Windows.Forms.DataGridView
$SvcGrid.Location = New-Object System.Drawing.Size(5,15)
$SvcGrid.Size = New-Object System.Drawing.Size(760,360)
$SvcGrid.ColumnHeadersBorderStyle = [System.Windows.Forms.DataGridViewHeaderBorderStyle]::Single
$SvcGrid.CellBorderStyle = [System.Windows.Forms.DataGridViewCellBorderStyle]::Single
$SvcGrid.ColumnHeadersHeightSizeMode = [System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode]::DisableResizing
$SvcGrid.GridColor = [System.Drawing.Color]::Black
$SvcGrid.RowHeadersVisible = $false
$SvcGrid.AllowUserToAddRows = $false
$SvcGrid.AllowUserToResizeColumns = $False
$SvcGrid.AllowUserToResizeRows = $false
$SvcGrid.ColumnHeadersHeight = 23
$SvcGrid.SelectionMode = [System.Windows.Forms.DataGridViewSelectionMode]::FullRowSelect
$Scroll = New-Object System.Windows.Forms.VScrollBar
$Scroll.Dock = [System.Windows.Forms.DockStyle]::Right
$Scroll.width = 18
$Scroll.isAccessible = $false
$SvcGrid.Controls.Add($Scroll)                
$SvcGrid.Columns.Add("Name","Service Name") > $null
$SvcGrid.Columns["Name"].Width = 200
$SvcGrid.Columns["Name"].HeaderCell.Style.Alignment = [System.Windows.Forms.DataGridViewContentAlignment]::MiddleLeft
$SvcGrid.Columns["Name"].DefaultCellStyle.Alignment = [System.Windows.Forms.DataGridViewContentAlignment]::MiddleLeft
$SvcGrid.Columns["Name"].ReadOnly = $False
$SvcGrid.Columns.Add("StartMode", "Start Mode") > $null
$SvcGrid.Columns["StartMode"].Width = 180
$SvcGrid.Columns["StartMode"].HeaderCell.Style.Alignment = [System.Windows.Forms.DataGridViewContentAlignment]::MiddleLeft
$SvcGrid.Columns["StartMode"].DefaultCellStyle.Alignment = [System.Windows.Forms.DataGridViewContentAlignment]::MiddleLeft
$SvcGrid.Columns["StartMode"].ReadOnly = $False
$SvcGrid.Columns.Add("Running","Running") > $null
$SvcGrid.Columns["Running"].Width = 180
$SvcGrid.Columns["Running"].HeaderCell.Style.Alignment = [System.Windows.Forms.DataGridViewContentAlignment]::MiddleCenter
$SvcGrid.Columns["Running"].DefaultCellStyle.Alignment = [System.Windows.Forms.DataGridViewContentAlignment]::MiddleCenter
$SvcGrid.Columns["Running"].ReadOnly = $true
$SvcGrid.Columns.Add("NotRunng","Not Running")>$null
$SvcGrid.Columns["NotRunng"].Width = 180
$SvcGrid.Columns["NotRunng"].HeaderCell.Style.Alignment = [System.Windows.Forms.DataGridViewContentAlignment]::MiddleCenter
$SvcGrid.Columns["NotRunng"].DefaultCellStyle.Alignment = [System.Windows.Forms.DataGridViewContentAlignment]::MiddleCenter
$SvcGrid.Columns["NotRunng"].ReadOnly = $true
$SvcListGroup.Controls.Add($SvcGrid)




Function SvcCheckCount
{
   $SvcGrid.Rows.Clear()
   $Servername = $ServerList.Text.Split("`n")|%{$_.trim()}

    foreach($Server in $Servername)
           {
             $Server = $Server.ToUpper()
                $svctest = Get-WmiObject Win32_Service | Where-Object {$_.StartMode -eq 'Auto'} | Select-Object Name, Startmode, State

                Foreach ($svc in $svctest)
                {
                $name = $svc.Name
                $startmode = $svc.StartMode
                $state = $svc.State

                If($state-eq"Running"){$SvcGrid.Rows.add($name,$startmode,$state)}
                If($state-eq"Stopped"){$SvcGrid.Rows.add($name,$startmode,$null,$state)}
                }

              }  



}




$SVCForm.Topmost = $True

$SVCForm.Add_Shown({$SVCForm.Activate()})
[void] $SVCForm.ShowDialog()

Solution

  • Since you already have the GUI portion of this functioning I am going to focus us the grouping of the data you are looking for. Going into this the one thing I am fuzzy on is why you have the if statements are for but we can work on that if need be. The following is meant to be in place of your foreach loop

    $services = @()
    foreach($Server in $Servername){
        $Server = $Server.ToUpper()
        $services += Get-WmiObject Win32_Service -ComputerName $Server -Filter 'StartMode="Auto"' |
                Select-Object Name, Startmode, State | 
                Add-Member -MemberType NoteProperty -Value $Server -Name "Server" -PassThru
    }  
    $services | Group-Object Name | ForEach-Object{
        $SvcGrid.Rows.add($_.Name,$_.Count)
    }
    

    First thing: you were not using the $server variable in your wmi call so all the results would have been from the one machine you were running this from. Also, I moved the Where into a -Filter so that should speed up processing on remote machines.

    Collect all of this information into an array (adding the computer name in case it becomes useful later). Then, using the results from that use Group-Object to get the counts you were looking for. Pipe that into another ForEach-Object to get the results in your grid ( which i have not tested.)

    Side note: If you just want the info in a grid you can use Out-GridView

    $services | Group-Object Name | Select name,count | Out-GridView