Error handling with Get-wmiObject for pscustomobject in Powershell - powershell

Building this script I want to have the output stored in a TXT file and leave the details blank which cannot be found.
It works for the Get-ADuser function but not for Get-wmiObject.
I've got my PC names and user ids from a CSV file but sometimes a user doesn't have a PC or the workstation is not turned on so I get no output. Then I want to leave those details blank.
I've tried with try and catch but it seems not working. Any advice?
$userName1 = "UserX"
$Computernames = Import-CSV 'C:\PCnames.csv' -Delimiter ';'
$pcName = $Computernames.Where({ $_."User ID" -match $userName1})."PC Name"
$aProperties = #(
'Name'
'mail'
'OfficePhone'
'Description'
'PasswordLastSet'
'LastBadPasswordAttempt'
'LockedOut'
'Enabled'
'msDS-UserPasswordExpiryTimeComputed'
)
$aUser = Get-Aduser -Identity $userName1 -Properties $aProperties
$aUser
$IP = try {Get-WmiObject Win32_NetworkAdapterConfiguration -Computername $pcName -ea stop |
Where { $_.IPAddress } |
Select -Expand IPAddress |
Where { $_ -like '10.33*' -or $_ -like '10.44*'} }
catch {""}
$Model = try { (Get-WmiObject -Class Win32_ComputerSystem -ComputerName $pcName -ea stop ).Model}
catch {""}
$OS =try { Get-WmiObject win32_operatingsystem -Computername $pcName -ea stop | select csname, #{LABEL='LastBootUpTime';EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}}
catch{""}
[pscustomobject]#{ UserID = $aUser.Name
Mail = $aUser.mail
Phone = $aUser.OfficePhone
Hostname = $pcName
LockedStatus = $aUser.LockedOut
AccountEnabled = $aUser.Enabled
LastBadPasswordAttempt = $aUser.LastBadPasswordAttempt
OSVersion = $OSVersion.Version
OSName = $OSVersion.Name
IPAddress = $IP
Model = $Model }

Related

Get Computer description and last logged on user from OU

How do I get a list of computers in a particular OU along with the Description and Last logged on user in a .csv?
$userName = (Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $machine -ErrorAction:SilentlyContinue).UserName
$DisComp = Get-ADComputer -LDAPFilter "(Name=LN-*)" -SearchBase "OU=Computers - Disabled,DC=XXXXX,DC=com" | Select-Object Name
$results = foreach ($Machine in $DisComp) {
$Description = Get-AdComputer -Identity $Machine -Properties * | Select-Object Description
$UserName
$Machine
$Description
}
$results | Export-Csv -Path C:\XXXXX
Define the OU and CSV file paths
$ouPath = "OU=Workstations,DC=contoso,DC=com"
$csvPath = "C:\temp\computer-list.csv"
Use the Get-ADComputer cmdlet to get a list of computers in the OU
$computers = Get-ADComputer -SearchBase $ouPath -Filter * -Properties lastlogondate,description
Loop through each computer and get the description and last logged on user
foreach ($computer in $computers) {
$description = $computer.Description
$lastLoggedOnUser = $computer.LastLogonUser
$data = [PSCustomObject]#{
"Computer Name" = $computer.Name
"Description" = $description
"Last Logged On User" = $lastLoggedOnUser
}
Add the computer data to the CSV file
$data | Export-Csv -Path $csvPath -Append -NoTypeInformation
}
AFAIK there is no AD computer property called LastLogonUser or any other property that holds this information.
To get the user that last logged on, you need to query the windows Eventlog on that computer and search for events with ID 4672
As aside, don't use -Properties * if all you want on top of the default properties returned is the Description property.
Try:
$searchBase = "OU=Computers - Disabled,DC=XXXXX,DC=com"
$Computers = Get-ADComputer -LDAPFilter "(Name=LN-*)" -SearchBase $searchBase -Properties Description
$results = foreach ($machine in $Computers) {
# to get the username who last logged on, you need to query the Security log
$events = Get-WinEvent -ComputerName $machine.NameĀ -FilterHashtable #{Logname='Security';ID=4672} -MaxEvents 50 -ErrorAction SilentlyContinue
$lastLogon = if ($events) {
(($events | Where-Object {$_.Properties[1].Value -notmatch 'SYSTEM|NETWORK SERVICE|LOCAL SERVICE'})[0]).Properties[1].Value
}
else {
"Unknown"
}
# output an object
[PsCustomObject]#{
ComputerName = $machine.Name
Description = $machine.Description
LastLoggedOnUser = $lastLogon
CurrentUser = (Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $machine.Name -ErrorAction SilentlyContinue).UserName
}
}
$results | Export-Csv -Path 'C:\Somewhere\Computers.csv' -NoTypeInformation
P.S. You of course need admin permissions to query the eventlog, so perhaps (if you are not a domain admin) you need to use the -Credential parameter on the Get-WinEvent line aswell.

PowerShell not running all lines in Function

Below Function is not running the lines "If ($script:AADServersTable)" down... I have put a write-host and that is working, however the variables are not working below that
Function get-AADVariables
{
$script:AADServersTable = New-Object 'System.Collections.Generic.List[System.Object]'
$scriptBlockaadinstalled = {
Get-WmiObject -Class Win32_Product |
where name -eq "Microsoft Azure AD Connect synchronization services" | select Name, Version}
##$scriptBlockaadinstalled = {hostname}
Import-Module ActiveDirectory
$servers = Get-ADComputer -Filter 'operatingsystem -like "*server*" -and enabled -eq "true"' | Select-Object -Property Name -ExcludeProperty Release
## just a single invoke-command
foreach ($server in $servers) {
$aadinstalledresults = Invoke-Command -ComputerName $server.name -ScriptBlock $scriptBlockaadinstalled ##-HideComputerName
$aadinstalledresults = $aadinstalledresults.PSComputerName
$script:AADServersTable.Add($aadinstalledresults)
}
If ($script:AADServersTable) {
Write-Host 'working'
$AADServers = ($script:AADServersTable | Group-Object -NoElement).Name | Get-Unique
$AADServers = $AADServers -split "`n"
$AADServer = $AADServers[0]
$StandByAADServer = $AADServers[1]
$SecondStandByAADServer = $AADServers[2]
}
}

Format output in Powershell

I have a small code in my script that is working well. I'm just annoyed with the output..
My output looks like this:
11.11.111.123
Model
-----
HP ZBook Studio G5
csname : XXXXXXX
LastBootUpTime : 22/Apr/2022 08:10:57
But I want it like this:
IP Address: 11.11.111.123
Model: HP ZBook Studio G5
csname: xxxxx
LastBootUpTime: 22/Apr/2022 08:10:57
This is the script:
Get-WmiObject Win32_NetworkAdapterConfiguration -Computername $pcName |
Where { $_.IPAddress } |
Select -Expand IPAddress |
Where { $_ -like '10.11*' -or $_ -like '10.12*'}
Get-WmiObject -Class Win32_ComputerSystem -Computername $pcName | Select Model
Get-WmiObject win32_operatingsystem -Computername $pcName -ea stop | select csname, #{LABEL='LastBootUpTime';EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}} | format-list
Since the output is produced by 3 different classes the way around it is create a new object to merge them:
$IPs = Get-CimInstance Win32_NetworkAdapterConfiguration -ComputerName $pcName |
Where-Object { $_.IPAddress -like '10.11*' -or $_.IPAddress -like '10.12*' }
$Model = (Get-CimInstance -Class Win32_ComputerSystem -ComputerName $pcName).Model
$OS = Get-CimInstance win32_operatingsystem -EA Stop -ComputerName $pcName
[pscustomobject]#{
'IP Address' = $IPs.IpAddress -join ', '
Model = $Model
csname = $OS.CSName
LastBootUpTime = $OS.LastBootUpTime.ToString()
}

i trying to collect different info with Get-ADComputer, Get-WmiObject and Get-windowsfeature

I am trying to collect different properties from all computer listed from my AD but I can't get format to recolected querys
I run get-adcomputer query
$computerList = Get-ADComputer -Filter 'Name -like "SCPW*" -and ObjectClass -eq "Computer"' | Select-Object -Property Name,objectClass`
I collect info from al computer listed in $computerlist
$list = foreach ($computer in $computerList) {Get-WmiObject -Class Win32_Product | Select-Object -Property Name }
$WFeature = foreach ($computer in $computerList) {Get-windowsfeature | Where {$_.installed -Eq $true} | Select-Object -Property Name}
$Wrole = foreach ($computer in $computerList) {Get-WmiObject -Class Win32_ServerFeature -Property * | select pscomputername,name }
Finally I try to list all info collected in a unique table with
%{[PSCustomObject]#{
'ComputerName' = $computer.Name
'features' = $WFeature.name
'Role' = $Wrole.name
'list' = $list.name
} } | Format-table
but the table listed is only in one line
ComputerName features Role list
------------ -------- ---- ----
SCPWEXC0101 {File-Services, FS-FileServer, Remote-Desktop-Services, RDS-RD-Server...} {Web Server (IIS), File Services, Print and Document Services, Remote Desktop Services...} {Microsoft Ap...
the table listed only in one line (screenshot)
I really will be much gratefull if somebody give me some help, I'm learning PS and I really lossed with this query. I've been running Ps 5.1
Thanks!!
You will have to put the queries inside a loop for each single computer to keep the correlation between the collected information and the computer name. Something like this should get you started:
$computerList = Get-ADComputer -Filter 'Name -like "SCPW*" -and ObjectClass -eq "Computer"'
$Result =
foreach ($computer in $computerList) {
$CimSession = New-CimSession -ComputerName $computer.name
[PSCustomObject]#{
ComputerName = $computer.Name
WindowsFeatureList = (Get-windowsfeature -ComputerName $computer.name | Where-Object { $_.installed } | Select-Object -Property Name) -join ', '
W32ServerFeatureList = (Get-CimInstance -CimSession $CimSession -ClassName Win32_ServerFeature | Select-Object -Property Name) -join ', '
W32ProductList = (Get-CimInstance -CimSession $CimSession -ClassName Win32_Product | Select-Object -Property Name) -join ', '
}
}
$Result

Use WMI to convert a remote SID to username

I am using Invoke-WMIMethod to identify all SIDS beginning with S-1-5-21, like so (thanks to Mathias R. Jessen):
$Keys = Invoke-WmiMethod -Path $ClassPath -Name EnumKey -ArgumentList 2147483651,''
| Select-Object -ExpandProperty sNames | Where-Object {$_ -match 'S-1-5-21-[\d\-]+$'}
I want to convert these SIDs from the remote system to usernames on the remote system using WMI. Is this possible through WMI or Invoke-WmiMethod?
You can use the Win32_SID class to obtain the account name:
foreach($Key in $Keys)
{
$SID = [wmi]"\\$RemoteComputer\root\cimv2:Win32_SID.SID=$Key"
New-Object psobject -Property #{
SID = $Key
Username = $SID.ReferencedDomainName,$SID.AccountName -join '\'
}
}
Rather than grabbing from the registry you could get the same information from the Win32_UserProfile provider. Then if folder name is good enough, consider something like this:
$Computer = "ExampleComputer"
Get-WMIObject Win32_UserProfile -Filter "SID like 'S-1-5-21-*'" -ComputerName $Computer |
select SID,#{name=LocalPath;Expression={Split-Path -leaf $_.LocalPath}}
Otherwise Win32_UserAccount exists but can be really slow with a large domain.
$Computer = "ExampleComputer"
$SIDs = Get-WMIObject Win32_UserProfile -Filter "SID like 'S-1-5-21-*'" -ComputerName $Computer | select -ExpandProperty SID
$UserAccounts = Get-WMIObject Win32_UserAccount -ComputerName $Computer
foreach ($SID in $SIDs) {
foreach ($Account in $UserAccounts) {
If ($SID -eq $Account.SID) {
$Account
}
}
}