How to split services into different cells

Currently this script outputs to an HTM file with the computername in cell 1, all the servicenames in cell 2, and all the status in cell 3. What I would like is to split it up so each line has the computer name, 1 service, and 1 status.

Function servicestatus ($serverlist, $serviceslist)

{

foreach ($machineName in $serverlist)

{
foreach ($service in $serviceslist)

{

  $serviceStatus = get-service -ComputerName $machineName -Name $service

	 if ($serviceStatus.status -eq "Running") {

     Write-Host $machineName `t $serviceStatus.name `t $serviceStatus.status -ForegroundColor Green 
     $svcName = $serviceStatus.name 
     $svcState = $serviceStatus.status         
     Add-Content $report "" 
     Add-Content $report "   $machineName" 
     Add-Content $report "  $svcName" 
     Add-Content $report "$svcState" 
     Add-Content $report "" 
                                                             }

      elseif ($serviceStatus.status -eq "Stopped")
                                               { 
   Write-Host $machineName `t $serviceStatus.name `t $serviceStatus.status -ForegroundColor Yellow 
     $svcName = $serviceStatus.name 
     $svcState = $serviceStatus.status          
     Add-Content $report "" 
     Add-Content $report "$machineName" 
     Add-Content $report "$svcName" 
     Add-Content $report "$svcState" 
     Add-Content $report "" 
                                                                } 
     else 
                                               { 
   Write-Host $machineName `t $serviceStatus.name `t $serviceStatus.status -ForegroundColor Yellow 
     $svcName = $serviceStatus.name 
     $svcState = $serviceStatus.status          
     Add-Content $report "" 
     Add-Content $report "$machineName" 
     Add-Content $report "$svcName" 
     Add-Content $report "$svcState" 
     Add-Content $report "" 
     
                                                       } 

}
}
}

Oh my. The Write-Hosts.

Have you considered:

$computers = "SERVER1","SERVER2"
foreach ($computer in $computers) {
  Get-Service -Computername $computer |
  Select-Object @{n='ComputerName';e={$computer}},Name,Status |
  ConvertTo-HTML |
  Out-File Report.html
}

Rather than manually building HTML as you’re doing? PowerShell’s perfectly willing to create HTML for you. I even wrote an EnhancedHTML2 module that lets you do very granular and dynamic HTML reports. Even wrote a free ebook about it.

forgive me if I sound ignorant or not understanding as I am learning this on the fly but you have $computers = “Server1”, “Server2” etc. I am using a txt document that have over 5000 computer names in it to run the scan from and the Service is also from a txt document as I need the service name to be a wildcard.

Basically I have found on my computers that some software that gets updated creates a new service everytime but doesn’t delete the old service. So some computers will have clientservice010117, clientservices010217 and so forth. So I need to use a scan that searches each computer in the list for a services clientservice* any that are stopped need to be delete.

Right now the report runs just fine except for the fact that it will report like this

COmputer1 clientservice010117 clientservice010217 clientservice 010317 Stopped Running Stopped

obviously each computer is alittle different

I would like it to be formatted like
Computer1 Clientservice010117 Stopped
Computer1 Clientservice010217 Running
Computer1 Clientservice010317 Stopped

Hi Cory,

Presuming you have them all listed in a column, you could use Get-Content, to read data from the txt file. then add the wildcard into the foreach loop:

$computers = Get-Content -Path C:\computer.txt 
foreach ($computer in $computers) {
  Get-Service clientservice* -Computername $computer |
  Select-Object @{n='ComputerName';e={$computer}},Name,Status |
  ConvertTo-HTML |
  Out-File C:\Report.html
}

Give that a whirl, see how you get on.

Here is the full powershell script as that might make it easier to understand. Again I am piecing this together from different how-to I have read and have got it working just now trying to figure out how to fix the format. After that is done I can go onto how to delete the bad services but that is another topic.

############################Define Server & Services Variable ###############

$serverList = Get-Content “.\server.txt”
$servicesList = Get-Content “.\services.txt”

#############################Define other variables##########################

$report = “.\report.htm”

$smtphost = “mail.mycompany.com
$from = “myself@mycompany.com
$to = “myself@mycompany.com

##############################################################################

$checkrep = Test-Path “.\report.htm”

If ($checkrep -like “True”)

{

Remove-Item “.\report.htm”
}

New-Item “.\report.htm” -type file
################################ADD HTML Content#############################

Add-Content $report “”
Add-Content $report “”
Add-Content $report “”
Add-Content $report ‘Service Status Report’
add-content $report ‘’
add-content $report “”
add-content $report “”
Add-Content $report “”
Add-Content $report “”
add-content $report “”
add-content $report “”
add-content $report “”
add-content $report “Service Status Report
add-content $report “”
add-content $report “”
add-content $report “”

add-content $report “”
Add-Content $report “”
Add-Content $report “Server Name”
Add-Content $report “Service Name”
Add-Content $report “Status”
Add-Content $report “”
########################################################################################################
################################## Get Services Status #################################################

Function servicestatus ($serverlist, $serviceslist)
{
foreach ($machineName in $serverlist)
{
foreach ($service in $serviceslist)
{
$serviceStatus = get-service -ComputerName $machineName -Name $service

	 if ($serviceStatus.status -eq "Running") {

     Write-Host $machineName `t $serviceStatus.name `t $serviceStatus.status -ForegroundColor Green 
     $svcName = $serviceStatus.name 
     $svcState = $serviceStatus.status         
     Add-Content $report "" 
     Add-Content $report "   $machineName" 
     Add-Content $report "  $svcName" 
     Add-Content $report "$svcState" 
     Add-Content $report "" 
                                               }

        else 
                                               { 
   Write-Host $machineName `t $serviceStatus.name `t $serviceStatus.status -ForegroundColor Red 
     $svcName = $serviceStatus.name 
     $svcState = $serviceStatus.status          
     Add-Content $report "" 
     Add-Content $report "$machineName" 
     Add-Content $report "$svcName" 
     Add-Content $report "$svcState" 
     Add-Content $report "" 
     
     sc.exe \\$machineName delete "$SvcName"  #This does not work

}
}
}
}
############################################Call Function#############################################
servicestatus $serverList $servicesList
############################################Close HTMl Tables#########################################
Add-content $report “”
Add-Content $report “”
Add-Content $report “”
#####################################################################################################
#############################################Send Email##############################################
$subject = “Daily Service Monitor”
$body = Get-Content “.\report.htm”
$smtp= New-Object System.Net.Mail.SmtpClient $smtphost
$msg = New-Object System.Net.Mail.MailMessage $from, $to, $subject, $body
$msg.isBodyhtml = $true
$smtp.send($msg)

#####################################################################################################

Cory, would you consider looking at the two short examples we’ve posted, and letting us know - obviously, using a couple of your own servers rather than SERVER1 and SERVER2 - if the basic output form is what you want? We’re trying to help, but the approach you’re taking with all that Add-Content is just a bad approach. We’re not going to be able to help you fix your existing script - it’s a bad direction. We’re trying to get you going in a good direction.

OK I have shrunk down the script to what I think it should look like with everyones input. However I now do not get any information in my report.html it is just blank. Also when I watch the script run instead of reporting back the names and services it is reporting back all HTML code. If I removed something I shouldn’t have removed please let me know.

############################Define Server & Services Variable ###############
$serverList = Get-Content “.\server.txt”
#############################Define other variables##########################

$report = “.\report.html”

$smtphost = “mail@mycompany.com
$from = “myself@mycompany.com
$to = “myself@mycompany.com

##############################################################################

$checkrep = Test-Path “.\report.html”

If ($checkrep -like “True”)

{

Remove-Item “.\report.html”

}

New-Item “.\report.html” -type file

################################## Get Services Status #################################################
foreach ($computer in $serverList)
{
Get-Service clientservice* -ComputerName $computer |
Select-Object @{n=‘ComputerName’;e={$computer}},Name,Status |
ConvertTo-Html
Out-File “.\report.html”
}

#############################################Send Email##############################################

$subject = “Daily Service Monitor”
$body = Get-Content “.\report.htm”
$smtp= New-Object System.Net.Mail.SmtpClient $smtphost
$msg = New-Object System.Net.Mail.MailMessage $from, $to, $subject, $body
$msg.isBodyhtml = $true
$smtp.send($msg)

#####################################################################################################

You did - you’re missing the pipe character after ConvertTo-HTML. As a result, the converted HTML is spewing to the screen, and Out-File isn’t being given anything to work with.

I appreciate the help

Don/Chris

After fixing the type of not having the Pipe behind the ConvertTo-html I was able to get content on my report.html.
However it only reported the last scanned computer, it did not report any other computers that were scanned.

Any thoughts on that

Did you try the -Append parameter?
https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.utility/out-file

-Append appears to have added all the computers now. Thanks for that.
It also added the header for the Computername, Service, and Status. I can live with editing that out manually unless someone knows how to only show the Header fields once

Again thank you everyone for the help.

Yeah, you really want to refactor it a bit probably.

Rather than:

foreach ($computer in $serverList)
{
Get-Service clientservice* -ComputerName $computer |
Select-Object @{n='ComputerName';e={$computer}},Name,Status |
ConvertTo-Html
Out-File ".\report.html"
}

Do something like:

function x {
 foreach ($computer in $serverList)
 {
  Get-Service clientservice* -ComputerName $computer |
  Select-Object @{n='ComputerName';e={$computer}},Name,Status
 }
}
x | 
ConvertTo-Html |
Out-File ".\report.html"
}

That’ll give you one report without all the headers, I think. The idea is to generate all the objects and only call ConvertTo-HTML once.

Thank you that did the trick