Pipe results to file instead of write-host

I have a script that runs locally to retrieve system info. I’m using PDQ Deploy to copy the script as part of the new PC setup process. PDQ installs teh software first, and the script is run as the final step.

I’m having trouble outputting the text I see from Write-host correctly. It looks fine on the console, but I understand you can’t pipe results from write-host. I just want to export the results to a file, which I can then attach and send as an email to myself.

Here’s my script:

$computerSystem = Get-CimInstance CIM_ComputerSystem
$computerBIOS = Get-CimInstance CIM_BIOSElement
$computerOS = Get-CimInstance CIM_OperatingSystem
$computerCPU = Get-CimInstance CIM_Processor
$computerHDD = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID = 'C:'"
Clear-Host

Write-host "System Information for: " $computerSystem.Name -BackgroundColor DarkCyan
"Manufacturer: " + $computerSystem.Manufacturer
"Model: " + $computerSystem.Model
"Serial Number: " + $computerBIOS.SerialNumber
"CPU: " + $computerCPU.Name
"HDD Capacity: "  + "{0:N2}" -f ($computerHDD.Size/1GB) + "GB"
"HDD Space: " + "{0:P2}" -f ($computerHDD.FreeSpace/$computerHDD.Size) + " Free (" + "{0:N2}" -f ($computerHDD.FreeSpace/1GB) + "GB)"
"RAM: " + "{0:N2}" -f ($computerSystem.TotalPhysicalMemory/1GB) + "GB"
"Operating System: " + $computerOS.caption + ", Service Pack: " + $computerOS.ServicePackMajorVersion
"User logged In: " + $computerSystem.UserName
"Last Reboot: " + $computerOS.LastBootUpTime 

What you recommend I do instead of write-host? Ideally, I’d like to email the results to myself. But if I can at least get the results exported to a file that would be fine too.

Write-Host draws pixels directly on the screen. There’s no way to get that into a file.

Consider using Write-Output.

Thanks for the response. Replacing write-host with write-output still writes to the host. Where do I specify where I want the results to go?

Well… no :). So, this is covered in more depth in “Learn Windows PowerShell in a Month of Lunches,” but here’s the short version.

Write-Host puts nothing in the pipeline. Write-Output does.

At the end of the pipeline, whatever’s still there goes to Out-Default, which in the console and ISE immediately redirects to Out-Host, so that you see something on the screen. But that’s only if you don’t intercept it.

Write "System Information for: " $computerSystem.Name 
"Manufacturer: " + $computerSystem.Manufacturer
"Model: " + $computerSystem.Model
"Serial Number: " + $computerBIOS.SerialNumber
"CPU: " + $computerCPU.Name
"HDD Capacity: "  + "{0:N2}" -f ($computerHDD.Size/1GB) + "GB"
"HDD Space: " + "{0:P2}" -f ($computerHDD.FreeSpace/$computerHDD.Size) + " Free (" + "{0:N2}" -f ($computerHDD.FreeSpace/1GB) + "GB)"
"RAM: " + "{0:N2}" -f ($computerSystem.TotalPhysicalMemory/1GB) + "GB"
"Operating System: " + $computerOS.caption + ", Service Pack: " + $computerOS.ServicePackMajorVersion
"User logged In: " + $computerSystem.UserName
"Last Reboot: " + $computerOS.LastBootUpTime |
Out-File myfile.txt

I’ll also point out that you’re missing out on a lot of really cool PowerShell stuff. For example, there’s no reason whatsoever to use all those + signs to concatenate strings.

$var = "hello"
$x = Get-Service | Select -First 1
Write "I say $var, and the name is $( $x.name )"

Try that.

Also, be aware that:

$computerSystem = Get-CimInstance CIM_ComputerSystem
$computerBIOS = Get-CimInstance CIM_BIOSElement
$computerOS = Get-CimInstance CIM_OperatingSystem
$computerCPU = Get-CimInstance CIM_Processor
$computerHDD = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID = 'C:'"

Will get really slow if you start querying remote computers. It’s often more efficient to open a CimSession, have each Get- command re-use that session, and then close the session. Not a factor on the local computer like you’re doing, but wanted you to be aware. Again, that’s also all in “Learn Windows PowerShell in a Month of Lunches,” now in its 3rd edition ;). You’ll save yourself a ton of time and heartache with that book, and YouTube.com/powershelldon has a ton of companion videos for it.

You should really be leveraging a PSObject versus trying to do things with text. If you format it as a PSObject, you can export the data to CSV, TXT, HTML, XML or any other format very easily.

$computerSystem = Get-CimInstance CIM_ComputerSystem
$computerBIOS = Get-CimInstance CIM_BIOSElement
$computerOS = Get-CimInstance CIM_OperatingSystem
$computerCPU = Get-CimInstance CIM_Processor
$computerHDD = Get-CimInstance Win32_LogicalDisk -Filter DeviceID = 'C:'
Clear-Host

$props = @{
    "ComputerName"     = $computerSystem.Name
    "Manufacturer"     = $computerSystem.Manufacturer
    "Model"            = $computerSystem.Model
    "Serial Number"    = $computerBIOS.SerialNumber
    "CPU"              = $computerCPU.Name
    "HDD Capacity"     = ("{0:N2} GB" -f ($computerHDD.Size/1GB))
    "HDD Space"        = ("{0:P2} Free ({1:N2} GB)" -f ($computerHDD.FreeSpace/$computerHDD.Size), ($computerHDD.FreeSpace/1GB))
    "RAM"              = ("{0:N2} GB" -f ($computerSystem.TotalPhysicalMemory/1GB))
    "Operating System" = ("{0}, Service Pack: {1}" -f $computerOS.caption, $computerOS.ServicePackMajorVersion)
    "User logged In"   = $computerSystem.UserName
    "Last Reboot"      = $computerOS.LastBootUpTime
}

$results = @()
$results += New-Object -TypeName PSObject -Property $props

$body = $results | ConvertTo-HTML -Head ("System Information for: {0}" -f  $computerSystem.Name)

$mailParams = @{
    To = "youremail@company.com"
    From = "admin@company.com"
    Subject = ("System Information for: {0}" -f  $computerSystem.Name)
    Body = $body
    BodyAsHtml = $true
    SmtpServer = "SMTP.company.com"
}

Send-MailMessage @mailParams


# OR Send to a file....

#$results | Out-File "C:\Scripts\Info.txt"
#Invoke-Item "C:\Scripts\Info.txt"

# OR CSV

#$results | Export-CSV C:\Scripts\MyCSV.csv -NoTypeInformation

Thanks for your help! I’m going to go through and re-write my script with your suggestions. I’ll be picking up a copy of your new book as well. I’m able to get the info to export(although not very pretty - those +'s are really screwing with the formatting), so I think I can get it to work from here.