0

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

  • query each server and pull the list of all services on that server
  • then in the datagridview, I want it to show the service name in column 1, and then the count of how many servers have that service in column 2

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()
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
LTrig
  • 89
  • 1
  • 2
  • 9
  • Can you provide some code? It is also not clear what you are asking. Is the problem with counting services on multiple servers or writing the script for all the behaviors you mentioned? If the second case is true, I would recommend you re-ask a specific question and show the code you tried. – David Vogel Dec 16 '14 at 15:35
  • updated my post with the script i have. It will get all services on the servers you enter in the text box and display the name, start mode, and running or stopped in the grid view. You can sort it by name and see there are duplicate service names as it is for each server. I want it to count and only display each service it finds as one row and a count next to it with how many servers it is running on (from what you entered int he text box). – LTrig Dec 16 '14 at 15:45

1 Answers1

1

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
Matt
  • 45,022
  • 8
  • 78
  • 119
  • You sir, are awesome! Thanks for this. Only thing I changed was in the get-wmi-object, I piped it with this to get both auto and stopped: `$services += Get-WmiObject Win32_Service -ComputerName $Server |Where{$_.StartMode-eq"Auto" -and $_.State-eq"Stopped"}` then continued the pipe you posted. – LTrig Dec 16 '14 at 17:26
  • Sorry, I noticed you had removed the `Where` and put in the `-filter` Is there a way to add more than one filter? – LTrig Dec 16 '14 at 17:45
  • @LTrig you could change the filter to this : `-Filter 'StartMode="Auto" and State="Stopped"'` – Matt Dec 16 '14 at 17:52