Pipe results to file instead of write-host

This topic contains 5 replies, has 3 voices, and was last updated by Profile photo of Daniel Brooks Daniel Brooks 5 days, 20 hours ago.

Viewing 6 posts - 1 through 6 (of 6 total)
  • Author
    Posts
  • #54464
    Profile photo of Daniel Brooks
    Daniel Brooks
    Participant

    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.

    • This topic was modified 5 days, 21 hours ago by Profile photo of Daniel Brooks Daniel Brooks.
    #54465
    Profile photo of Don Jones
    Don Jones
    Keymaster

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

    Consider using Write-Output.

    #54470
    Profile photo of Daniel Brooks
    Daniel Brooks
    Participant

    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?

    #54471
    Profile photo of Don Jones
    Don Jones
    Keymaster

    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.

    • This reply was modified 5 days, 20 hours ago by Profile photo of Don Jones Don Jones.
    #54480
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    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 = "[email protected]"
        From = "[email protected]"
        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
    
    #54483
    Profile photo of Daniel Brooks
    Daniel Brooks
    Participant

    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.

Viewing 6 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic.