?
Solved

Powershell custom table

Posted on 2010-09-23
8
Medium Priority
?
1,280 Views
Last Modified: 2012-08-13
Hello,

I am looking to use PowerShell to gather information about several hosts, and display the information in a table.  I have the logic down to gather the information, and sort the machines into 3 arrays based on the results, but can't figure out how to get them into a table type view.

Here the basic idea,

Script gathers list of hosts
Pings host, if no response add machine name to $noping
If it is pingable, searches for an active process, if the process is there add it to $running
If process is not there add it to $complete

This is all in a loop that checks every 5 minutes and all of that works fine if I just print the list lengthwise.

I would like to print it in 3 columns, i.e.

Completed          Running          No Pingy
====================================
Host1                 Host3             Host9
Host2                 Host99
Host17
Host47


Then when it runs again in the loop it will clear the screen and display the current status.

Can't think of a way to do it though.

Is there any simple way to accomplish a manual table with column1 containing the contents of an array/string, column2 the contents of a different array, etc?

Thank you.
0
Comment
Question by:omnipower321
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
8 Comments
 
LVL 71

Expert Comment

by:Chris Dent
ID: 33744066

A simple way? No. PS isn't built to produce that kind of output formatting. That means you'd have to write your own format, which is possible, just not entirely easy considering the example.

Chris
0
 

Author Comment

by:omnipower321
ID: 33745063
Yeah that is what I figured.  But I wanted to make sure before going through the nightmare.  I am working on creating a custom object with 3 properties, and it will print out the ammount of rows for the largest array count, and each object will contain the info for that line if needed.

i.e.
$row1.col1 = $arr1[0]
$row1.col2 = $arr2[0]
$row1.col3 = $arr3[0]

Then I will just loop through the $rows to print it.  It's gonna be ugly, but I think it will work.
0
 
LVL 7

Expert Comment

by:wittyslogan
ID: 33745081
do you want to write the data to a database because then every fiv minutes you could just write your three columns to a table.
OR to a csv file and then import it wherever you want

but just to be clear are you trying to do something like:

write-output "$completed,$running,$nopingy"
| out-file -filepath "\\servername\powershell\log_files\log.csv"

?
0
10 Questions to Ask when Buying Backup Software

Choosing the right backup solution for your organization can be a daunting task. To make the selection process easier, ask solution providers these 10 key questions.

 

Author Comment

by:omnipower321
ID: 33745242
Just outputting to the screen directly, wanted to keep any DB or external files out of it, but csv may be another route, I will tinker and give it a try.
0
 
LVL 12

Accepted Solution

by:
GusGallows earned 2000 total points
ID: 33746250
Ok, this is going to look a little complicated, but it really isn't.
First, I have three functions, one to add characters to a string to make the string a uniform size. this is important to making the columns line up. The other two functions are for the ping test and the process test. Replace the servernames with your list of computers, replace the column width (in my script it is set to 14) to whatever you want the columns to be sized too, and finally replace 'Outlook' with the process you are looking for. Wrap it in whatever you are using to run it every 5 minutes and you should be good to go.

Function Repeat-String([string]$str, [int]$repeat)
{  
      $builder = new-object System.Text.StringBuilder
      for ($i = 0; $i -lt $repeat; $i++)
      {
            [void]$builder.Append($str)
      }  
      $builder.ToString()
}

Function Ping-Host ($Server)
{
      $status=get-wmiobject win32_pingstatus -Filter "Address='$Server'" | Select-Object statuscode
      if($status.statuscode -eq 0)
      {
            $res = $True
      }
      else
      {
            $res = $False
      }
      Return $Res
}
Function Get-RProcess ([String]$processName, [string]$Computer)
{
      $procres = [system.Diagnostics.Process]::GetProcessesByName($processName,$Computer)
      if ($procres -ne $null)
      {
            $result = $True
      }
      Else
      {
            $result = $False
      }
      Return $result
}
CLS
[Array]$NoPingList = $null
[Array]$RunningList = $null
[Array]$CompletedList = $null
$i = 0
$ColWidth = 14
$ServerList = @('Servername1','Servername2','Servername3','Servername4','Servername5','Servername6')
ForEach ($Server in $ServerList)
{
      $pingres = Ping-Host $Server
      If ($pingres -eq $true)
      {
            $rprocres = Get-RProcess 'Outlook' $Server
            If ($rprocres -eq $True)
            {
                  $Running = $Server
                  $RunningList = $RunningList + $Running
            }
            Else
            {
                  $Completed = $Server
                  $CompletedList = $CompletedList + $Completed
            }
      }
      Else
      {
            $NoPing = $Server
            $NoPingList = $NoPingList + $NoPing
      }
      
}
$CountRun = $RunningList.Count
$CountComp = $CompletedList.Count
$CountNoPing = $NoPingList.Count
$HiCount = $CountRun
If ($CountComp -gt $HiCount){$HiCount = $CountComp}
If ($CountNoPing -gt $HiCount){$HiCount = $CountNoPing}

$H1 = 'Completed'
$H2 = 'Running'
$H3 = 'NoPingy'
$h1len = $ColWidth - $H1.Length
$h2len = $ColWidth - $H2.Length
$h3len = $ColWidth - $H3.Length
$tH1 = Repeat-String " " $h1len
$tH2 = Repeat-String " " $h2len
$tH3 = Repeat-String " " $h3len
$Header = "$H1$tH1`t$H2$tH2`t$H3$tH3"

$R1 = Repeat-String "-" $ColWidth
$R2 = Repeat-String "-" $ColWidth
$R3 = Repeat-String "-" $ColWidth
$Row1 = "$R1`t$R2`t$R3"
$Header
$Row1


for ($i = 0; $i -le $hiCount; $i +=1)
{
      If ($CompletedList -eq $Null)
      {
            $clistlen = 0
            $CompletedList = $CompletedList + ""
      }
      Else
      {
            $clistlen = $CompletedList[$i].Length
      }
      $lCom = $ColWidth - $clistlen
      $lc1 = Repeat-String " " $lCom
      
      If ($RunningList -eq $Null)
      {
            $rlistlen = 0
            $RunningList = $RunningList + ""
      }
      Else
      {
            $rlistlen = $RunningList[$i].Length
      }
      $lRun = $ColWidth - $rlistlen
      $lr1 = Repeat-String " " $lRun

      If ($NoPingList -eq $Null)
      {
            $plistlen = 0
            $NoPingList = $NoPingList + ""
      }
      Else
      {
            $plistlen = $NoPingList[$i].Length
      }
      $plistlen = $NoPingList[$i].Length
      $lPin = $ColWidth - $plistlen
      $lp1 = Repeat-String " " $lPin
      $Line = $CompletedList[$i] + $lc1 + "`t" + $RunningList[$i] + $lr1 + "`t" + $NoPingList[$i] + $lp1
      $Line
}
0
 

Author Closing Comment

by:omnipower321
ID: 33746516
Thank you very much, that is exactly what I was looking for!
0
 
LVL 7

Expert Comment

by:wittyslogan
ID: 33752085
That is lovely
0
 

Author Comment

by:omnipower321
ID: 33757098
Here is my final result using most of GusGallows' ideas.  I probably made it less elegant with the exclusion of funcations, and more verbose, but it makes sense to now.    This will be in a larger timed loop eventually.Thanks again!
$ErrorActionPreference = "SilentlyContinue"

$strH1 = "Running"
$strH2 = "No Ping"
$strH3 = "Complete"
$arrNoPingList = @()
$arrRunningList = @()
$arrCompletedList = @()
$arrResultsCtr = @()
$colComputers = GC .\Computers.txt
$intColumnWidth = ($colComputers | %{$_.Length} | Sort | Select -Last 1)
If($intColumnWidth -lt $strH1.Length){$intColumnWidth = $strH1.Length}
If($intColumnWidth -lt $strH2.Length){$intColumnWidth = $strH2.Length}
If($intColumnWidth -lt $strH3.Length){$intColumnWidth = $strH3.Length}
Write-Host -F Cyan -NoNewLine "$strH1 $(" " * ($intColumnWidth - $strH1.Length))`t"
Write-Host -F Cyan -NoNewLine "$strH2 $(" " * ($intColumnWidth - $strH2.Length))`t"
Write-Host -F Cyan "$strH3 $(" " * ($intColumnWidth - $strH3.Length))"
Write-Host -F Cyan "$("=" * $($intColumnWidth * 3 + 8))"
ForEach($objComputer in $colComputers){
	$intSpacesToAdd = $intColumnWidth - $objComputer.Length
	If(Test-Connection -ComputerName $objComputer -Quiet -Count 1){
		$objIsItRunning = $Null
		$objIsItRunning = Get-Process -ComputerName $objComputer Outlook, Notepad
		If($objIsItRunning){$arrRunningList += "$objComputer $(" " * $intSpacesToAdd)`t"}
		Else{$arrCompletedList += "$objComputer $(" " * $intSpacesToAdd)`t"}
	}
	Else{$arrNoPingList += "$objComputer $(" " * $intSpacesToAdd)`t"}
}
$arrResultsCtr += $arrNoPingList, $arrRunningList, $arrCompletedList
$intTotalDataRows = $arrResultsCtr | %{$_.Count} | Sort | Select -Last 1
For($j = 0; $j -le $intTotalDataRows; $j++){
	If($arrRunningList[$j] -eq $Null){$strDataCol1 = "$(" " * ($intColumnWidth + 4))"}
	Else{$strDataCol1 = $arrRunningList[$j]}
	If($arrNoPingList[$j] -eq $Null){$strDataCol2 = "$(" " * ($intColumnWidth + 4))"}
	Else{$strDataCol2 = $arrNoPingList[$j]}
	If($arrCompletedList[$j] -eq $Null){$strDataCol3 = "$(" " * ($intColumnWidth + 4))"}
	Else{$strDataCol3 = $arrCompletedList[$j]}
	$strDataCol1 + $strDataCol2 + $strDataCol3
}

Open in new window

0

Featured Post

Ransomware Attacks Keeping You Up at Night?

Will your organization be ransomware's next victim?  The good news is that these attacks are predicable and therefore preventable. Learn more about how you can  stop a ransomware attacks before encryption takes place with our Ransomware Prevention Kit!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Issue: One Windows 2008 R2 64bit server on the network unable to connect to a buffalo Device (Linkstation) with firmware version 1.56. There are a total of four servers on the network this being one of them. Troubleshooting Steps: Connect via h…
In the absence of a fully-fledged GPO Management product like AGPM, the script in this article will provide you with a simple way to watch the domain (or a select OU) for GPOs changes and automatically take backups when policies are added, removed o…
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
Suggested Courses

764 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question