Adding new item into XML output file - powershell

I would like to combined the external IP address with the current hardware information output file.
PC info
#lists computer information
$cpu = Get-WmiObject -Class Win32_Processor
$mb = Get-WmiObject -Class Win32_BaseBoard
$bios = Get-WmiObject -Class Win32_BIOS -ComputerName .
#$user = Get-WmiObject -Class Win32_ComputerSystem
$last = Get-WmiObject -class Win32_NetworkLoginProfile |
Where {($_.NumberOfLogons -gt 0) -and ($_.NumberOfLogons -lt 65535)} |
Select-Object Name,#{label='LastLogon';expression={$_.ConvertToDateTime($_.LastLogon)}},NumberOfLogons
$props = #{
"Name" = $cpu.Name
"Description" = $cpu.Description
"MB Manufacturer" = $mb.Manufacturer
"MB Product" = $mb.Product
"Bios Verison" = $bios.SMBIOSBIOSVersion
"Bios Manufacturer" = $bios.Manufacturer
"Bios Serial" = $bios.SerialNumber
"~Last Logon" = $last
}
New-Object PSObject -Property $props | Out-File c:\Windows\Script\PS_Output3.xml
External IP Address
$wc=New-Object net.webclient;
$wc.downloadstring("http://checkip.dyndns.com") -replace "[^\d\.]"
Update
One last question: how could I organize the list?

Something like this might help:
#lists computer information
$cpu = Get-WmiObject -Class Win32_Processor
$mb = Get-WmiObject -Class Win32_BaseBoard
$bios = Get-WmiObject -Class Win32_BIOS -ComputerName .
#$user = Get-WmiObject -Class Win32_ComputerSystem
$DyDNS = Invoke-WebRequest http://checkip.dyndns.com/ -DisableKeepAlive
$Dyreg = $DyDNS.RawContent -match '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b'
$last = Get-WmiObject -class Win32_NetworkLoginProfile | Where {($_.NumberOfLogons -gt 0) -and ($_.NumberOfLogons -lt 65535)} | Select-Object Name,#{label='LastLogon';expression={$_.ConvertToDateTime($_.LastLogon)}},NumberOfLogons
$props = #{
"Name" = $cpu.Name
"Description" = $cpu.Description
"MB Manufacturer" = $mb.Manufacturer
"MB Product" = $mb.Product
"Bios Verison" = $bios.SMBIOSBIOSVersion
"Bios Manufacturer" = $bios.Manufacturer
"Bios Serial" = $bios.SerialNumber
"~Last Logon" = $last
"DNS" = $matches[0]
}
New-Object PSObject -Property $props | Out-File C:\test.csv

Related

How to export information about the monitor to a csv file using PowerShell?

I am new to PowerShell and am struggling to write a script to export the UserFriendlyName (see the code below) for three monitors. Here is what I have so far:
$monitors = Get-WmiObject -Namespace root\wmi -Class wmiMonitorID
Get-CimInstance -Namespace root\wmi -ClassName wmimonitorid -ComputerName $ComputerName |
foreach {
$Object = New-Object PSObject -Property #{
MonitorName = ($monitors.UserFriendlyName -notmatch '^0$' | foreach {[char]$_}) -join ""
MonitorSerial = ($monitors.serialnumberid -notmatch '^0$' | foreach {[char]$_}) -join ""
}
}
$Object | Select MonitorName,MonitorSerial
$Object | Export-Csv -append -force /Computer.csv -NoTypeInformation
The result that I am getting:
MonitorName MonitorSerial
----------- -------------
27B1DELL P2717HDELL P2717H GUHJBHA018695YKNFG6CQAGLLYKNFG71KAPTL
I would like to have each monitor name and serial number under their own column (Monitor 1, Monitor 2, Monitor 3 and the same for serial number) but the values are together. Any help is much appreciated.
I am hoping to have the above incorporated with this:
$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:'"
Get-CimInstance -Namespace root\wmi -ClassName wmimonitorid -ComputerName $ComputerName |
foreach {
$Object = New-Object PSObject -Property #{
"Computer Name" = $computerSystem.Name
"Operating System" = $computerOS.caption + ", Service Pack: " + $computerOS.ServicePackMajorVersion
"Manufacturer" = $computerSystem.Manufacturer
"Model" = $computerSystem.Model
"Serial Number" = $computerBIOS.SerialNumber
"CPU" = $computerCPU.Name
"HDD Capacity" = "{0:N2}" -f ($computerHDD.Size/1GB) + "GB"
"RAM" = "{0:N2}" -f ($computerSystem.TotalPhysicalMemory/1GB) + "GB"
"User logged In" = $computerSystem.UserName
}
}
$Object | Export-Csv -append -force /Computer.csv -NoTypeInformation
Something does not seem right with your code. You should be adding each monitor to an array or a list.
$monitors = Get-WmiObject -Namespace root\wmi -Class wmiMonitorID
$allMonitors = #()
Get-CimInstance -Namespace root\wmi -ClassName wmimonitorid -ComputerName $ComputerName |
foreach {
$Object = [PSCustomObject]#{
MonitorName = ($monitors.UserFriendlyName -notmatch '^0$' | foreach {[char]$_}) -join ""
MonitorSerial = ($monitors.serialnumberid -notmatch '^0$' | foreach {[char]$_}) -join ""
}
$allMonitors += $Object
}
$allMonitors | Select MonitorName,MonitorSerial
$allMonitors | Export-Csv -append -force /Computer.csv -NoTypeInformation

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
}
}
}

powershell drives calculator

So I have the below code which works quite well but for some reason it's only calculating my D: drive and not also my C: drive?
$computerName = Get-Wmiobject Win32_ComputerSystem
$computerOS = Get-Wmiobject Win32_OperatingSystem
$computerHDD = Get-Wmiobject Win32_LogicalDisk -Filter drivetype=3
ForEach($HDD in $computerHDD){
$txtObject = New-Object PSObject -property #{
'ComputerName' = $computerName.Name
'ComputerModel' = $computerName.Model
'SerialNumber' = $computerName.SerialNumber
'HDDSize' = "{0:N2}" -f ($HDD.Size/1GB)
'HDDFree' = "{0:P2}" -f ($HDD.FreeSpace/$HDD.Size)
'OS' = $computerOS.caption
'OS_type' = $computerOS.OSArchitecture
'User' = $computerName.UserName
}
}
$txtObject | Select-Object ComputerName, ComputerModel, SerialNumber, HDDSize, HDDFree, OS, Os_type, User | Out-File "$PSSCriptRoot\computer_info.txt" -Append
seems like you would need to make an array. Try this...
$computerName = Get-Wmiobject Win32_ComputerSystem
$computerOS = Get-Wmiobject Win32_OperatingSystem
$computerHDD = Get-Wmiobject Win32_LogicalDisk -Filter drivetype=3
$output = #()
ForEach($HDD in $computerHDD){
$txtObject = New-Object PSObject -property #{
'ComputerName' = $computerName.Name
'ComputerModel' = $computerName.Model
'SerialNumber' = $computerName.SerialNumber
'HDDSize' = "{0:N2}" -f ($HDD.Size/1GB)
'HDDFree' = "{0:P2}" -f ($HDD.FreeSpace/$HDD.Size)
'OS' = $computerOS.caption
'OS_type' = $computerOS.OSArchitecture
'User' = $computerName.UserName
}
$output += $txtObject
}
$output | Select-Object ComputerName, ComputerModel, SerialNumber, HDDSize, HDDFree, OS, Os_type, User | Out-File "$PSSCriptRoot\computer_info.txt" -Append
You're overwriting $txtObject on every iteration of the loop, so your output only contains the drive from the final iteration. Instead, you should be initializing $txtObject as an array and then appending each drive's information to that:
$computerHDD = Get-Wmiobject Win32_LogicalDisk -Filter drivetype=3
$txtObject = #()
ForEach($HDD in $computerHDD){
$txtObject += New-Object PSObject -property #{
# ...
}
}
$txtObject | Select-Object ... | Out-File "$PSSCriptRoot\computer_info.txt" -Append
Better yet, you can eliminate the loop and the variable and just use the pipeline:
$computerName = Get-WmiObject Win32_ComputerSystem
$computerOS = Get-WmiObject Win32_OperatingSystem
Get-WmiObject Win32_LogicalDisk -Filter drivetype=3 `
| ForEach-Object -Process {
New-Object PSObject -Property #{
'ComputerName' = $computerName.Name
'ComputerModel' = $computerName.Model
'SerialNumber' = $computerName.SerialNumber
'HDDSize' = "{0:N2}" -f ($_.Size/1GB)
'HDDFree' = "{0:P2}" -f ($_.FreeSpace/$_.Size)
'OS' = $computerOS.caption
'OS_type' = $computerOS.OSArchitecture
'User' = $computerName.UserName
};
} | Out-File "$PSSCriptRoot\computer_info.txt" -Append
Note that New-Object above is nearly identical to your original code except $_ has to be used instead of $HDD.

PowerShell add objects to body of email

I want to be able to collect information from this script and put it in the body of an email. For the most part it seems to work except I want serialnumber, osversion, model, loggedin on different lines in the body of the email.
[CmdletBinding()]
param (
$computername = (Read-Host "Enter Computer Name"),
$subject = 'Serial Numbers',
$to = 'test#test.com',
$bcc = 'test#test.com',
$body = $Collection,
#$body = (Get-Content -path "c:\powershell\serialnumber\SerialNumber.csv"),
#$mail = "mailto:$to&subject=$subject&body=$body",
[string]$ErrorLog = 'c:\powershell\useful\errorlog\retry.txt',
[switch]$LogErrors
)
[Array]$Collection = foreach($computer in $computername)
{
$os = Get-WmiObject `
Win32_OperatingSystem -computer $computer
$bios = Get-WmiObject `
Win32_BIOS -computer $computer
$model = Get-WmiObject `
Win32_ComputerSystem -computer $computer
$Monitor = Get-WmiObject -computer $computer WmiMonitorID -Namespace root\wmi |
ForEach-Object {($_.UserFriendlyName -notmatch 0 |
foreach {[char]$_}) -join ""; ($_.SerialNumberID -notmatch 0 |
foreach {[char]$_}) -join ""}
$body = New-Object -TypeName PSObject -Property #{
Computername = $computer;
LoggedIn = $Model.username;
OSVersion = $os.Caption;
SerialNumber = $bios.SerialNumber;
Model = $Model.Model;
Monitor = $Monitor;
}
#$obj | convertTo-csv | out-string
#$obj = $body
#$Collection = [string]$body
#[String]$Collection
[string]$body
Start-Process -FilePath "mailto:$to&bcc=$bcc&subject=$subject&body=$body"
}
$Collection
You can't use an object directly as the body of an email, it must be a [string]. Try this:
$body = New-Object -TypeName PSObject -Property #{
Computername = $computer;
LoggedIn = $Model.username;
OSVersion = $os.Caption;
SerialNumber = $bios.SerialNumber;
Model = $Model.Model;
Monitor = $Monitor;
} | format-list | out-string