Single connection for multiple Get-WmiObject calls - powershell

The script below successfully obtains the manufacturer, model, serial number, and operating system from each computer I provide in hostnames.txt. However, it is slow because it must connect to WMI on each computer three times.
$OS = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer
$CS = Get-WmiObject Win32_ComputerSystem -ComputerName $Computer
$BIOS = Get-WmiObject Win32_Bios -ComputerName $Computer
Using PowerShell, how can I connect to the remote-computer's WMI once and execute the three queries using the same connection?
$Array = #() ## Create Array to hold the Data
$Computers = Get-Content -Path .\hostnames.txt
foreach ($Computer in $Computers)
{
$Result = "" | Select HostPS,Mfg,Model,Serial,OS
$Result.HostPS = $Computer
$ErrorActionPreference = "SilentlyContinue" ## Don't output errors for offline computers
$OS = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer
$CS = Get-WmiObject Win32_ComputerSystem -ComputerName $Computer
$BIOS = Get-WmiObject Win32_Bios -ComputerName $Computer
$ErrorActionPreference = "Continue"
$Result.Mfg = $CS.Manufacturer
$Result.Model = $CS.Model
$Result.Serial = $BIOS.SerialNumber
$Result.OS = $OS.Caption
$Array += $Result ## Add the data to the array
}
$Array | Export-Csv file.csv -NoTypeInformation

You can use CIM (which has a session option), more on CIM vs WMI ("WMI is the Microsoft implementation of CIM for the Windows platform")
$CIMSession = New-CimSession -ComputerName $RemoteComputer
Get-CimInstance win32_OperatingSystem -CimSession $CIMSession -Property Caption
Get-CimInstance Win32_ComputerSystem -CimSession $CIMSession -Property Manufacturer,Model
Get-CimInstance Win32_Bios -CimSession $CIMSession -Property SerialNumber

for me, the usual way to do that is to use Invoke-Command to run a script block on each target system. if you tell it to ignore errors, it will run in parallel [on the target systems] and return your data from the responders. to get the non-responders, compare the input list with the results. [grin]
here's a demo of the idea ...
#requires -RunAsAdministrator
# fake reading in a list of computer names
# in real life, use Get-Content or (Get-ADComputer).Name
$ComputerList = #'
Localhost
BetterNotBeThere
127.0.0.1
10.0.0.1
::1
'#.Split("`n").Trim("`r")
$IC_ScriptBlock = {
$CIM_ComputerSystem = Get-CimInstance -ClassName CIM_ComputerSystem
$CIM_BIOSElement = Get-CimInstance -ClassName CIM_BIOSElement
$CIM_OperatingSystem = Get-CimInstance -ClassName CIM_OperatingSystem
$CIM_Processor = Get-CimInstance -ClassName CIM_Processor
$CIM_LogicalDisk = Get-CimInstance -ClassName CIM_LogicalDisk |
Where-Object {$_.Name -eq $CIM_OperatingSystem.SystemDrive}
[PSCustomObject]#{
LocalComputerName = $env:COMPUTERNAME
Manufacturer = $CIM_ComputerSystem.Manufacturer
Model = $CIM_ComputerSystem.Model
SerialNumber = $CIM_BIOSElement.SerialNumber
CPU = $CIM_Processor.Name
RAM_GB = '{0:N2}' -f ($CIM_ComputerSystem.TotalPhysicalMemory / 1GB)
SysDrive_Capacity_GB = '{0:N2}' -f ($CIM_LogicalDisk.Size / 1GB)
SysDrive_FreeSpace_GB ='{0:N2}' -f ($CIM_LogicalDisk.FreeSpace / 1GB)
SysDrive_FreeSpace_Pct = '{0:N0}' -f ($CIM_LogicalDisk.FreeSpace / $CIM_LogicalDisk.Size * 100)
OperatingSystem_Name = $CIM_OperatingSystem.Caption
OperatingSystem_Version = $CIM_OperatingSystem.Version
OperatingSystem_BuildNumber = $CIM_OperatingSystem.BuildNumber
OperatingSystem_ServicePack = $CIM_OperatingSystem.ServicePackMajorVersion
CurrentUser = $CIM_ComputerSystem.UserName
LastBootUpTime = $CIM_OperatingSystem.LastBootUpTime
UpTime_Days = '{0:N2}' -f ([datetime]::Now - $CIM_OperatingSystem.LastBootUpTime).Days
}
}
$IC_Params = #{
ComputerName = $ComputerList
ScriptBlock = $IC_ScriptBlock
ErrorAction = 'SilentlyContinue'
}
$RespondingSystems = Invoke-Command #IC_Params
$NOT_RespondingSystems = $ComputerList.Where({
# these two variants are needed to deal with an ipv6 localhost address
"[$_]" -notin $RespondingSystems.PSComputerName -and
$_ -notin $RespondingSystems.PSComputerName
})
$RespondingSystems
$NOT_RespondingSystems
one item from the $RespondingSystems list ...
LocalComputerName : [MySystemName]
Manufacturer : System manufacturer
Model : System Product Name
SerialNumber : System Serial Number
CPU : AMD Phenom(tm) II X4 945 Processor
RAM_GB : 8.00
SysDrive_Capacity_GB : 931.41
SysDrive_FreeSpace_GB : 735.15
SysDrive_FreeSpace_Pct : 79
OperatingSystem_Name : Microsoft Windows 7 Professional
OperatingSystem_Version : 6.1.7601
OperatingSystem_BuildNumber : 7601
OperatingSystem_ServicePack : 1
CurrentUser : [MySystemName]\[MyUserName]
LastBootUpTime : 2018-10-19 7:01:51 PM
UpTime_Days : 7.00
PSComputerName : [::1]
RunspaceId : e17c2741-ba8b-4fbb-b3db-9c7fd0d84f0d
the $NOT_RespondingSystems list ...
BetterNotBeThere
10.0.0.1

Related

Powershell CSV Output Issue

Can anyone assist my with explanation as to why I get System.String[] as my Gateway output in the CSV file but it works fine in the ISE view/window.
$testcomputers = Get-Content -Path 'C:\Users2\101.txt'
$exportLocation = 'C:\Users2\PingResults.csv'
# Test connection to each computer before getting the inventory info
foreach ($computer in $testcomputers) {
if (Test-Connection -ComputerName $computer -Quiet -count 1){
Add-Content -value $computer -path C:\Users2\OnlineComputers.txt
}else{
Add-Content -value $computer -path C:\Users2\OfflineComputers.txt
}
}
#Specify the list of PC names in the line below
$ArrComputers = Get-Content -Path 'C:\Users2\OnlineComputers.txt'
Clear-Host
foreach ($Computer in $ArrComputers)
{
$computerSystem = get-wmiobject Win32_ComputerSystem -Computer $Computer
$computerBIOS = get-wmiobject Win32_BIOS -Computer $Computer
$computerOS = get-wmiobject Win32_OperatingSystem -Computer $Computer
$computerCPU = get-wmiobject Win32_Processor -Computer $Computer
$computerHDD = Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter drivetype=3
$computerGateway = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Computer $Computer -Filter “IPEnabled=TRUE”
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.ConvertToDateTime($computerOS.LastBootUpTime)
"Gateway: " + $computerGateway.DefaultIPGateway
""
"-------------------------------------------------------"
#Build the CSV file
$csvObject = New-Object PSObject -property #{
'PCName' = $computerSystem.Name
'Manufacturer' = $computerSystem.Manufacturer
'Model' = $computerSystem.Model
'Service Tag' = $computerBIOS.SerialNumber
'RAM' = "{0:N2}" -f ($computerSystem.TotalPhysicalMemory/1GB)
'HDDSize' = "{0:N2}" -f ($computerHDD.Size/1GB)
'HDDFree' = "{0:P2}" -f ($computerHDD.FreeSpace/$computerHDD.Size)
'CPU' = $computerCPU.Name
'OS' = $computerOS.caption
'SP' = $computerOS.ServicePackMajorVersion
'User' = $computerSystem.UserName
'Last_Reboot' = $computerOS.ConvertToDateTime($computerOS.LastBootUpTime)
'Gateway' = $computerGateway.DefaultIPGateway
}
#Export the fields you want from above in the specified order
$csvObject | Select PCName, Manufacturer, Model, OS, SerialNumber, CPU, Ram, User, Last_Reboot, HDDSize, HDDFree, Gateway | Export-Csv 'C:\Users2\results.csv' -NoTypeInformation -Append
}
Here is the ISE output
System Information for: WS101161
-------------------------------------------------------
Manufacturer: Dell Inc.
Model: OptiPlex 5070
Serial Number: 7HF8T13
CPU: Intel(R) Core(TM) i5-9500 CPU # 3.00GHz
HDD Capacity: 237.96GB
HDD Space: 67.87% Free (161.51GB)
RAM: 15.79GB
Operating System: Microsoft Windows 10 Pro, Service Pack: 0
User logged In:
Last Reboot: 04/28/2022 17:40:52
Gateway: 10.170.1.250
-------------------------------------------------------
And here is the CSV output (User being empty is okay, nobody is signed into this PC at the moment)
"PCName","Manufacturer","Model","OS","SerialNumber","CPU","RAM","User","Last_Reboot","HDDSize","HDDFree","Gateway"
"WS101161","Dell Inc.","OptiPlex 5070","Microsoft Windows 10 Pro",,"Intel(R) Core(TM) i5-9500 CPU # 3.00GHz","15.79",,"4/28/2022 5:40:52 PM","237.96","67.87%","System.String[]"
Thank you for the assistance!
asdasdasd
The main issue that answers your question, the property DefaultIPGateway of the Win32_NetworkAdapterConfiguration class is of the type string[]:
DefaultIPGateway
Data type: string array
You need to convert it to string so that Export-Csv can handle it:
PS /> #{ Gateway = $computerGateway[0].DefaultIPGateway } | ConvertTo-Csv
"Gateway"
"System.String[]"
PS /> #{ Gateway = [string] $computerGateway[0].DefaultIPGateway } | ConvertTo-Csv
"Gateway"
"192.168.0.1"
It is also worth noting that $computerGateway may return an array of IPs in which case you should join them:
$computerGateway.DefaultIPGateway -join ', '
Aside from that, there are other issues with your code, for example all Division operations on $computerHDD:
$computerHDD.Size / 1GB
Will throw this exception if the host has more than one Physical Disk:
InvalidOperation: Method invocation failed because [System.Object[]] does not contain a method named 'op_Division'.
Test-NetConnection is not reliable to tell you if you can or cannot connect to a remote host, there may be a firewall blocking ICMP packets and you may have been able to still connect it since the protocol being used in your code is WinRM (WinRM HTTP uses port 5985 and WinRM HTTPS uses port 5986).
Your code can also be invoked in parallel instead of going one host at a time, Invoke-Command is the best alternative as Lee_Dailey mentions in his helpful comment.
Sending information to the console (Write-Host) will only slow your script down, I've removed all instances of console output.
Appending to a file with Export-Csv -Append on each iteration of your loop will also slow your script down, the more Disk I/O the slower the code will be, it is better to collect all output first in memory and then writing to a file once.
Lastly, Get-WmiObject should be replaced by Get-CimInstance. All the WMI Cmdlets are no longer in circulation in newer versions of PowerShell (PowerShell Core). And the CIM Cmdlets have been available since PowerShell 3. No reason to use WMI over CIM.
With all that being said, this is how I would approach your script:
$unavaibleHosts = [System.Collections.Generic.List[string]]::new()
$session = foreach($computer in Get-Content -Path 'C:\Users2\101.txt') {
try {
New-PSSession $computer -ErrorAction Stop
}
catch {
$unavaibleHosts.Add($computer)
}
}
Invoke-Command -Session $session -HideComputerName -ScriptBlock {
$computerSystem = Get-CimInstance Win32_ComputerSystem
$computerBIOS = Get-CimInstance Win32_BIOS
$computerOS = Get-CimInstance Win32_OperatingSystem
$computerCPU = Get-CimInstance Win32_Processor
$computerHDD = Get-CimInstance Win32_LogicalDisk -Filter drivetype=3
$computerGateway = Get-CimInstance -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE
$hddSize = $computerHDD.ForEach{ "[{0} {1:N2}]" -f $_.DeviceID, ($_.Size / 1GB) } -join ' | '
$hddFree = $computerHDD.ForEach{ "[{0} {1:P2}]" -f $_.DeviceID, ($_.FreeSpace / $_.Size) } -join ' | '
# output from these 2 would look like this:
# HDDSize : [C: 236.76] | [D: 931.51]
# HDDFree : [C: 73.30%] | [D: 81.43%]
[pscustomobject]#{
'PCName' = $computerSystem.Name
'Manufacturer' = $computerSystem.Manufacturer
'Model' = $computerSystem.Model
'Service Tag' = $computerBIOS.SerialNumber
'RAM' = "{0:N2}" -f ($computerSystem.TotalPhysicalMemory / 1GB)
'HDDSize' = $hddSize
'HDDFree' = $hddFree
'CPU' = $computerCPU.Name
'OS' = $computerOS.caption
'SP' = $computerOS.ServicePackMajorVersion
'User' = $computerSystem.UserName
'Last_Reboot' = $computerOS.LastBootUpTime
'Gateway' = $computerGateway.DefaultIPGateway -join ','
}
} | Select-Object * -ExcludeProperty RunspaceId | Export-Csv 'C:\Users2\results.csv' -NoTypeInformation
Remove-PSSession $session
$unavaibleHosts # => Is here for you to troubleshoot the failed connections.
# https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-networkadapterconfiguration
# DefaultIPGateway
# Data type: string array
# Access type: Read-only
# Qualifiers: MappingStrings ("Win32Registry|System\\CurrentControlSet\\Services|Parameters|DefaultGateway")
# Array of IP addresses of default gateways that the computer system uses.
# Example: "192.168.12.1 192.168.46.1"
# Your case
$computerGateway = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Computer "DESKTOP-9EPNRSP" -Filter "IPEnabled=TRUE"
$csvObject = New-Object PSObject -property #{
'Gateway' = $computerGateway.DefaultIPGateway
}
$csvObject.Gateway.GetType().FullName
# Convert to String
$computerGateway = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Computer "DESKTOP-9EPNRSP" -Filter "IPEnabled=TRUE"
$csvObject = New-Object PSObject -property #{
'Gateway' = "$($computerGateway.DefaultIPGateway)"
}
$csvObject.Gateway.GetType().FullName
#Take first element
$computerGateway = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Computer "DESKTOP-9EPNRSP" -Filter "IPEnabled=TRUE"
$csvObject = New-Object PSObject -property #{
'Gateway' = $computerGateway.DefaultIPGateway[0]
}
$csvObject.Gateway.GetType().FullName
#Generate with comma sepparated - █ Recommended █
$computerGateway = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Computer "DESKTOP-9EPNRSP" -Filter "IPEnabled=TRUE"
$csvObject = New-Object PSObject -property #{
'Gateway' = [string]::Join(",", $computerGateway.DefaultIPGateway)
}
$csvObject.Gateway.GetType().FullName
Output
System.String[]
System.String
System.String
System.String

Powershell - Export csv for program name, version, installdate

im trying to run a command against a list of computers to find out information on the programs on the computers. then i would like to export that information on a Csv in the following format:
Computer name, McAfee Agent, version, Installdate
i wanted to get the list of these computers and the programs version numbers and installdate.
this command works, but not for exporting:
Get-WmiObject win32_product -ComputerName SYSTEMName01 | Where name -Match "McAfee Agent" | Select Name, Version, Installdate
I tried using the following code here, but this isn't working because it populates the information in Powershell then gives me a:
"RPC server is unavailable" red text.
and the Exported CSV document only gives me one populated row of the Name of the program and its version # and install date. but it doesn't populate the computer name it looked into and it doesn't list the other computers in the .txt document.
$computers = Get-content -Path "C:\nice\List-of-systems.txt"
Get-WmiObject win32_product -ComputerName $computers | Where name -Match "McAfee Agent" | Select Name, Version, Installdate |
Export-Csv -Path "C:\nice\computers-mcafee-status.csv"
If you're gonna go through the trouble of just querying single information, might as well query the system info a long with it.
<#
SYNTAX
Get-SystemInfo [[-ComputerName] <string[]>] [<CommonParameters>]
EXAMPLE
Get-SystemInfo -ComputerName SystemOne, SystemTwo
'SystemOne', 'SystemTwo' | Get-SystemInfo
Get-content -Path "C:\nice\List-of-systems.txt" | Get-SystemInfo
Get-content -Path "C:\nice\List-of-systems.txt" | Get-SystemInfo | Export-CSV C:\List-Of-Systems.csv -NoTypeInformation
#>
Function Get-SystemInfo{
[CmdletBinding()]
Param(
[Parameter(Mandatory=$False,
ValueFromPipeLine=$True,
ValueFromPipelineByPropertyName=$true,
HelpMessage='Enter Computer Name')]
[Alias('CN','Name')]
[String[]]$ComputerName = $env:COMPUTERNAME)
Process{
try{
#$ExportPath = "C:\nice\computers-mcafee-status.csv"
#if(-Not(Test-Path -Path '$ExportPath')){
#New-Item '$ExportPath' -ItemType File }
foreach($Computer in $ComputerName){
$CIMSession = New-CimSession -ComputerName $Computer -ErrorAction Stop
#$OS = Get-CimInstance -CimSession $CIMSession -Namespace Root/CIMv2 -ClassName WIN32_OperatingSystem -ErrorAction SilentlyContinue
$CS = Get-CimInstance -CimSession $CIMSession -Namespace Root/CIMv2 -ClassName WIN32_ComputerSystem -Property Model,Manufacturer,Username -ErrorAction SilentlyContinue
$BS = Get-CimInstance -CimSession $CIMSession -Namespace Root/CIMv2 -ClassName WIN32_BIOS -ErrorAction SilentlyContinue
$MAC = Get-CimInstance -CimSession $CIMSession -Namespace Root/CIMv2 -ClassName WIN32_NetworkAdapterConfiguration | Where-Object -Property Description -Like "*Ethernet*"
$MA = Get-CimInstance -CimSession $CIMSession -Namespace Root/CIMv2 -ClassName WIN32_Product | Where-Object Name -Match "McAfee Agent" -ErrorAction SilentlyContinue
[PSCustomobject] #{
"Computer Name" = $Computer
"Status" = "Online"
"Manufacturer" = if($CS.Manufacturer){$CS.Manufacturer}Else{"Unable to get Manufacturer"}
"Model" = if($CS.Model){$CS.Model}Else{"Unable to get Model"}
"User Logged in" = if($cs.UserName){$cs.UserName}Else{"No user logged in"}
"Serial Number" = if($BS.SerialNumber){$BS.SerialNumber}Else{"Unable to get Serial #"}
"MAC Address" = if($MAC.MACAddress){$MAC.MACAddress}Else{"Unable to get MAC Address"}
"McAfee InstallDate" = if($MA.InstallDate){$MA.InstallDate}Else{"Unable to get InstallDate"}
"McAfee Version" = if($Ma.Version){$MA.Version}Else{"Unable to get Version"}
} #| Export-Csv -Path '$ExportPath' -Append -NoTypeInformation
}
} Catch [Microsoft.Management.Infrastructure.CimException] {
[PSCustomobject] #{
"Computer Name" = $Computer
"Status" = "Offline"
"Manufacturer" = $null
"Model" = $null
"User Logged in" = $null
"Serial Number" = $null
"MAC Address" = $null
"McAfee InstallDate" = $null
"McAfee Version" = $null
} #| Export-Csv -Path '$ExportPath' -Append -NoTypeInformation
} Finally {
if($CIMSession){
Get-CimSession | Remove-CimSession
}
}
}
}
The issue with what you're trying to do is, you're not including the computername to be exported along with the other information. You also need to -Append to the file. The errors you receive mean that you just couldn't connect to the remote machine.

Display computer information for all computers in AD

Hi i've got a script that gets computer information. I have placed defined the different get values within a variable. And then created a hashtable where i call upon different properties within the variables. This part works fine for a single computer.
I want to get these information for all computer within the domain, but don't know how?
I've been thinking that you could define a variable that contains all AD computers, and then use a foreach statement to cycle through them, but can't get it to work.
How can i output this information information for all computers within the AD, anybody got any pointers?
Thanks in advance
$System =Get-WmiObject WIN32_ComputerSystem
$OS = Get-CimInstance WIN32_OperatingSystem
$Core = Get-WmiObject win32_processor
$GPU = Get-WmiObject WIN32_VideoController
$Disk = get-WmiObject win32_logicaldisk
$ADComps = Get-ADComputer -Filter *
foreach($i in $ADComps){
$hashtable = #{
CPU_Cores = $Core.NumberOfCores
CPU_Model = $Core.Caption
Ram = $System.TotalPhysicalMemory
GPU = $GPU.Caption
OSD = $OS.InstallDate
OS = $OS.Caption
Model = $System.Model
Computer_Producent = $System.Manufacturer
Computer_Name = $System.Name
}
}
Get-WmiObject and Get-CimInstance only queries the WMI service on one machine at a time, so you need to repeat the calls for each machine:
$ADComps = Get-ADComputer -Filter *
foreach($Comp in $ADComps){
$System = Get-WmiObject WIN32_ComputerSystem -ComputerName $Comp.DNSHostName
$OS = Get-CimInstance WIN32_OperatingSystem -ComputerName $Comp.DNSHostName
$Core = Get-WmiObject win32_processor -ComputerName $Comp.DNSHostName
$GPU = Get-WmiObject WIN32_VideoController -ComputerName $Comp.DNSHostName
$Disk = get-WmiObject win32_logicaldisk -ComputerName $Comp.DNSHostName
$hashtable = #{
CPU_Cores = $Core.NumberOfCores
CPU_Model = $Core.Caption
Ram = $System.TotalPhysicalMemory
GPU = $GPU.Caption
OSD = $OS.InstallDate
OS = $OS.Caption
Model = $System.Model
Computer_Producent = $System.Manufacturer
Computer_Name = $System.Name
}
}
Get-WmiObject defaults to querying to remote machine using RPC, if that's blocked in the network you might want to use Invoke-Command to run the queries on the remote machine and then return the resulting object:
$ADComps = Get-ADComputer -Filter *
foreach($Comp in $ADComps){
Invoke-Command -ComputerName $Comp.DNSHostName {
$System = Get-WmiObject WIN32_ComputerSystem
$OS = Get-CimInstance WIN32_OperatingSystem
$Core = Get-WmiObject win32_processor
$GPU = Get-WmiObject WIN32_VideoController
$Disk = get-WmiObject win32_logicaldisk
$hashtable = #{
CPU_Cores = $Core.NumberOfCores
CPU_Model = $Core.Caption
Ram = $System.TotalPhysicalMemory
GPU = $GPU.Caption
OSD = $OS.InstallDate
OS = $OS.Caption
Model = $System.Model
Computer_Producent = $System.Manufacturer
Computer_Name = $System.Name
}
return [pscustomobject]$hashtable
}
}

Powershell script in columns instead of rows

I was trying to write a script which would use a text file with hostnames and needs to generate a file with the extra data. I can only manage to get it in rows instead of columns:
Model:
Bios Version:
TPM OEM Ver:
User logged In:
I would also like to get the emailaddress from the logged on user. I was thinking to use get-aduser. Could I add another foreach after the current code, using the column with the usernames? How would I do this?
All help is greatly appreciated!
My code is:
$output = foreach ($hostname in Get-Content C:\temp\hostnames.txt)
{
$computerinfo = get-ciminstance -computername $hostname Win32_ComputerSystem
$computerBIOS = get-ciminstance -computername $hostname Win32_BIOS
$tpm = Get-ciminstance -class Win32_Tpm -namespace root\CIMV2\Security\MicrosoftTpm -ComputerName $hostname
"Hostname: " + $computerinfo.name
"Model: " + $computerinfo.Model
"Bios Version: " + $computerBIOS.smbiosbiosversion
"TPM OEM Ver: " + $tpm.ManufacturerVersion
"User logged In: " + $computerinfo.UserName
}
$output | out-file 'C:\Temp\hostnames3.txt' -append
You should use the CSV file format instead of plain text for structured data. That makes it easier to use them for further steps if needed.
$output =
foreach ($hostname in Get-Content C:\temp\hostnames.txt) {
$computerinfo = Get-CimInstance -ComputerName $hostname -ClassName Win32_ComputerSystem
$computerBIOS = Get-CimInstance -ComputerName $hostname -ClassName Win32_BIOS
$tpm = Get-CimInstance -Namespace root\CIMV2\Security\MicrosoftTpm -ComputerName $hostname -ClassName Win32_Tpm
[PSCustomObject]#{
Hostname = $computerinfo.name
Model = $computerinfo.Model
Bios_Version = $computerBIOS.smbiosbiosversion
TPM_OEM_Ver = $tpm.ManufacturerVersion
User_logged_In = $computerinfo.UserName
}
}
$output |
Export-Csv -Path 'C:\Temp\hostnames3.csv' -NoTypeInformation
In my experience the UserName property of the CIM-Class Win32_ComputerSystem is unreliable to determine the logged on user. I usually use good old quser.exe like this:
$UserQuery = ( C:\Windows\System32\quser.exe /server:$hostname 2> null)
if ($UserQuery) {
$UserQuery[1].Trim() -match "^(\S+)\s+.*((\d{2}\.){2}\d{4}\s+\d{2}:\d{2})" | Out-Null
$LoggedOnUser = $Matches[1]
$LogonTime = Get-Date -Date $Matches[2]
}
Then you can use $LoggedOnUser and $LogonTime to include it in your output object if you like.
Of course you can include a additional AD query for more information about the logged on user.

get-process product version remote computer

If I locally do this I get all the information:
get-process | select-object name,fileversion,company
However, if I do it on a remote computer I only get the process name and all the other fields are blank. Does anyone know why or how to get the same information. I am using a domain admin credential so I should have access to that information.
get-process -computername xcomp123 | select-object name,fileversion,company
You can try this solution:
$Computername = 'Remotehost'
$Session = New-CimSession -ComputerName $Computername
$process = Get-CimInstance -ClassName Win32_Process -CimSession $Session
$col = New-Object System.Collections.ArrayList
foreach ($n in $process){
$exePath = $null
$ExeInfo = $null
$exePath = $n.ExecutablePath -Replace '\\','\\'
$ExeInfo = Get-CimInstance -ClassName Cim_DataFile -Filter "Name = '$exePath'" -ErrorAction SilentlyContinue
[void]$col.add([PSCustomObject]#{
Name = $n.name
FileVersion = $ExeInfo.Version
Company = $ExeInfo.Manufacturer
PSComputername = $n.PSComputername
})
}
Remove-Cimsession $session
$col
Update:
I reduced the code to check for one process only. I assert the referencefile having the same name, as the process on the client computers. You might change that for your needs.
You can specify multiple computers at $computername, so you do not have to run the code over and over again.
#region Reference file
$RefFile = Get-item "\\x123\c$\program files\prog\winagent\file.exe"
#endregion
#region remote file
[string[]]$Computername = 'Remotehost1', 'Remotehost2'
$Processname = $RefFile.Name
foreach ($n in $Computername) {
$Session = New-CimSession -ComputerName $n
$process = Get-CimInstance -ClassName Win32_Process -CimSession $Session -Filter "name = '$Processname'"
$exePath = $process.ExecutablePath -Replace '\\', '\\'
$ExeInfo = Get-CimInstance -ClassName Cim_DataFile -Filter "Name = '$exePath'" -ErrorAction SilentlyContinue
[PSCustomObject]#{
Name = $Processname
FileVersion = $ExeInfo.Version
Company = $ExeInfo.Manufacturer
PSComputername = $n
}
Remove-Cimsession $session
}
#endregion