Get Pc & Monitor Info remotely with one script - powershell

Code 1 gets PC info Remotely and Code 2 gets Monitor Info remotely. How do I incorporate Code 2 into Code 1? I would like the output to look like the PC info followed by Monitor Info. I tried to incorporate but got a lot of errors.
Code 1 logs all the information like computers queried and UN-queried.
Code 1: Courtesy of Alexander Obersht
$ArrComputers = gc .\computernames.txt
$OutputLog = ".\output.log"
$NotRespondingLog = ".\notresponding.log"
$ErrorActionPreference = "Stop"
Clear-Host
ForEach ($Computer in $ArrComputers)
{
try
{
$computerSystem = get-wmiobject Win32_ComputerSystem -Computer $Computer
$computerBIOS = get-wmiobject Win32_BIOS -Computer $Computer
$Version = Get-WmiObject -Namespace "Root\CIMv2" `
-Query "Select * from Win32_ComputerSystemProduct" `
-computer $computer | select -ExpandProperty version
}
catch
{
$Computer | Out-File -FilePath $NotRespondingLog -Append -Encoding UTF8
continue
}
$Header = "System Information for: {0}" -f $computerSystem.Name
write-host $Header -BackgroundColor DarkCyan
$Header | Out-File -FilePath $OutputLog -Append -Encoding UTF8
$Output = (#"
-------------------------------------------------------
Model: {0}
Serial Number: {1}
Version: {2}
-------------------------------------------------------
"#) -f $computerSystem.Model, $computerBIOS.SerialNumber, $Version
Write-Host $Output
$Output | Out-File -FilePath $OutputLog -Append -Encoding UTF8
}
Code 2:
$users = gc .\computernames1.txt
gwmi WmiMonitorID -Namespace root\wmi -computername $users |
Select PSComputerName,
#{n="Model";e={[System.Text.Encoding]::ASCII.GetString($_.UserFriendlyName -ne 00)}},
#{n="Serial Number";e={[System.Text.Encoding]::ASCII.GetString($_.SerialNumberID -ne 00)}} |
Format-List | Out-File '.\report.csv'

Updated my solution from your previous question:
$ArrComputers = gc .\computernames.txt
$OutputLog = ".\output.log" # Main log
$NotRespondingLog = ".\notresponding.log" # Logging "unqueried" hosts
$ErrorActionPreference = "Stop" # Or add '-EA Stop' to Get-WmiObject queries
Clear-Host
ForEach ($Computer in $ArrComputers)
{
try
{
$computerSystem = get-wmiobject Win32_ComputerSystem -Computer $Computer
$computerBIOS = get-wmiobject Win32_BIOS -Computer $Computer
$Version = Get-WmiObject -Namespace "Root\CIMv2" `
-Query "Select * from Win32_ComputerSystemProduct" `
-computer $computer | select -ExpandProperty version
$MonitorInfo = gwmi WmiMonitorID -Namespace root\wmi `
-computername $Computer `
| Select PSComputerName, `
#{n="Model";e={[System.Text.Encoding]::ASCII.GetString(`
$_.UserFriendlyName -ne 00)}},
#{n="Serial Number";e={[System.Text.Encoding]::ASCII.GetString(`
$_.SerialNumberID -ne 00)}}
}
catch
{
$Computer | Out-File -FilePath $NotRespondingLog -Append -Encoding UTF8
continue
}
$Header = "System Information for: {0}" -f $computerSystem.Name
# Outputting and logging header.
write-host $Header -BackgroundColor DarkCyan
$Header | Out-File -FilePath $OutputLog -Append -Encoding UTF8
$Output = (#"
-------------------------------------------------------
Model : {0}
Serial Number : {1}
Version : {2}
Monitor Model : {3}
Monitor Serial : {4}
-------------------------------------------------------
"#) -f $computerSystem.Model, $computerBIOS.SerialNumber, $Version, `
$MonitorInfo.Model, $MonitorInfo."Serial Number"
# Ouputting and logging WMI data
Write-Host $Output
$Output | Out-File -FilePath $OutputLog -Append -Encoding UTF8
}

Related

PowerShell Drive Size

I have found this idea how to get drive size
I'm having problem incorporating it to my script as I don't know where to insert the code.
Also the idea is to have only one line per computer outputted even when multi hard drive system exists.
This is the code I'm working with it includes the "Get Drive Data" code
# Output file location to be changed as needed
$file="C:\scripts\reports\InentoryTest_$((Get-Date).ToString('MM-dd-yyyy')).csv"
$txt="c:\scripts\reports\InentoryTest-error_$((Get-Date).ToString('MM-dd-yyyy')).txt"
# Getting computers from Active Directory
$Computers = Get-ADComputer -Filter {Name -like 'M416*'} | select -expand name
Foreach($Computer in $Computers){
if(!(Test-Connection -ComputerName $Computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{
write-host "Cannot reach $Computer is offline" -ForegroundColor red
}
else
{
$Output = #()
Try
{
# Get Drive Data
$disk = Get-WmiObject -ComputerName $Computer Win32_LogicalDisk | Where-Object { ( $_.DriveType ) -eq 3 -and ( ( $_.freespace / $_.size ) -lt .1 ) } | ForEach-Object -Process {
[pscustomobject] #{
Drive = $_.DeviceID
Size = '{0:N1}' -f ( $_.Size / 1GB )
Free = '{0:N1}' -f ( $_.freespace / 1GB )
PercentFree = '{0:N1}' -f ( $_.freespace / $_.size * 100 )
}
}
$domain = Get-WmiObject Win32_ComputerSystem -ComputerName $Computer -ErrorAction Stop
$os = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer -ErrorAction Stop
$mac = Get-WmiObject -class Win32_NetworkAdapterConfiguration -Filter "IPEnabled='True'" -ComputerName $Computer -ErrorAction Stop
$bios = Get-WmiObject win32_bios -ComputerName $Computer -ErrorAction Stop
$cpu = Get-WmiObject –class Win32_processor -ComputerName $Computer -ErrorAction Stop
$AD = Get-ADComputer $Computer -properties Name,Lastlogondate,ipv4Address,enabled,description,DistinguishedName -ErrorAction Stop
$ram = "{0} GB" -f ((Get-WmiObject Win32_PhysicalMemory -ComputerName $Computer -ErrorAction Stop | Measure-Object Capacity -Sum).Sum / 1GB)
$pc = Get-WmiObject win32_computersystem -ComputerName $Computer -ErrorAction Stop | select #{Name = "Type";Expression = {if (($_.pcsystemtype -eq '2') )
{'Laptop'} Else {'Desktop Or Other'}}
},Manufacturer,#{Name = "Model";Expression = {if (($_.model -eq "$null") ) {'Virtual'} Else {$_.model}}},username
# Create Output
$data = New-Object PSObject -Property #{
SerialNumber = $bios.serialnumber -replace "-.*"
Computername = $AD.name
IPaddress = $AD.ipv4Address
MACaddress = $mac.MACAddress
Enabled = $AD.Enabled
Description = $AD.description
OU = $AD.DistinguishedName.split(',')[1].split('=')[1]
DC = $domain.domain
Type = $pc.type
Manufacturer = $pc.Manufacturer
Model = $pc.Model
RAM = $ram
Disk = $disk #Get Drive Data
ProcessorName = ($cpu.name | Out-String).Trim()
NumberOfCores = ($cpu.NumberOfCores | Out-String).Trim()
NumberOfLogicalProcessors = ($cpu.NumberOfLogicalProcessors | Out-String).Trim()
Addresswidth = ($cpu.Addresswidth | Out-String).Trim()
OperatingSystem = $os.caption
InstallDate = ([WMI] '').ConvertToDateTime($os.installDate)
LastLogonDate = $ld.lastlogondate
LoggedinUser = $pc.username
}
# Only do this kind of update if it hasn't failed yet
$Output += $data
$desc="$($mac.MACAddress) ( $($bios.serialnumber -replace "-.*") ) $($pc.Model) | $((Get-Date).ToString('MM-dd-yyyy'))"
#Set-ADComputer $Computer -Description $desc -verbose
$Output | select Computername,Enabled,Description,IPaddress,MACaddress,OU,DC,Type,SerialNumber,Manufacturer,Model,RAM,Disk,ProcessorName,NumberOfCores,NumberOfLogicalProcessors,Addresswidth,OperatingSystem,InstallDate,LoggedinUser,LastLogonDate | export-csv -Append $file -NoTypeInformation
}
Catch [Exception]
{
# Only do this kind of update if create output has failed
$ErrorMessage = $_.Exception.Message
Add-Content -value "$Computer, $ErrorMessage, skipping to next" $txt
#Set-ADComputer $Computer -Description $ErrorMessage
continue
}
}
}
You're building a complex hierarchical object so you'd be better off collecting all the objects then dumping the result as a JSON or XML file. But if you do want a flat string, then you'll have to explicitly format your disk data into a string before adding it to the object you're dumping to CSV. Something like:
$diskData = $disk | foreach {
"[Drive: $($_.DeviceID), Size: $([int]($_.Size/1GB)), FreeSpace: $([int]($_.freespace/1GB)), PercentFree: $([int]($_.freespace/$_.size *100))]"
}
$diskdata = $diskdata -join " "

PowerShell Set-ADComputer description based on the input

I have a code which runs trough Active Directory computers objects to collect information. Part of that information is then updated on Active directory description field.
My problem is that when I get the Exception.Message the AD object of a computer is still updated with the last found computer information.
I would like to find out how can I:
Update AD description when there is Exception.Message
Update Ad description with populated system info
Attached is the script I'm using but can't figure out where to put the output for the two Set-ADComputer statements
# Getting computers from Active Directory
$Computers = Get-ADComputer -Filter {Enabled -eq $true} | select -expand name
Foreach($computer in $computers)
# Checking if the computer is Online
{
if(!(Test-Connection -ComputerName $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{write-host "Cannot reach $Computer is offline" -ForegroundColor red}
else {
$Output = #()
Try{
$xx = Get-WmiObject win32_computersystem -ComputerName $Computer -ErrorAction Stop
$in = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer -ErrorAction Stop
$mc = Get-WmiObject -class Win32_NetworkAdapterConfiguration -Filter "IPEnabled='True'" -ComputerName $Computer -ErrorAction Stop
$sr = Get-WmiObject win32_bios -ComputerName $Computer -ErrorAction Stop
$Xr = Get-WmiObject –class Win32_processor -ComputerName $Computer -ErrorAction Stop
$ld = Get-ADComputer $Computer -properties Name,Lastlogondate,ipv4Address,enabled,description,DistinguishedName -ErrorAction Stop
$r = "{0} GB" -f ((Get-WmiObject Win32_PhysicalMemory -ComputerName $Computer -ErrorAction Stop | Measure-Object Capacity -Sum).Sum / 1GB)
$x = Get-WmiObject win32_computersystem -ComputerName $Computer -ErrorAction Stop | select #{Name = "Type";Expression = {if (($_.pcsystemtype -eq '2') )
{'Laptop'} Else {'Desktop Or Other'}}},Manufacturer,#{Name = "Model";Expression = {if (($_.model -eq "$null") ) {'Virtual'} Else {$_.model}}},username
$t= New-Object PSObject -Property #{
SerialNumber = $sr.serialnumber -replace "-.*"
Computername = $ld.name
IPaddress = $ld.ipv4Address
MACaddress = $mc.MACAddress
Enabled = $ld.Enabled
Description = $ld.description
OU = $ld.DistinguishedName.split(',')[1].split('=')[1]
DC = $xx.domain
Type = $x.type
Manufacturer = $x.Manufacturer
Model = $x.Model
RAM = $R
ProcessorName = ($xr.name | Out-String).Trim()
NumberOfCores = ($xr.NumberOfCores | Out-String).Trim()
NumberOfLogicalProcessors = ($xr.NumberOfLogicalProcessors | Out-String).Trim()
Addresswidth = ($xr.Addresswidth | Out-String).Trim()
Operatingsystem = $in.caption
InstallDate = ([WMI] '').ConvertToDateTime($in.installDate)
LastLogonDate = $ld.lastlogondate
LoggedinUser = $x.username
}
$Output += $t
}
Catch [Exception]
{
$ErrorMessage = $_.Exception.Message
Add-Content -value "$Computer, $ErrorMessage, skipping to next" $txt
Set-ADComputer $Computer -Description $ErrorMessage
}
}
# Output file location to be chnaged as needed
$file="C:\scripts\reports\AD-Inentory_$((Get-Date).ToString('MM-dd-yyyy')).csv"
$txt="c:\scripts\reports\AD-Inentory-error_$((Get-Date).ToString('MM-dd-yyyy')).txt"
$desc="$($mc.MACAddress) ( $($sr.serialnumber -replace "-.*") ) $($x.Model) | $((Get-Date).ToString('MM-dd-yyyy'))"
# Properties to be included in the output file
$Output | select Computername,Enabled,Description,IPaddress,MACaddress,OU,DC,Type,SerialNumber,Manufacturer,Model,RAM,ProcessorName,NumberOfCores,NumberOfLogicalProcessors,Addresswidth,Operatingsystem,InstallDate,LoggedinUser,LastLogonDate | export-csv -Append $file -NoTypeInformation
Set-ADComputer $Computer -Description $desc -verbose
}
It looks like the reason why it had the problem behaviour is it was catching the error, and setting the description as you wanted with the error.
However it would then continue on to evaluate the code outside of the catch and the else block, since it failed on the current computer the variables used to build the description variable still contained data from the previous computer that was successful and then update the failed computer again.
You could fix this by using the continue statement at the bottom of the catch block to skip the rest of the code for that iteration and move to the next item in the loop.
That solution would look like this:
Catch [Exception]
{
$ErrorMessage = $_.Exception.Message
Add-Content -value "$Computer, $ErrorMessage, skipping to next" $txt
Set-ADComputer $Computer -Description $ErrorMessage
## add continue statement here
continue
}
continue statement documentation here and examples here.
The other option is you restructure your code to make sure this cannot happen, like below.
I think this will fix your issue and do what you are trying to achieve. I put comments in the code around the changes I made (denoted by the ##) feel free to ask questions.
I would recommend you use more descriptive variable names.
## No Need to define these in the foreach loop
# Output file location to be chnaged as needed
$file = "C:\scripts\reports\AD-Inentory_$((Get-Date).ToString('MM-dd-yyyy')).csv"
$txt = "c:\scripts\reports\AD-Inentory-error_$((Get-Date).ToString('MM-dd-yyyy')).txt"
# Getting computers from Active Directory
## Update to use pipeline
Get-ADComputer -Filter {Enabled -eq $true} | Foreach-Object {
$computer = $_.Name
if(!(Test-Connection -ComputerName $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{
write-host "Cannot reach $Computer is offline" -ForegroundColor red
}
else
{
Try
{
## No Longer Need this because we are uisng the pipe line
#$Output = #()
$xx = Get-WmiObject win32_computersystem -ComputerName $Computer -ErrorAction Stop
$in = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer -ErrorAction Stop
$mc = Get-WmiObject -class Win32_NetworkAdapterConfiguration -Filter "IPEnabled='True'" -ComputerName $Computer -ErrorAction Stop
$sr = Get-WmiObject win32_bios -ComputerName $Computer -ErrorAction Stop
$Xr = Get-WmiObject –class Win32_processor -ComputerName $Computer -ErrorAction Stop
$ld = Get-ADComputer $Computer -properties Name, Lastlogondate, ipv4Address, enabled, description, DistinguishedName -ErrorAction Stop
$r = "{0} GB" -f ((Get-WmiObject Win32_PhysicalMemory -ComputerName $Computer -ErrorAction Stop | Measure-Object Capacity -Sum).Sum / 1GB)
$x = Get-WmiObject win32_computersystem -ComputerName $Computer -ErrorAction Stop | select #{Name = "Type"; Expression = {if (($_.pcsystemtype -eq '2') )
{'Laptop'} Else {'Desktop Or Other'}}
}, Manufacturer, #{Name = "Model"; Expression = {if (($_.model -eq "$null") ) {'Virtual'} Else {$_.model}}}, username
## Output on creation
New-Object PSObject -Property #{
SerialNumber = $sr.serialnumber -replace "-.*"
Computername = $ld.name
IPaddress = $ld.ipv4Address
MACaddress = $mc.MACAddress
Enabled = $ld.Enabled
Description = $ld.description
OU = $ld.DistinguishedName.split(',')[1].split('=')[1]
DC = $xx.domain
Type = $x.type
Manufacturer = $x.Manufacturer
Model = $x.Model
RAM = $R
ProcessorName = ($xr.name | Out-String).Trim()
NumberOfCores = ($xr.NumberOfCores | Out-String).Trim()
NumberOfLogicalProcessors = ($xr.NumberOfLogicalProcessors | Out-String).Trim()
Addresswidth = ($xr.Addresswidth | Out-String).Trim()
Operatingsystem = $in.caption
InstallDate = ([WMI] '').ConvertToDateTime($in.installDate)
LastLogonDate = $ld.lastlogondate
LoggedinUser = $x.username
}
## Only do this kind of update if it hasnt failed yet
$desc = "$($mc.MACAddress) ( $($sr.serialnumber -replace "-.*") ) $($x.Model) | $((Get-Date).ToString('MM-dd-yyyy'))"
# Properties to be included in the output file
Set-ADComputer $Computer -Description $desc -verbose
## No longer need this
# $t
}
Catch [Exception]
{
$ErrorMessage = $_.Exception.Message
Add-Content -value "$Computer, $ErrorMessage, skipping to next" $txt
Set-ADComputer $Computer -Description $ErrorMessage
continue
}
}
} | select Computername, Enabled, Description, IPaddress, MACaddress, OU, DC, Type, SerialNumber, Manufacturer, Model, RAM, ProcessorName, NumberOfCores, NumberOfLogicalProcessors, Addresswidth, Operatingsystem, InstallDate, LoggedinUser, LastLogonDate | export-csv -Append $file -NoTypeInformation
After looking at the suggestion to include continue statement I was able to achieve the solution to my problem with the following final script:
# Output file location to be changed as needed
$file="C:\scripts\reports\AD-Inentory_$((Get-Date).ToString('MM-dd-yyyy')).csv"
$txt="c:\scripts\reports\AD-Inentory-error_$((Get-Date).ToString('MM-dd-yyyy')).txt"
# Getting computers from Active Directory
$Computers = Get-ADComputer -Filter {Enabled -eq $true} | select -expand name
Foreach($computer in $computers){
if(!(Test-Connection -ComputerName $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{
write-host "Cannot reach $Computer is offline" -ForegroundColor red
}
else
{
$Output = #()
Try
{
$xx = Get-WmiObject win32_computersystem -ComputerName $Computer -ErrorAction Stop
$in = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer -ErrorAction Stop
$mc = Get-WmiObject -class Win32_NetworkAdapterConfiguration -Filter "IPEnabled='True'" -ComputerName $Computer -ErrorAction Stop
$sr = Get-WmiObject win32_bios -ComputerName $Computer -ErrorAction Stop
$Xr = Get-WmiObject –class Win32_processor -ComputerName $Computer -ErrorAction Stop
$ld = Get-ADComputer $Computer -properties Name,Lastlogondate,ipv4Address,enabled,description,DistinguishedName -ErrorAction Stop
$r = "{0} GB" -f ((Get-WmiObject Win32_PhysicalMemory -ComputerName $Computer -ErrorAction Stop | Measure-Object Capacity -Sum).Sum / 1GB)
$x = Get-WmiObject win32_computersystem -ComputerName $Computer -ErrorAction Stop | select #{Name = "Type";Expression = {if (($_.pcsystemtype -eq '2') )
{'Laptop'} Else {'Desktop Or Other'}}
},Manufacturer,#{Name = "Model";Expression = {if (($_.model -eq "$null") ) {'Virtual'} Else {$_.model}}},username
## Output on creation
$t= New-Object PSObject -Property #{
SerialNumber = $sr.serialnumber -replace "-.*"
Computername = $ld.name
IPaddress = $ld.ipv4Address
MACaddress = $mc.MACAddress
Enabled = $ld.Enabled
Description = $ld.description
OU = $ld.DistinguishedName.split(',')[1].split('=')[1]
DC = $xx.domain
Type = $x.type
Manufacturer = $x.Manufacturer
Model = $x.Model
RAM = $R
ProcessorName = ($xr.name | Out-String).Trim()
NumberOfCores = ($xr.NumberOfCores | Out-String).Trim()
NumberOfLogicalProcessors = ($xr.NumberOfLogicalProcessors | Out-String).Trim()
Addresswidth = ($xr.Addresswidth | Out-String).Trim()
Operatingsystem = $in.caption
InstallDate = ([WMI] '').ConvertToDateTime($in.installDate)
LastLogonDate = $ld.lastlogondate
LoggedinUser = $x.username
}
# Only do this kind of update if it hasn't failed yet
$Output += $t
$desc="$($mc.MACAddress) ( $($sr.serialnumber -replace "-.*") ) $($x.Model) | $((Get-Date).ToString('MM-dd-yyyy'))"
Set-ADComputer $Computer -Description $desc -verbose
$Output | select Computername,Enabled,Description,IPaddress,MACaddress,OU,DC,Type,SerialNumber,Manufacturer,Model,RAM,ProcessorName,NumberOfCores,NumberOfLogicalProcessors,Addresswidth,Operatingsystem,InstallDate,LoggedinUser,LastLogonDate | export-csv -Append $file -NoTypeInformation
}
Catch [Exception]
{
# Only do this kind of update if it has failed
$ErrorMessage = $_.Exception.Message
Add-Content -value "$Computer, $ErrorMessage, skipping to next" $txt
Set-ADComputer $Computer -Description $ErrorMessage
continue
}
}
}

Log output of ForEach loop

The code below gets computer info remotely. I couldn't get it send output to a log file. Also, how do I log all unqueried computers in a separate log file?
Code:
$ArrComputers = gc .\computernames.txt
Clear-Host
ForEach ($Computer in $ArrComputers)
{
$computerSystem = get-wmiobject Win32_ComputerSystem -Computer $Computer
$computerBIOS = get-wmiobject Win32_BIOS -Computer $Computer
$Version = Get-WmiObject -Namespace "Root\CIMv2" -Query "Select * from Win32_ComputerSystemProduct" -computer $computer | select version
write-host "System Information for: " $computerSystem.Name -BackgroundColor DarkCyan
"-------------------------------------------------------"
"Model: " + $computerSystem.Model
"Serial Number: " + $computerBIOS.SerialNumber
"Version: " + $Version
""
"-------------------------------------------------------"
}
Logging is fairly straightforward. You just need to store output in a variable and then use Out-File cmdlet:
$ArrComputers = gc .\computernames.txt
$OutputLog = ".\output.log" # Main log
$NotRespondingLog = ".\notresponding.log" # Logging "unqueried" hosts
$ErrorActionPreference = "Stop" # Or add '-EA Stop' to Get-WmiObject queries
Clear-Host
ForEach ($Computer in $ArrComputers)
{
try
{
$computerSystem = get-wmiobject Win32_ComputerSystem -Computer $Computer
$computerBIOS = get-wmiobject Win32_BIOS -Computer $Computer
$Version = Get-WmiObject -Namespace "Root\CIMv2" `
-Query "Select * from Win32_ComputerSystemProduct" `
-computer $computer | select -ExpandProperty version
}
catch
{
$Computer | Out-File -FilePath $NotRespondingLog -Append -Encoding UTF8
continue
}
$Header = "System Information for: {0}" -f $computerSystem.Name
# Outputting and logging header.
write-host $Header -BackgroundColor DarkCyan
$Header | Out-File -FilePath $OutputLog -Append -Encoding UTF8
$Output = (#"
-------------------------------------------------------
Model: {0}
Serial Number: {1}
Version: {2}
-------------------------------------------------------
"#) -f $computerSystem.Model, $computerBIOS.SerialNumber, $Version
# Ouputting and logging WMI data
Write-Host $Output
$Output | Out-File -FilePath $OutputLog -Append -Encoding UTF8
}
In its current state, your code will give an error for each computer the Get-WmiObject command could not reach. I would consider using -ErrorAction SilentlyContinue -ErrorVariable Err at the end of the first Get-WmiObject command. This will stop the errors from coming to your screen and clogging your output. You can then condition the other two calls to Get-WmiObject to only happen if the ErrorVariable is empty. If it exists, log the name of the computer, and then output to a file.
The reason you are not able to log anything else to a file is because you are using Write-Host. I would consider using a PSObject to return information. This will allow you to see the output on the screen in an organized fashion while also allowing you to write output to a file.
Also, using the -ExpandProperty switch with Select-Object will keep you from returning a hashtable for the Version property.

Export computer information to a CSV

The code below outputs information like:
System Information for: Localhost
Model : {0}
Serial Number : {1}
Version : {2}
Monitor Model : {3}
Monitor Serial : {4}
How do I export to CSV and have the formatting in Excel like:
Name, Model, Serial Number, Version, Monitor Model, Monitor serial
I would like each value in its own cell.
Code 1:
$ArrComputers = "localhost"
$OutputLog = ".\output.log"
$NotRespondingLog = ".\notresponding.log"
$ErrorActionPreference = "Stop"
Clear-Host
ForEach ($Computer in $ArrComputers) {
try {
$computerSystem = get-wmiobject Win32_ComputerSystem -Computer $Computer
$computerBIOS = get-wmiobject Win32_BIOS -Computer $Computer
$Version = Get-WmiObject -Namespace "Root\CIMv2" `
-Query "Select * from Win32_ComputerSystemProduct" `
-computer $computer | select -ExpandProperty version
$MonitorInfo = gwmi WmiMonitorID -Namespace root\wmi -computername $computer |
Select -last 1 #{n="Model"; e={[System.Text.Encoding]::ASCII.GetString($_.UserFriendlyName -ne 00)}},
#{n="Serial Number";e={[System.Text.Encoding]::ASCII.GetString($_.SerialNumberID -ne 00)}}
} catch {
$Computer | Out-File -FilePath $NotRespondingLog -Append -Encoding UTF8
continue
}
$Header = "System Information for: {0}" -f $computerSystem.Name
write-host $Header -BackgroundColor DarkCyan
$Header | Out-File -FilePath $OutputLog -Append -Encoding UTF8
$Output = (#"
-------------------------------------------------------
Model : {0}
Serial Number : {1}
Version : {2}
Monitor Model : {3}
Monitor Serial : {4}
-------------------------------------------------------
"#) -f -join $computerSystem.Model, $computerBIOS.SerialNumber, $Version, `
$MonitorInfo.Model, $MonitorInfo."Serial Number"
Write-Host $Output
$Output | Out-File -FilePath $OutputLog -Append -Encoding UTF8
}
Drop the format string and simply export the data to a CSV:
$data = ForEach ($Computer in $ArrComputers) {
try {
...
} catch {
...
}
$props = [ordered]#{
'Name' = $computerSystem.Name
'Model' = $computerSystem.Model
'Serial Number' = $computerBIOS.SerialNumber
'Version' = $Version
'Monitor Model' = $MonitorInfo.Model
'Monitor Serial' = $MonitorInfo."Serial Number"
}
New-Object -Type PSCustomObject -Property $props
}
$data | Export-Csv 'C:\path\to\output.csv' -NoType
The New-Object statement is required, because Export-Csv exports the properties of a list of objects as the fields of the CSV file.
Beware that Excel is rather particular about what it accepts as CSV. The file must must be comma-separated (regardless of what field separator is configured in your system's regional settings).

How to have both write -host and html

I have written a code snippet and I have incorporated write host in it i want both write host and convert html to run for this snippet can any one help me with that.
$arrComputers = get-Content -Path "C:\Computers.txt"
foreach ($strComputer in $arrComputers)
{
$colItems = get-wmiobject -class "Win32_BIOS" -namespace "root\CIMV2" `
-computername $strComputer
foreach ($objItem in $colItems)
{
write-host "Computer Name: " $strComputer
write-host "BIOS Version: " $objItem.BIOSVersion
}
$colItems1 = get-wmiobject -class Win32_logicaldisk -Filter "DeviceID = 'C:'" -computername $strComputer
foreach ($objItem1 in $colItems1)
{
$e=$objItem1.freeSpace/1GB
write-host "Total Space: " $e
}
$colItems4 = Get-WMIObject -class Win32_PhysicalMemory -computername $strComputer
$colItems5=$colItems4 | Measure-Object -Property capacity -Sum
foreach ($objItem4 in $colItems5)
{
$e4=$colItems5.Sum/1GB
write-host "Memory : " $e4
}
}
You can use the -Fragment parameter.
$pcName = "Computer Name: $strComputer" | ConvertTo-HTML -Fragment;
$biosV = "BIOS Version: $objItem.BIOSVersion" | ConvertTo-HTML -Fragment;
ConvertTo-HTML -Body "$pcName $biosV" -Title "List of Computers" | Out-File c:\listofcomputers.html
Just create variables after the Write-Host with the same content and use the converTo-HTML at the end of the script.
This way allows you to style your HTML output too by using the param tag or even table tags to have a better layout then a clean sterile layout.