user3364233
user3364233

Reputation: 105

Formatting Output File

I am creating a script to get the uptime / last reboot of a group of PCs read in from a text file.

I can output the results to file, but it keeps repeating the column header which I do not want. Basically what I would like is to output the first line for the headers and then each line after for the data the data underneath. The code below repeats the column header to the output file and there are a lot of spaces between the lines. Would an output to CSV be easier to handle?

Here is my code. The first Out-File command is to overwrite the file if it exists, essentially clearing the file.

$computers = Get-Content "c:\temp\ps\pc.txt"

out-file -FilePath "C:\temp\ps\output.txt"
foreach ($computer in $computers) 
{
    $Computerobj = "" | select ComputerName, Uptime, LastReboot
    $wmi = Get-WmiObject -ComputerName $computer -Query "SELECT LastBootUpTime     FROM Win32_OperatingSystem"
    $now = Get-Date
    $boottime = $wmi.ConvertToDateTime($wmi.LastBootUpTime)
    $uptime = $now - $boottime
    $d =$uptime.days
    $h =$uptime.hours
    $m =$uptime.Minutes
    $s = $uptime.Seconds
    $Computerobj.ComputerName = $computer
    $Computerobj.Uptime = "$d Days $h Hours $m Min $s Sec"
    $Computerobj.LastReboot = $boottime
    $Computerobj
    out-file -FilePath "C:\temp\ps\output.txt" -in $computerobj -append
}

Upvotes: 0

Views: 1169

Answers (2)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200493

A pipeline with ForEach-Object and Export-Csv would be a better approach:

$now = Get-Date

Get-Content -Path 'C:\temp\ps\pc.txt' | ForEach-Object {
  $wmi = Get-WmiObject -ComputerName $_ -Class Win32_OperatingSystem
  $boottime = $wmi.ConvertToDateTime($wmi.LastBootUpTime)
  $uptime = $now - $boottime
  New-Object -Type PSObject -Property @{
    'ComputerName' = $_
    'Uptime'       = '{0} Days {1} Hours {2} Min {3} Sec' -f $uptime.Days, 
                     $uptime.Hours, $uptime.Minutes, $uptime.Seconds
    'LastReboot'   = $boottime
  }
} | Export-Csv -Path 'C:\temp\ps\output.txt' -NoType

If you need the data both in a file and on the console, you could use ConvertTo-Csv and Tee-Object:

Get-Content 'c:\temp\ps\pc.txt' | ForEach-Object {
  ...
} | ConvertTo-Csv -NoType | Tee-Object -FilePath 'C:\temp\ps\output.txt'

Upvotes: 3

Bacon Bits
Bacon Bits

Reputation: 32220

Try this:

$computers = Get-Content "c:\temp\ps\pc.txt"

#Create a report variable as an array to hold all our data
$report = @();

#No longer necessary
#out-file -FilePath "C:\temp\ps\output.txt"

foreach ($computer in $computers) 
{
    $Computerobj = "" | select ComputerName, Uptime, LastReboot
    $wmi = Get-WmiObject -ComputerName $computer -Query "SELECT LastBootUpTime     FROM Win32_OperatingSystem"
    $now = Get-Date
    $boottime = $wmi.ConvertToDateTime($wmi.LastBootUpTime)
    $uptime = $now - $boottime
    $d =$uptime.days
    $h =$uptime.hours
    $m =$uptime.Minutes
    $s = $uptime.Seconds
    $Computerobj.ComputerName = $computer
    $Computerobj.Uptime = "$d Days $h Hours $m Min $s Sec"
    $Computerobj.LastReboot = $boottime

    #Add the computer to the report array
    $report += $Computerobj
}

#Uncomment this if you need to see the report as well as write it to a file
#Write-Output $report

out-file -FilePath "C:\temp\ps\output.txt" -in $report

Now you can manipulate the report as a whole, so you can even add things at the end like $report = $report | Sort-Object -Property ComputerName to sort the report by computer names, or filter it with Where-Object.

Upvotes: 0

Related Questions