SystemInfo.psm1
<#
.SYNOPSIS Very fast displays system information on a local or remote computer. .DESCRIPTION The function uses WMI to collect information related to the characteristics of the computer The function uses multithreading. Multithreading is implemented through powershell runspace and WMI Job The function allows you to quickly get the system information of a large number of computers on the network After executing, two variables are created: $Result-contains successful queries, $ErrorResult-contains computers that have errors. .PARAMETER MaxJob Specifies the maximum number of WMI and Runspace operations that can be executed simultaneously. By default, the value of this parameter is 254. .PARAMETER JobTimeout Specifies the amount of time that the function waits for a response from the wmi job or runspace job. By default, the value of this parameter is 120 seconds. .PARAMETER AppendToResult Adds the output to the $Result global variable. Without this parameter, $Result global variable replaces. .PARAMETER Credential Specifies a user account that has permission to perform this action. The default is the current user. Type a user n ame, such as "User01", "Domain01\User01", or User@domain01.com. Or, enter a PSCredential object, such as an object t hat is returned by the Get-Credential cmdlet. When you type a user name, you are prompted for a password. .PARAMETER ShowStatistics Show statistics information .EXAMPLE Get-SystemInfo ComputerName : Localhost OsCaption : Майкрософт Windows 10 Pro OsArchitecture : 64-разрядная OsUpTime : 10:1:17:41 OsLoggedInUser : Domain\Username CPUName : Intel(R) Core(TM) i3-2105 CPU @ 3.10GHz MotherboardModel : H61M-S1 DeviceModel : To be filled by O.E.M. MemoryTotal : 4,0Gb MemoryModules : Capacity MemoryType Speed Manufacturer PartNumber -------- ---------- ----- ------------ ---------- 2Gb DDR3 1333 Kingston 99U5595-005.A00LF 2Gb DDR3 1333 Kingston 99U5595-005.A00LF HddDevices : Size InterfaceType Model PredictFailure ---- ------------- ----- -------------- 112Gb IDE KINGSTON SHFS37A120G ATA Device False 149Gb IDE ST3160813AS ATA Device False VideoModel : Intel(R) HD Graphics 3000 MonitorName : E2042 CdRom : TSSTcorp CDDVDW SH-222BB This command get the system information on the local computer. .EXAMPLE Get-SystemInfo -Computername comp1,comp2,comp3 This command receives system information from computers comp1, comp2, comp3. By default, the current account must be a member of the Administrators group on the remote computer. .EXAMPLE 1..254 | foreach {"192.168.1.$_"} | Get-SystemInfo -Properties OsCaption,OSArchitecture,OsInstallDate -Credential Domain01\administrator01 | Out-GridView Get OsCaption, OSArchitecture, OsInstallDate from the computers that are in the 192.168.1.0/24 network and sends them to a grid view window. This command uses the Credential parameter. The value of the Credential parameter is a user account name. The user is prompted for a password. .EXAMPLE Get-ADComputer -Filter * | Get-SystemInfo -Cpu -Motherboard -Memory -Properties OsVersion,OsProductKey -MaxJob 100 -JobTimeOut 30 Get CPU, Motherboard, Memory and OsVersion, OsProductKey information from all domain computers. The module activedirectory must be installed and loaded. This command uses MaxJob and JobTimeOut parameter. .EXAMPLE Get-SystemInfo -RegistryKey "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" -RegistryValue SMB1 -RegistryValueType GetDWORDValue This command gets the SMB1 registry value If errors occur, such as timeout expired or other errors. After some time, you can repeat the command for computers that have had errors.To do this, you need to use the variable $ErrorResult and -AppendToResult parameter to add the result to a variable $Result. PS C:\>$ErrorResult | Get-SystemInfo -RegistryKey "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" -RegistryValue SMB1 -RegistryValueType GetDWORDValue -AppendToResult .EXAMPLE Get-Content -Path C:\Computers.txt | Get-SystemInfo -Properties MemoryTotal,OsLoggedInUser -WarningAction SilentlyContinue | Where-Object {$_.memorytotal -lt 1.5gb} This command gets computers that have a RAM size less than 1.5 gb. List of computers is taken from the file C:\Computers.txt. This command use parameter -WarningAction SilentlyContinue to ignore warning. .EXAMPLE Get-Content -Path C:\Computers.txt | Get-SystemInfo -Properties OsLoggedInUser,HddSmart | Where-Object {$_.hddsmart.smartstatus -eq "Critical" -or $_.hddsmart.smartstatus -eq "Warning"} This command gets computers that have hard disk problems .EXAMPLE $Computers=Get-Content -Path C:\Computers.txt Get-SystemInfo -Computername $Computers | ConvertTo-Html -Head "SystemInformation" | Out-File -FilePath C:\report.html This command create html report .NOTES Author: SAGSA https://github.com/SAGSA/SystemInfo Requires: Powershell 2.0 #> function Get-SystemInfo { [CmdletBinding()] param( [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true,Position=0)] [Alias('CN','Computername','DnsHostname')] [string[]]$Name="127.0.0.1", [switch]$OsInfo, [switch]$Cpu, [switch]$Motherboard, [switch]$Memory, [switch]$HDD, [switch]$Video, [switch]$Monitor, [switch]$NetworkAdapter, [switch]$PrinterInfo, [switch]$UsbDevices, [switch]$SoftwareList, [string]$RegistryKey, [string]$RegistryValue, [ValidateSet("GetStringValue","GetBinaryValue","GetDWORDValue")] [string]$RegistryValueType, $Credential, [Alias("ThrottleLimit")] [ValidateRange(1,1000)] [int]$MaxJob=254, [Alias("Timeout")] [ValidateRange(1,6000)] [int]$JobTimeOut=120, [switch]$AppendToResult, [switch]$ShowStatistics, [ValidateSet("*","OsVersion","OSArchitecture","OsCaption","OsInstallDate","OsUpTime","OsLoggedInUser","OsProductKey","MemoryTotal","MemoryFree","MemoryModules","MemoryModInsCount", "MemoryMaxIns","MemorySlots","ECCType","MemoryAvailable","Motherboard","MotherboardModel","DeviceModel","Cdrom","CdromMediatype","HddDevices","HddDevCount","HDDSmart", "HddSmartStatus","VideoModel","VideoRam","VideoProcessor","CPUName","CPUSocket","MaxClockSpeed","CPUCores","CPULogicalCore","MonitorManuf", "MonitorPCode","MonitorSN","MonitorName","MonitorYear","NetPhysAdapCount","NetworkAdapters","Printers","IsPrintServer","UsbConPrOnline","UsbDevices","CPULoad","SoftwareList","RegistryValue","OsAdministrators","OsActivationStatus")] [array]$Properties ) begin { #Config ################################################################################################################################# #Default Information (information output when executed Get-SystemInfo without parameters) $DefaultInfoConfig="OsCaption","OsArchitecture","OsUpTime","OsLoggedInUser","CPUName","MotherboardModel","DeviceModel","MemoryTotal","MemoryModules","HddDevices","VideoModel","MonitorName","CdRom" #FunctionConfig $FunctionConfig=@{ OsVersion= '-Class Win32_OperatingSystem -Property Version' OsCaption= '-Class Win32_OperatingSystem -Property Caption' OSArchitecture= '-Class Win32_OperatingSystem -Property OSArchitecture' OsInstallDate= '-Class Win32_OperatingSystem -ScriptBlock $SBOsInstalldate' OsUpTime= '-Class Win32_OperatingSystem -ScriptBlock $SbOsUpTime' MemoryTotal= '-Class Win32_PhysicalMemory -ScriptBlock $SbMemoryTotal' MemoryAvailable= '-Class Win32_OperatingSystem -ScriptBlock $SbMemoryAvailable' MemoryFree= '-Class Win32_OperatingSystem -ScriptBlock $SbMemoryFree' MemoryModules= '-Class Win32_PhysicalMemory -ScriptBlock $SbMemoryModules' MemoryModInsCount= '-Class Win32_PhysicalMemory -ScriptBlock $SbMemoryModInsCount' MemoryMaxIns= '-Class Win32_PhysicalMemoryArray -ScriptBlock $SbMemoryMaxIns' MemorySlots= '-Class Win32_PhysicalMemoryArray -ScriptBlock $SbMemorySlots' ECCType= '-Class Win32_PhysicalMemoryArray -ScriptBlock $SbECCType' Motherboard= '-Class Win32_BaseBoard -Property Manufacturer' MotherboardModel= '-Class Win32_BaseBoard -Property Product' DeviceModel= '-Class Win32_Computersystem -Property model' Cdrom= '-Class Win32_CDROmDrive -Property Caption' CdromMediatype= '-Class Win32_CDROMDrive -Property MediaType' HddDevices= '-Class Win32_DiskDrive,MSStorageDriver_FailurePredictStatus,MSStorageDriver_FailurePredictData -ScriptBlock $SbHddDevices' HddDevCount= '-Class Win32_DiskDrive -ScriptBlock $SbHddDevCount' HddPredictFailure= '-Class MSStorageDriver_FailurePredictStatus -Property PredictFailure' VideoModel= '-Class Win32_VideoController -ScriptBlock $SbVideoModel' VideoRam= '-Class Win32_VideoController -ScriptBlock $SbVideoRamMb' VideoProcessor= '-Class Win32_VideoController -ScriptBlock $SbVideoProcessor' CPUName= '-Class Win32_Processor -Property Name' CPUSocket= '-Class Win32_Processor -Property SocketDesignation' MaxClockSpeed= '-Class Win32_Processor -Property MaxClockSpeed' CPUCores= '-Class Win32_Processor -Property NumberOfCores' CPULogicalCore= '-Class Win32_Processor -Property NumberOfLogicalProcessors' CPULoad= '-Class Win32_Processor -Property LoadPercentage' MonitorManuf= '-Class wmiMonitorID -ScriptBlock $SBMonitorManuf' MonitorPCode= '-Class wmiMonitorID -ScriptBlock $SBMonPCode' MonitorSN= '-Class wmiMonitorID -ScriptBlock $SbMonSn' MonitorName= '-Class wmiMonitorID -ScriptBlock $SbMonName' MonitorYear= '-Class wmiMonitorID -Property YearOfManufacture' NetworkAdapters= '-Class Win32_NetworkAdapterConfiguration -ScriptBlock $SbNetworkAdapters' NetPhysAdapCount= '-Class Win32_NetworkAdapter -ScriptBlock $SbNetPhysAdapCount' Printers= '-Class Win32_Printer -ScriptBlock $SbPrinters' UsbConPrCount= '-Class Win32_Printer -ScriptBlock $SbUsbConPrCount' IsPrintServer= '-Class Win32_Printer -ScriptBlock $SbIsPrintServer' UsbConPrOnline= '-Class Win32_Printer -ScriptBlock $SbUsbConPrOnline' UsbDevices= '-Class Win32_USBControllerDevice -ScriptBlock $SbUsbDevices' RegistryValue= '-Class StdRegProv -ScriptBlock $SbGetRegistryValue -UseRunspace -RunspaceImportVariable $RegistryKey,$RegistryValue,$RegistryValueType' SoftwareList= '-Class StdRegProv -ScriptBlock $SbSoftwareList -UseRunspace' OsProductKey= '-Class StdRegProv -ScriptBlock $SBOsProductKey -UseRunspace' OsLoggedInUser= '-Class Win32_ComputerSystem -Property UserName' OsAdministrators= '-Class Win32_OperatingSystem -Scriptblock $SbOsAdministrators -UseRunspace' OsActivationStatus= '-Query Select * From SoftwareLicensingProduct Where ApplicationID = "55c92734-d682-4d71-983e-d6ec3f16059f" And Licensestatus > 0 -ScriptBlock $SbOsActivationStatus' HDDSmart= '-Class MSStorageDriver_FailurePredictStatus,MSStorageDriver_FailurePredictData,Win32_DiskDrive -ScriptBlock $SbHddSmart' HddSmartStatus= '-Class MSStorageDriver_FailurePredictStatus,MSStorageDriver_FailurePredictData,Win32_DiskDrive -ScriptBlock $SbHddSmartStatus' } $ManualNamespace=@{ wmiMonitorID='-Namespace Root\wmi' MSStorageDriver_FailurePredictStatus='-Namespace Root\wmi' MSStorageDriver_FailurePredictData='-Namespace Root\wmi' StdRegProv='-Namespace ROOT\default -Query SELECT * FROM meta_class WHERE __class="StdRegProv"' } #End FunctionConfig ################################################################################################################################# #Config Switch Param $SwitchConfig=@{ OSInfo="OsVersion","OSArchitecture","OsCaption","OsInstallDate","OsUpTime","OsProductKey","OsLoggedInUser","OsActivationStatus",'OsAdministrators' Cpu="CPUName","CPUSocket","MaxClockSpeed","CPUCores","CPULogicalCore","CPULoad" Hdd="HddDevices","HddDevCount" Motherboard="Motherboard","MotherboardModel","DeviceModel" Memory="MemoryTotal","MemoryFree","MemoryModules","MemoryMaxIns","MemorySlots","MemoryAvailable","MemoryModInsCount","ECCType" Video="VideoModel","VideoRam","VideoProcessor" Monitor="MonitorManuf","MonitorName","MonitorPCode","MonitorSN","MonitorYear" NetworkAdapter="NetworkAdapters","NetPhysAdapCount" PrinterInfo="Printers","UsbConPrCount","IsPrintServer","UsbConPrOnline" UsbDevices="UsbDevices" SoftwareList="SoftwareList" } #Exclude switch Param $ExcludeParam="Verbose","AppendToResult","Debug","ShowStatistics" #End Config Switch Param ################################################################################################################################# $LocalComputer=$env:COMPUTERNAME,"Localhost","127.0.0.1" $AdminRequired="HDDSmart","HddDevices","HddSmartStatus" $RequiredExecutionPolicy="Unrestricted","RemoteSigned" #End Config #ScriptBlock ################################################################################################################################# [scriptblock]$SbHddSmartStatus= { GetHddSmart | foreach {$_.smartstatus} } [scriptblock]$SbHddSmart= { GetHddSmart } [scriptblock]$SbOsActivationStatus={ $ActStat=@{ "1" = "Licensed" "2" = "Out-Of-Box Grace Period" "3" = "Out-Of-Tolerance Grace Period" "4" = "Non-Genuine Grace Period" "5" = "Notification" "6" = "Extended Grace" } if ($Query_SoftwareLicensingProduct_OsActivationStatus) { $LicStat=($Query_SoftwareLicensingProduct_OsActivationStatus.Licensestatus).tostring() $Stat=$ActStat[$LicStat] if (!$Stat) { $Stat="Unknown value $($Query_SoftwareLicensingProduct_OsActivationStatus.Licensestatus)" } if ($Query_SoftwareLicensingProduct_OsActivationStatus.Description -match ".+,\s?(.+)") { $Descr=$Matches[1] } else { $Query_SoftwareLicensingProduct_OsActivationStatus.Description } $KmsPort=$Query_SoftwareLicensingProduct_OsActivationStatus.KeyManagementServicePort $KmsServer=$Query_SoftwareLicensingProduct_OsActivationStatus.KeyManagementServiceMachine if ($KmsServer -and $KmsPort) { $FullKms=$KmsServer+":"+$KmsPort } else { $FullKms=$null } } else { $Stat="Unlicensed or Unknown" } $Prop=@{ "Status"=$Stat "Description"=$Descr } if ($FullKms) { $Prop.Add("KMSServer",$FullKms) } $DispObj=New-Object psobject -Property $Prop $DispObj } [scriptblock]$SbOsAdministrators={ try{ $LangAdminGroups=@{ #Key https://msdn.microsoft.com/ru-ru/library/ms912047(v=winembedded.10).aspx Value Administrators Group "1049"="Администраторы" "1033"="Administrators" } $ComputerName=$Win32_OperatingSystem.__SERVER $GroupName=$LangAdminGroups["$($Win32_OperatingSystem.OSLanguage)"] if ($GroupName -eq $Null) { $GroupName="Administrators" } $wmitmp = Get-WmiObject -ComputerName $ComputerName -Query "SELECT * FROM Win32_GroupUser WHERE GroupComponent=`"Win32_Group.Domain='$ComputerName',Name='$GroupName'`"" -ErrorAction Stop if ($wmitmp -ne $null) { $DispObjArray=@() $wmitmp | foreach{ if ($_.PartComponent -match '(.+:)?(.+)\..+?="(.+?)",Name="(.+?)"') { $Type=$Matches[2] $Domain=$matches[3] $Name=$Matches[4] if ($domain -eq $computername) { $IsLocalAccount=$True } else { $IsLocalAccount=$false } $DispObj=New-Object psobject $DispObj | Add-Member -MemberType NoteProperty -Name FullName -Value "$Domain\$Name" #$DispObj | Add-Member -MemberType NoteProperty -Name Domain -Value $Domain #$DispObj | Add-Member -MemberType NoteProperty -Name Name -Value $Name $DispObj | Add-Member -MemberType NoteProperty -Name Type -Value $Type $DispObj | Add-Member -MemberType NoteProperty -Name IsLocal -Value $IsLocalAccount $DispObjArray+=$DispObj } } $DispObjArray | Sort-Object -Property IsLocal,Type } else { Write-Error -Message "Query SELECT * FROM Win32_GroupUser WHERE GroupComponent=`"Win32_Group.Domain='$ComputerName',Name='$GroupName'`" return null value. Check LangAdminGroups hashtable" -ErrorAction Stop } }catch{ $_ } } [scriptblock]$SBOsInstalldate= { [Management.ManagementDateTimeConverter]::ToDateTime($Win32_OperatingSystem.installdate) } [scriptblock]$SbOsUpTime= { $Uptime=$Win32_OperatingSystem.ConvertToDateTime($Win32_OperatingSystem.LocalDateTime) –$Win32_OperatingSystem.ConvertToDateTime($Win32_OperatingSystem.LastBootUpTime) "$($Uptime.days)"+":"+"$($Uptime.hours)"+":"+"$($Uptime.minutes)"+":"+"$($Uptime.seconds)" } [scriptblock]$SbMemoryTotal= { $Win32_PhysicalMemory | Select-Object Capacity | foreach { $MemTotalCount+=$_.capacity } $MemTotalCount } [scriptblock]$SbMemoryAvailable= { $Win32_OperatingSystem.TotalVisibleMemorySize * 1kb } [scriptblock]$SbMemoryFree= { $Win32_OperatingSystem.FreePhysicalMemory*1kb } [scriptblock]$SbMemoryModInsCount= { $count=0 $Win32_PhysicalMemory | foreach {$count++} $count } [scriptblock]$SbMemoryModules= { $MemoryTypeArray=@{ '0'='Unknown'; '1'='Other'; '2'='DRAM'; '4' ="Cache DRAM"; '5'='EDO'; '6'='EDRAM'; '7'='VRAM'; '8'='SRAM'; '9'='RAM'; '10'='ROM'; '11'='Flash'; '12'='EEPROM'; '13'='FEPROM'; '14'='EPROM'; '15'='CDRAM'; '16'='3DRAM'; '17'='SDRAM'; '18'='SGRAM'; '19'='RDRAM'; '20'='DDR'; '21'='DDR-2' '22'='DDR2 FB-DIMM' '24'='DDR3' '25'='FBD2' } #$MemModules=$Win32_PhysicalMemory | Select-Object Capacity,MemoryType,Speed,Manufacturer,PartNumber $MemModules=@() $Win32_PhysicalMemory | foreach { $Property=@{ Capacity=$_.capacity MemoryType=$MemoryTypeArray[[string]$_.memorytype] Speed=$_.speed Manufacturer=$_.Manufacturer PartNumber=$_.PartNumber } $MemModule=New-Object Psobject -Property $Property $MemModule.psobject.typenames.insert(0,"ModuleSystemInfo.SystemInfo.Memory.Modules") $MemModules+=$MemModule } $MemModules } [scriptblock]$SbMemorySlots= { $Win32_PhysicalMemoryArray | foreach {$_.memorydevices} } [scriptblock]$SbECCType= { $MemoryEccArray=@{'0'='Reserved'; '1'='Other'; '2'='Unknown'; '3'='None'; '4'='Parity'; '5'='Single-bit ECC'; '6'='Multi-bit ECC'; '7'='CRC' } $Win32_PhysicalMemoryArray| foreach{$MemoryEccArray[[string]$_.MemoryErrorCorrection]} } [scriptblock]$SbHddDevices= { $DispInfo=GetHddSmart | foreach { $Property=@{ Size=$_.Size InterfaceType=$_.InterfaceType Model=$_.Model SmartStatus=$_.SmartStatus } $TmpObj=New-Object psobject -Property $Property $TmpObj.psobject.typenames.insert(0,"ModuleSystemInfo.Systeminfo.Hdd.Devices") $TmpObj } $DispInfo } [scriptblock]$SbHddDevCount= { $count=0 $Win32_DiskDrive | foreach {$count++} $count } [scriptblock]$SbVideoModel= { $Win32_VideoController | foreach { if ($_.name -notmatch "Radmin.+" -and $_.name -notmatch "DameWare.+") { $_.name } } } [scriptblock]$SbVideoRamMb= { $Win32_VideoController | foreach { if ($_.name -notmatch "Radmin.+" -and $_.name -notmatch "DameWare.+") { $_.AdapterRAM } } } [scriptblock]$SbVideoProcessor= { $Win32_VideoController | foreach { if ($_.name -notmatch "Radmin.+" -and $_.name -notmatch "DameWare.+") { $_.VideoProcessor } } } [scriptblock]$SBMonitorManuf= { $ManufacturerHashTable = @{ "AAC" = "AcerView"; "ACR" = "Acer"; "AOC" = "AOC"; "AIC" = "AG Neovo"; "APP" = "Apple Computer"; "AST" = "AST Research"; "AUO" = "Asus"; "BNQ" = "BenQ"; "CMO" = "Acer"; "CPL" = "Compal"; "CPQ" = "Compaq"; "CPT" = "Chunghwa Pciture Tubes, Ltd."; "CTX" = "CTX"; "DEC" = "DEC"; "DEL" = "Dell"; "DPC" = "Delta"; "DWE" = "Daewoo"; "EIZ" = "EIZO"; "ELS" = "ELSA"; "ENC" = "EIZO"; "EPI" = "Envision"; "FCM" = "Funai"; "FUJ" = "Fujitsu"; "FUS" = "Fujitsu-Siemens"; "GSM" = "LG Electronics"; "GWY" = "Gateway 2000"; "HEI" = "Hyundai"; "HIT" = "Hyundai"; "HSL" = "Hansol"; "HTC" = "Hitachi/Nissei"; "HWP" = "HP"; "IBM" = "IBM"; "ICL" = "Fujitsu ICL"; "IVM" = "Iiyama"; "KDS" = "Korea Data Systems"; "LEN" = "Lenovo"; "LGD" = "Asus"; "LPL" = "Fujitsu"; "MAX" = "Belinea"; "MEI" = "Panasonic"; "MEL" = "Mitsubishi Electronics"; "MS_" = "Panasonic"; "NAN" = "Nanao"; "NEC" = "NEC"; "NOK" = "Nokia Data"; "NVD" = "Fujitsu"; "OPT" = "Optoma"; "PHL" = "Philips"; "REL" = "Relisys"; "SAN" = "Samsung"; "SAM" = "Samsung"; "SBI" = "Smarttech"; "SGI" = "SGI"; "SNY" = "Sony"; "SRC" = "Shamrock"; "SUN" = "Sun Microsystems"; "SEC" = "Hewlett-Packard"; "TAT" = "Tatung"; "TOS" = "Toshiba"; "TSB" = "Toshiba"; "VSC" = "ViewSonic"; "ZCM" = "Zenith"; "UNK" = "Unknown"; "_YV" = "Fujitsu"; "ENV"="Envision" "HSD"="Hanns.G" } if ($wmiMonitorID.ManufacturerName -ne $null) { $manuf = $null $manuf= ([System.Text.Encoding]::ASCII.GetString($wmiMonitorID.ManufacturerName)).Replace("$([char]0x0000)","") if ($ManufacturerHashTable["$manuf"]) { $ManufacturerHashTable["$manuf"] } else { $manuf } } } [scriptblock]$SBMonPCode= { if ($wmiMonitorID.ProductCodeID -ne $null) { $dispproduct = $null $dispproduct=([System.Text.Encoding]::ASCII.GetString($wmiMonitorID.ProductCodeID)).Replace("$([char]0x0000)","") $dispproduct } } [scriptblock]$SbMonSn= { if ($wmiMonitorID.SerialNumberID -ne $null) { $dispserial = $null $dispserial=([System.Text.Encoding]::ASCII.GetString($wmiMonitorID.SerialNumberID)).Replace("$([char]0x0000)","") $dispserial } } [scriptblock]$SbMonName= { if ($wmiMonitorID.UserFriendlyName -ne $null) { $dispname = $null $dispname=([System.Text.Encoding]::ASCII.GetString($wmiMonitorID.UserFriendlyName)).Replace("$([char]0x0000)","") $dispname } } [scriptblock]$SbNetworkAdapters= { $dispNetAdap=$Win32_NetworkAdapterConfiguration | Select-Object -Property Description,MACAddress,IPAddress,DHCPServer,DefaultIPGateway,DNSServerSearchOrder $dispNetAdap } [scriptblock]$SbNetPhysAdapCount= { $Count=0 $Win32_NetworkAdapter | foreach {if ($_.physicaladapter){$count++}} $count } [scriptblock]$SbPrinters= { #$dispPrinter=$Win32_Printer | Select-Object -Property Name,DriverName,Network,Local,PortName,WorkOffline,Published,Shared,ShareName,Direct,PrinterStatus,PrintProcessor $dispPrinter=$Win32_Printer | foreach { $Property=@{ Name=$_.Name DriverName=$_.DriverName Local=$_.Local ShareName=$_.ShareName } $TmpObj=New-Object psobject -Property $Property $TmpObj.psobject.typenames.insert(0,"ModuleSystemInfo.Systeminfo.Printers.Printer") $TmpObj } $dispPrinter } [scriptblock]$SbUsbConPrCount= { $count=0 $dispPrinter=$Win32_Printer | Select-Object -Property Name,DriverName,Network,Local,PortName,WorkOffline,Published,Shared,ShareName,Direct,PrinterStatus,PrintProcessor $dispPrinter | foreach { if (($_.portname -match "Usb") -and ($_.local -eq $True) -and ($_.workOffline -eq $false)) { $Count++ } } $count } [scriptblock]$SbIsPrintServer= { $IsPrintServer=$false $dispPrinter=$Win32_Printer | Select-Object -Property Name,DriverName,Network,Local,PortName,WorkOffline,Published,Shared,ShareName,Direct,PrinterStatus,PrintProcessor $dispPrinter | foreach { if (($_.portname -match "Usb") -and ($_.local -eq $True) -and ($_.workOffline -eq $false)) { if ($_.shared -eq $true) { $IsPrintServer=$True } } } $IsPrintServer } [scriptblock]$SbUsbConPrOnline= { $ObjUsbConnectPrinters=@() $dispPrinter=$Win32_Printer | Select-Object -Property Name,DriverName,Network,Local,PortName,WorkOffline,Published,Shared,ShareName,Direct,PrinterStatus,PrintProcessor $dispPrinter | foreach { if (($_.portname -match "Usb") -and ($_.local -eq $True) -and ($_.workOffline -eq $false)) { $ObjUsbConnectPrinter=New-Object psobject $ObjUsbConnectPrinter | Add-Member -NotePropertyName PrinterName -NotePropertyValue $_.name $ObjUsbConnectPrinter | Add-Member -NotePropertyName DriverName -NotePropertyValue $_.DriverName $ObjUsbConnectPrinters+=$ObjUsbConnectPrinter } } $ObjUsbConnectPrinters } [scriptblock]$SbUsbDevices= { $Win32_USBControllerDevice | foreach {[wmi]($_.dependent)} | Select-Object -Property Name } [scriptblock]$SbMemoryMaxIns= { $MemMaxinsCount=0 $Win32_PhysicalMemoryArray | foreach {$MemMaxinsCount+=$_.MaxCapacity*1kb} $MemMaxinsCount } [scriptblock]$SBOsProductKey= { try{ $map="BCDFGHJKMPQRTVWXY2346789" If((RegGetValue -Key "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" -Value "PROCESSOR_ARCHITECTURE" -GetValue GetStringValue -ErrorAction Stop) -eq "AMD64") { $value=(RegGetValue -Key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Value "DigitalProductId4" -GetValue GetBinaryValue -ErrorAction Stop)[0x34..0x42] } Else { $value=(RegGetValue -Key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Value "DigitalProductId" -GetValue GetBinaryValue -ErrorAction Stop)[0x34..0x42] } $ProductKey = "" for ($i = 24; $i -ge 0; $i--) { $r = 0 for ($j = 14; $j -ge 0; $j--) { $r = ($r * 256) -bxor $value[$j] $value[$j] = [math]::Floor([double]($r/24)) $r = $r % 24 } $ProductKey = $map[$r] + $ProductKey if (($i % 5) -eq 0 -and $i -ne 0) { $ProductKey = "-" + $ProductKey } } $ProductKey } catch{$_} } [scriptblock]$SbGetRegistryValue= { try{ RegGetValue -key $ReGistryKey -Value $ReGistryValue -GetValue $RegistryValueType -ErrorAction Stop } catch{$_} } [ScriptBlock]$SbSoftwareList= { try{ $Object =@() $excludeArray = ("Security Update for Windows", "Update for Windows", "Update for Microsoft .NET", "Security Update for Microsoft", "Hotfix for Windows", "Hotfix for Microsoft .NET Framework", "Hotfix for Microsoft Visual Studio 2007 Tools", "Hotfix", "Update for Microsoft Office" ) $GetArch=RegGetValue -key "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" -Value "PROCESSOR_ARCHITECTURE" -GetValue GetStringValue -ErrorAction Stop If($GetArch -eq "AMD64") { $OSArch='64-bit' } Else { $OSArch='32-bit' } Switch ($OSArch) { "64-bit"{ $RegKey_64BitApps_64BitOS = "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall" $RegKey_32BitApps_64BitOS = "HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" #$RegKey_32BitApps_32BitOS = "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall" ############################################################################# # Get SubKey names $SubKeys = RegEnumKey -key $RegKey_64BitApps_64BitOS -ErrorAction Stop ForEach ($Name in $SubKeys) { $SubKey = "$RegKey_64BitApps_64BitOS\$Name" $AppName = RegGetValue -key $SubKey -Value "DisplayName" -GetValue GetStringValue -ErrorAction SilentlyContinue $Version =RegGetValue -key $SubKey -Value "DisplayVersion" -GetValue GetStringValue -ErrorAction SilentlyContinue $Publisher=RegGetValue -key $SubKey -Value "Publisher" -GetValue GetStringValue -ErrorAction SilentlyContinue $donotwrite = $false if($AppName.length -gt "0"){ Foreach($exclude in $excludeArray) { if($AppName.StartsWith($exclude) -eq $TRUE) { $donotwrite = $true break } } if ($donotwrite -eq $false) { $TmpObject="" | Select-Object Appication,Architecture,Version,Publisher $TmpObject.Appication=$AppName $TmpObject.Architecture="64-BIT" $TmpObject.Version=$Version $TmpObject.Publisher=$Publisher $Object += $TmpObject } } } ############################################################################# $SubKeys = RegEnumKey -key $RegKey_32BitApps_64BitOS -ErrorAction Stop # Loop Through All Returned SubKEys ForEach ($Name in $SubKeys) { $SubKey = "$RegKey_32BitApps_64BitOS\$Name" $AppName = RegGetValue -key $SubKey -Value "DisplayName" -GetValue GetStringValue -ErrorAction SilentlyContinue $Version =RegGetValue -key $SubKey -Value "DisplayVersion" -GetValue GetStringValue -ErrorAction SilentlyContinue $Publisher=RegGetValue -key $SubKey -Value "Publisher" -GetValue GetStringValue -ErrorAction SilentlyContinue $donotwrite = $false if($AppName.length -gt "0"){ Foreach($exclude in $excludeArray) { if($AppName.StartsWith($exclude) -eq $TRUE) { $donotwrite = $true break } } if ($donotwrite -eq $false) { $TmpObject="" | Select-Object Appication,Architecture,Version,Publisher $TmpObject.Appication=$AppName $TmpObject.Architecture="32-BIT" $TmpObject.Version=$Version $TmpObject.Publisher=$Publisher $Object += $TmpObject } } } } #End of 64 Bit ###################################################################################### ########################################################################################### "32-bit"{ $RegKey_32BitApps_32BitOS = "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall" ############################################################################# # Get SubKey names $SubKeys = RegEnumKey -key $RegKey_32BitApps_32BitOS -ErrorAction Stop # Loop Through All Returned SubKEys ForEach ($Name in $SubKeys) { $SubKey = "$RegKey_32BitApps_32BitOS\$Name" $AppName = RegGetValue -key $SubKey -Value "DisplayName" -GetValue GetStringValue -ErrorAction SilentlyContinue $Version =RegGetValue -key $SubKey -Value "DisplayVersion" -GetValue GetStringValue -ErrorAction SilentlyContinue $Publisher=RegGetValue -key $SubKey -Value "Publisher" -GetValue GetStringValue -ErrorAction SilentlyContinue if($AppName.length -gt "0"){ $TmpObject="" | Select-Object Appication,Architecture,Version,Publisher $TmpObject.Appication=$AppName $TmpObject.Architecture="32-BIT" $TmpObject.Version=$Version $TmpObject.Publisher=$Publisher $Object+= $TmpObject } } }#End of 32 bit } # End of Switch $object } catch { $_ } } ################################################################################################################################# #EndScriptBlock #Block Function #Registry function function RegGetValue { [CmdletBinding()] param( [parameter(Mandatory=$true)] [string]$Key, [parameter(Mandatory=$true)] [string]$Value, [parameter(Mandatory=$true)] [ValidateSet("GetStringValue","GetBinaryValue","GetDWORDValue")] [string]$GetValue ) if ($stdregprov -eq $null) { Write-Error "Variable StdRegProv Null" } $ResultProp=@{ "GetStringValue"="Svalue" "GetBinaryValue"="Uvalue" "GetDWORDValue"="UValue" } $ErrorCode=@{ "1"="Value doesn't exist" "2"="Key doesn't exist" "2147749893"="Wrong value type" "5"="Access Denied" "6"="Wrong Key String" } $hk=@{ "HKEY_CLASSES_ROOT"=2147483648 "HKEY_CURRENT_USER"=2147483649 "HKEY_LOCAL_MACHINE"=2147483650 "HKEY_USERS"=2147483651 "HKEY_CURRENT_CONFIG"=2147483653 } if($Key -match "(.+?)\\(.+)") { if ($hk.Keys -eq $matches[1]) { $RootHive=$hk[$matches[1]] $KeyString=$matches[2] $StdRegProvResult=$StdRegProv | Invoke-WmiMethod -Name $GetValue -ArgumentList $RootHive,$KeyString,$Value } else { Write-Error "$($matches[1]) Does not belong to the set $($hk.Keys)" -ErrorAction Stop } if ($StdRegProvResult.returnvalue -ne 0) { if ($ErrorCode["$($StdRegProvResult.returnvalue)"] -ne $null) { $er=$ErrorCode["$($StdRegProvResult.returnvalue)"] Write-Error "$Er! Key $Key Value $Value " } else { $er=$StdRegProvResult.returnvalue Write-Error "$GetValue return $Er! Key $Key Value $Value " } } else { $StdRegProvResult.($ResultProp["$GetValue"]) } } else { Write-Error "$Key not valid" } } function RegEnumKey { [CmdletBinding()] param( [parameter(Mandatory=$true)] [string]$Key ) $ErrorActionPreference="Stop" if ($stdregprov -eq $null) { Write-Error "Variable StdRegProv Null" } $ErrorCode=@{ "1"="Value doesn't exist" "2"="Key doesn't exist" "5"="Access Denied" "6"="Wrong Key String" } $hk=@{ "HKEY_CLASSES_ROOT"=2147483648 "HKEY_CURRENT_USER"=2147483649 "HKEY_LOCAL_MACHINE"=2147483650 "HKEY_USERS"=2147483651 "HKEY_CURRENT_CONFIG"=2147483653 } if($Key -match "(.+?)\\(.+)") { $StdRegProvResult=$StdRegProv.EnumKey($hk[$matches[1]],$matches[2]) if ($StdRegProvResult.returnvalue -ne 0) { if ($ErrorCode["$($StdRegProvResult.returnvalue)"] -ne $null) { $er=$ErrorCode["$($StdRegProvResult.returnvalue)"] } else { $er=$StdRegProvResult.returnvalue } Write-Error "$Er key $Key" } else { $StdRegProvResult.snames } } else { Write-Error "$Key not valid" } } #End Registry function function GetHddSmart { function ConvertTo-Hex ( $DEC ) { '{0:x2}' -f [int]$DEC } function ConvertTo-Dec ( $HEX ) { [Convert]::ToInt32( $HEX, 16 ) } function Get-AttributeDescription ( $Value ) { switch ($Value) { '01' { 'Raw Read Error Rate' } '02' { 'Throughput Performance' } '03' { 'Spin-Up Time' } '04' { 'Number of Spin-Up Times (Start/Stop Count)' } '05' { 'Reallocated Sector Count' } '07' { 'Seek Error Rate' } '08' { 'Seek Time Performance' } '09' { 'Power On Hours Count (Power-on Time)' } '0a' { 'Spin Retry Count' } '0b' { 'Calibration Retry Count (Recalibration Retries)' } '0c' { 'Power Cycle Count' } 'aa' { 'Available Reserved Space' } 'ab' { 'Program Fail Count' } 'ac' { 'Erase Fail Count' } 'ae' { 'Unexpected power loss count' } 'b7' { 'SATA Downshift Error Count' } 'b8' { 'End-to-End Error' } 'bb' { 'Reported Uncorrected Sector Count (UNC Error)' } 'bc' { 'Command Timeout' } 'bd' { 'High Fly Writes' } 'be' { 'Airflow Temperature' } 'bf' { 'G-Sensor Shock Count (Mechanical Shock)' } 'c0' { 'Power Off Retract Count (Emergency Retry Count)' } 'c1' { 'Load/Unload Cycle Count' } 'c2' { 'Temperature' } 'c3' { 'Hardware ECC Recovered' } 'c4' { 'Reallocated Event Count' } 'c5' { 'Current Pending Sector Count' } 'c6' { 'Offline Uncorrectable Sector Count (Uncorrectable Sector Count)' } 'c7' { 'UltraDMA CRC Error Count' } 'c8' { 'Write Error Rate (MultiZone Error Rate)' } 'c9' { 'Soft Read Error Rate' } 'cb' { 'Run Out Cancel' } 'cа' { 'Data Address Mark Error' } 'dc' { 'Disk Shift' } 'e1' { 'Load/Unload Cycle Count' } 'e2' { 'Load ''In''-time' } 'e3' { 'Torque Amplification Count' } 'e4' { 'Power-Off Retract Cycle' } 'e8' { 'Endurance Remaining' } 'e9' { 'Media Wearout Indicator' } 'f0' { 'Head Flying Hours' } 'f1' { 'Total LBAs Written' } 'f2' { 'Total LBAs Read' } 'f9' { 'NAND Writes (1GiB)' } 'fe' { 'Free Fall Protection' } default { $Value } } } $PnpDev=@{} $hdddev=$Win32_DiskDrive | Select-Object Model,Size,MediaType,InterfaceType,FirmwareRevision,SerialNumber,PNPDeviceID $hdddev | foreach { $PnpDev.Add($($_.pnpdeviceid -replace "\\","\\"),$_) } $PnpDev.Keys | foreach { $PnpDevid=$_ $TmpFailData=$MSStorageDriver_FailurePredictData | Where-Object {$_.InstanceName -Match $PnpDevid} $TmpFailStat=$MSStorageDriver_FailurePredictStatus | Where-Object {$_.InstanceName -Match $PnpDevid} if ($TmpFailStat) { $PnpDev[$PnpDevid] | Add-Member -MemberType NoteProperty -Name PredictFailure -Value $TmpFailStat.PredictFailure } else { $PnpDev[$PnpDevid] | Add-Member -MemberType NoteProperty -Name PredictFailure -Value 'Not supported' } if ($TmpFailData) { $Disk=$TmpFailData $i = 0 #$Report = @() $pByte = $null foreach ( $Byte in $Disk.VendorSpecific ) { $i++ if (( $i - 3 ) % 12 -eq 0 ) { if ( $Byte -eq 0) { break } $Attribute = '{0:x2}' -f [int]$Byte } else { $post = ConvertTo-Hex $pByte $pref = ConvertTo-Hex $Byte $Value = ConvertTo-Dec "$pref$post" if (( $i - 3 ) % 12 -eq 6 ) { if ( $Attribute -eq '09' ) { [int]$Value = $Value / 24 } $PnpDev[$PnpDevid] | Add-Member -MemberType NoteProperty -Name $( Get-AttributeDescription $Attribute) -Value $Value } } $pByte = $Byte } } else { $PnpDev[$PnpDevid] | Add-Member -MemberType NoteProperty -Name SmartStatus -Value 'Not supported' } $HddSmart=$PnpDev[$PnpDevid] $WarningThreshold=@{ "Temperature"=46,54 "Reallocated Sector Count"=1,10 } $CriticalThreshold=@{ "Temperature"=55 "Reallocated Sector Count"=11 } $HddWarning=$False $HddCritical=$False $HddSmart | Get-Member | foreach { $Property=$_.name if ($WarningThreshold[$Property]) { $MinWarningThreshold=$WarningThreshold[$Property][0] $MaxWarningThreshold=$WarningThreshold[$Property][1] if ($HddSmart.$Property -le $MaxWarningThreshold -and $HddSmart.$Property -ge $MinWarningThreshold) { $HddWarning=$true } } if ($CriticalThreshold[$Property]) { $MinCriticalThreshold=$CriticalThreshold[$Property] if($HddSmart.$Property -ge $MinCriticalThreshold) { $HddCritical=$true } } #End Foreach } if ($HddSmart.smartstatus -ne "Not supported") { if ($HddWarning) { $HddSmart | Add-Member -MemberType NoteProperty -Name SmartStatus -Value 'Warning' } elseif($HddCritical -or $HddSmart.PredictFailure) { $HddSmart | Add-Member -MemberType NoteProperty -Name SmartStatus -Value 'Critical' } else { $HddSmart | Add-Member -MemberType NoteProperty -Name SmartStatus -Value 'Ok' } } $HddSmart #End Foreach } } #################################################### function StartRunspaceJob { param( $WmiVariable, $ScriptBlock, $ComputerName, $Prop ) $ParamList=@{} $WmiVariable | Get-Member -MemberType NoteProperty | foreach {$ParamList.Add($_.name,$WmiVariable.($_.name))} if ($PropertyParams[$prop] | Where-Object {$_.keys -eq "RunspaceImportVariable"}) { $AddParam=@() $AddParam+=($PropertyParams[$prop] | Where-Object {$_.keys -eq "RunspaceImportVariable"}).RunspaceImportVariable $AddParam | foreach { if ($_ -match "^\$") { $ParamList.Add($($_ -replace "\$",""),$(get-variable -name $($_ -replace "\$","") -ValueOnly)) } else { Write-Error "RunspaceImportVariable Wrong param $_. Check FunctionConfig" -ErrorAction Stop } } } $PowerShell = [powershell]::Create() [void]$PowerShell.AddScript( $ScriptBlock ) [void]$PowerShell.AddParameters($ParamList) $PowerShell.Runspacepool = $RunspacePool $State = $PowerShell.BeginInvoke() $temp = '' | Select PSJobTypeName,PowerShell,State,Location,StartTime,Property,Runspace $temp.PSJobTypeName="RunspaceJob" $temp.powershell=$PowerShell $temp.state=$State $temp.location=$Computername $temp.StartTime=get-date $temp.Property=$Prop $temp.runspace=$Runspace $temp } function GetWmi{ param( $ComputerName, $WmiParamArray ) $Count=0 $WmiParamArray | foreach { $WmiParam=$_ if ($Credential -ne $null) { if (!($LocalComputer -eq $ComputerName)) { if (!($WmiParam["Credential"])) { $WmiParam.Add("Credential",$Credential) } } } if ($jobs.count -ge $MaxJob) { do{ $repeat=$true GetJob if ($Jobs.Count -lt $MaxJob) { $repeat=$false } else { Start-Sleep -Milliseconds 20 } }while($repeat) } $RemoveClass=$null if ($WmiParam['Query']) { $RemoveClass=$WmiParam['Class'] $WmiParam.Remove("Class") } if ($WmiParam['class']) { Write-Verbose "$Computername Start Job Get-WmiObject -Class $($WmiParam['class']) -NameSpace $($WmiParam['NameSpace'])" } else { Write-Verbose "$Computername Start Job Get-WmiObject -Query $($WmiParam['Query']) -NameSpace $($WmiParam['NameSpace'])" } $TmpWmiJob=Get-WmiObject @WmiParam -computername $ComputerName -ErrorAction Stop -AsJob if ($?) { $temp = '' | Select-Object PSJobTypeName,WmiJob,StartTime,Location,Class,Query $temp.PSJobTypeName="WmiJob" $temp.WmiJob=$TmpWmiJob $temp.StartTime=Get-Date $Temp.Location=$ComputerName if ($RemoveClass) { $Temp.Class=$RemoveClass $Temp.Query=$true } else { $Temp.Class=$WmiParam['Class'] $Temp.Query=$False } [void]$Jobs.Add($temp) } if ($WmiParam['Query']) { $WmiParam.Add("Class",$RemoveClass) } $Count++ if ($Count -eq $WmiParamArray.count) { Write-Verbose "$ComputerName All Wmi request completed" [void]$GetWmicompletedForComputers.Add($ComputerName) } #End Foreach } } function WrErr($Err,$Job) { try{ if ($Job -eq $null) { Write-Error "$Computername Job variable null" -ErrorAction Stop } if($tmperr=$Global:ErrorResult | Where-Object {$_.computername -eq $Job.location}) { if ($tmperr.warning -ne $err.Exception.Message) { Write-Warning "$($Job.location) $($err.Exception.Message)" $tmperr.warning=$tmperr.warning+","+$err.Exception.Message } } else { Write-Warning "$($Job.location) $($err.Exception.Message)" $ErTmp="" | select ComputerName,Warning,Error $ErTmp.ComputerName=$Job.location $ErTmp.Warning=$err.Exception.Message $ErTmp.Error=$err $Global:ErrorResult+=$ErTmp } if ($Job.PSJobTypeName -eq "RunspaceJob") { $Job.powershell.dispose() $Job.State = $null $Job.powershell = $null } $RemoveJobs=$jobs | Where-Object {$_.location -eq $Job.location} $RemoveJobs | foreach {$Jobs.Remove($_)} }catch{ $Jobs.Remove($Job) } } function GetJob { try { #Write-Verbose "getjob" #Start-Sleep -Milliseconds 500 #Failed Job $AllFailedWmiJobs=$Jobs | Where-Object {$_.WmiJob.State -eq "Failed"} if ($AllFailedWmiJobs -ne $null) { $AllFailedWmiJobs | foreach { try { $Job=$_.WmiJob $TmpErRec=$Job | Receive-Job -ErrorAction Stop if ($TmpErRec -eq $null) { if ($VerbosePreference -eq "Continue") { Write-Warning "$($Job.location) $($_.Class) JobState Failed Get-WmiObject return Null Value" } } Remove-Job $Job $Jobs.Remove($_) } catch { WrErr -Err $_ -Job $Job } # End Foreach } } #Completed Job $AllCompletedJobs=$Jobs | Where-Object {$_.WmiJob.State -eq "Completed"} #Completed Runspace Job $AllRunspaceCompletedJob=$jobs | Where-Object {$_.state.isCompleted} if ($AllRunspaceCompletedJob -ne $null) { $AllRunspaceCompletedJob | foreach { $Job=$_ $TmpRes=$_.powershell.EndInvoke($_.State) if($_.powershell.HadErrors -eq $true) { if ($TmpRes.count -eq 0) { Write-Error "Scriptblock HadErrors, use try{}catch{} in the ScriptBlock to find out the details" -ErrorAction Stop } elseif ($TmpRes[0].GetType().name -eq "ErrorRecord") { Write-Error $TmpRes[0] -ErrorAction Stop } else { Write-Error "Unknown Error" -ErrorAction Stop } } elseif($TmpRes[0] -ne $null) { if ($TmpRes[0].GetType().name -eq "ErrorRecord") { Write-Error $TmpRes[0] -ErrorAction Stop } Write-Verbose "$($Job.location) RunspaceJob for Property $($Job.property) Completed" write-verbose "$($Job.location) Add to result $($Job.property)=[Scriptblock]$(($PropertyParams[$Job.property] | Where-Object {$_.Scriptblock}).ScriptBlock)" $HashtableResult[$Job.location].($Job.property)=$TmpRes $_.powershell.dispose() $_.State = $null $_.powershell = $null $Jobs.Remove($Job) } else { Write-Error "Scriptblock return empty value" -ErrorAction Stop } # End Foreach } } if($AllCompletedJobs -ne $null) { $AllCompletedJobs | foreach { $Job=$_.WmiJob $Computername=$_.location $GetWmi=@() $GetWmi+=Receive-Job -Job $Job -ErrorAction Stop if ($GetWmi.Count -eq 0 -or $GetWmi[0] -eq $null) { if ($VerbosePreference -eq "Continue") { Write-Warning -Message "$Computername $($_.Class) Get-Wmiobject return empty value.." } } else { if ($_.Query) { $GwmiClass=$_.Class } else { $GwmiClass=$GetWmi[0].__CLASS } if ($GetWmi.Count -eq 1) { $GetWmi=$Getwmi[0] } Write-Verbose "$Computername Receive-Job $GwmiClass Completed" $HashtableWMi[$ComputerName].$GwmiClass=$GetWmi } Remove-Job $Job -Force $Jobs.Remove($_) # End Foreach } } #Create Result $TmpGetWmicompletedForComputers=$GetWmicompletedForComputers.clone() $TmpGetWmicompletedForComputers | foreach { $ComputerName=$_ if (!($Jobs | Where-Object {$_.Location -eq $ComputerName})) { if (!($Global:ErrorResult | Where-Object {$_.computername -eq $ComputerName})) { #Create Variable $HashtableWMi[$computername] | Get-Member -MemberType NoteProperty | foreach {New-Variable -Name $_.Name -Value $HashtableWMi[$computername].$($_.Name)} $AllProperties | foreach{ $Property=$_ $Keys=$PropertyParams[$property] | foreach {$_.keys} $ParamProperty=($PropertyParams[$Property] | Where-Object {$_.Property}).Property $ParamScriptblock=($PropertyParams[$Property] | Where-Object {$_.Scriptblock}).ScriptBlock $Class=($PropertyParams[$Property] | Where-Object {$_.class}).class if ($Keys -eq "UseRunspace") { if ($HashtableResult[$ComputerName].$Property -eq $null) { #Add param to Runspace scriptblock $AddParam=@() #Add all wmi variable $HashtableWMi[$computername] | Get-Member -MemberType NoteProperty | foreach {$AddParam+=('$'+$_.name)} if ($Keys -eq "RunspaceImportVariable") { #Add all RunspaceImportVariable $AddParam+=($PropertyParams[$property] | Where-Object {$_.runspaceimportvariable}).runspaceimportvariable } Write-Verbose -Message "$ComputerName Edit ScriptBlock [ScriptBlock]$($ParamScriptblock)" $ScriptBlockParam = $ExecutionContext.InvokeCommand.NewScriptBlock("param($($AddParam -Join ", "))`r`n"+$(get-variable -name $($ParamScriptblock -replace "\$","") -ValueOnly).ToString()) Write-Verbose "$ComputerName StartRunspaceJob for Property $Property" StartRunspaceJob -WmiVariable $HashtableWMi[$computername] -ScriptBlock $ScriptBlockParam -ComputerName $ComputerName -Prop $Property | foreach {[void]$Jobs.Add($_);} #It is mandatory to use this delay otherwise there are run-time errors Start-Sleep -Milliseconds 200 } } if ($HashtableResult[$ComputerName].$Property -eq $null) { if ($ParamProperty) { Write-Verbose ("$ComputerName Add to result $Property=$"+"$Class.$ParamProperty") $WmiVariables=Get-Variable -Name $Class -ValueOnly if ($WmiVariables.count -gt 1) { $ResultParamProperty=$WmiVariables | foreach {$_.$ParamProperty} } else { $ResultParamProperty=$WmiVariables.$ParamProperty } $HashtableResult[$ComputerName].$Property=$ResultParamProperty } elseif ($ParamScriptblock -and !($Keys -eq "UseRunspace" )) { Write-Verbose "$ComputerName Add to result $Property= [Scriptblock]$($ParamScriptblock)" try { $HashtableResult[$ComputerName].$Property=&$(get-variable -name $($ParamScriptblock -replace "\$","") -ValueOnly) } catch { Write-Error -Message "Check Scriptblock [ScriptBlock]$ParamScriptblock $($_.Exception.message) $($_.InvocationInfo.PositionMessage)" -ErrorAction stop } } elseif (!($Keys -eq "UseRunspace" )) { Write-Verbose ("$ComputerName Add to result $Property=$"+"$Class") $WmiVariables=Get-Variable -Name $Class -ValueOnly $ResultParamProperty=$WmiVariables $HashtableResult[$ComputerName].$Property=$ResultParamProperty } } #End Foreach } #Remove Variable $HashtableWMi[$computername] | Get-Member -MemberType NoteProperty | foreach {Remove-Variable -Name $_.name -Force} if (!($Jobs | Where-Object {$_.Location -eq $ComputerName})) { Write-Verbose -Message "$ComputerName All Job Completed" $Global:Result+=$HashtableResult[$ComputerName] if ($UpdateFormatData) { CreateFormatPs1xml -ForObject $HashtableResult[$ComputerName] -ErrorAction Stop Update-FormatData -PrependPath $($env:TEMP+"\SystemInfoAutoformat.ps1xml") -ErrorAction SilentlyContinue Set-Variable -Name UpdateFormatData -Value $false -Scope 1 -Force } $HashtableResult[$ComputerName].psobject.typenames.insert(0,"ModuleSystemInfo.Systeminfo.AutoFormatObject") $HashtableResult[$ComputerName] $GetWmicompletedForComputers.remove($ComputerName) } } } # End Foreach } #Timeout Job $AllTimeOutJob=$Jobs | Where-Object {(New-TimeSpan -start $_.StartTime).TotalSeconds -gt $JobTimeOut} if ($AllTimeOutJob -ne $null) { $AllTimeOutJob | foreach { try { $Job=$_ Write-Error -Message "Timeout expired" -ErrorAction Stop } catch { WrErr -Err $_ -Job $Job } } } } catch { WrErr -Err $_ -Job $Job } # End Function } function CreateFormatPs1xml { [CmdletBinding()] param( $ForObject ) $ConvertToGb="MemoryTotal","MemoryMaxIns","MemoryFree","MemoryAvailable","VideoRam" $FormatTableFor="PSCustomObject","ManagementObject" [string]$XmlFormatList='' $DollarUnder='$_' $AllProperties | foreach{ $Property=$_ if ($Forobject.$Property.count -gt 1) { $ForObjectProperty=$Forobject.$Property[0] } else { $ForObjectProperty=$Forobject.$Property } if ($ForObjectProperty -eq $null) { $XmlFormatList+=" <ListItem> <PropertyName>$Property</PropertyName> </ListItem>" } elseif($ForObject.HddSmart) { $XmlFormatList+=" <ListItem> <Label>$Property</Label> <ScriptBlock> $DollarUnder.$Property | fl | out-string </ScriptBlock> </ListItem>" } elseif ($FormatTableFor -eq ($ForObjectProperty).GetType().name) { $XmlFormatList+=" <ListItem> <Label>$Property</Label> <ScriptBlock> $DollarUnder.$Property | ft -autosize | out-string </ScriptBlock> </ListItem>" } elseif ($ConvertToGb -eq $Property) { $XmlFormatList+="<ListItem> <Label>$Property</Label> <ScriptBlock> [string]('{0:N1}' -f ($DollarUnder.$property/1gb))+'Gb' </ScriptBlock> </ListItem>" } else { $XmlFormatList+=" <ListItem> <PropertyName>$Property</PropertyName> </ListItem>" } # End Foreach } #$XmlFormatList $XmlAutoFormat='<?xml version="1.0" encoding="utf-8" ?>' $XmlAutoFormat+=" <Configuration> <ViewDefinitions> <View> <Name>Default</Name> <ViewSelectedBy> <TypeName>ModuleSystemInfo.Systeminfo.AutoFormatObject</TypeName> </ViewSelectedBy> <ListControl> <ListEntries> <ListEntry> <ListItems> <ListItem> <PropertyName>ComputerName</PropertyName> </ListItem> $XmlFormatList </ListItems> </ListEntry> </ListEntries> </ListControl> </View> </ViewDefinitions> </Configuration>" Write-Verbose "Create ps1xml file $($env:TEMP+"\SystemInfoAutoformat.ps1xml")" $XmlAutoFormat | Out-File -FilePath $($env:TEMP+"\SystemInfoAutoformat.ps1xml") -Force -ErrorAction Stop #End Function } Function ParseParam { param( [parameter(Mandatory=$true)] [string]$ParamString, [String]$Property ) $PermitParams="Class","ScriptBlock","UseRunspace","RunspaceImportVariable","Property","Query","Namespace" $ArrayHashTableParam=@() $ArrayParamString=(((($ParamString -replace "\s+"," ") -replace "\s+$","") -replace "^-"," -") -replace " -"," --") -split "\s-" $ArrayParamString | foreach { $HashTableParam=@{} if ($_ -match "^-(.+?)\s(.+)$") { $ParseParam=$Matches[1] $ParseValue=$Matches[2] if ($ParseValue -match ",") { $ArrayParseValue=$ParseValue -split "," $ParseValue=$ArrayParseValue } $HashTableParam.Add($ParseParam,$ParseValue) $ArrayHashTableParam+=$HashTableParam } elseif ($_ -match "-(.+\S)") { $HashTableParam.Add($Matches[1],$null) $ArrayHashTableParam+=$HashTableParam } # End Foreach } $DifObj=$ArrayHashTableParam | foreach {$_.keys} $CompareParam=Compare-Object -ReferenceObject $PermitParams -DifferenceObject $DifObj if ($CompareParam | where-object {$_.sideindicator -eq "=>"}) { Write-Error "$Property Parameter -$(($CompareParam | Where-Object {$_.SideIndicator -eq "=>"}).inputobject) not allowed. Check FunctionConfig" -ErrorAction Stop } $ArrayHashTableParam #End Function } #End Block Function ##################################################################################################### $TestAdminUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent()) $IsAdmin=$TestAdminUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) $CurrentExecutionPolicy=Get-ExecutionPolicy $ExecutionPolicyChanged=$false if (!($RequiredExecutionPolicy -eq $CurrentExecutionPolicy)) { Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -Force -Confirm:$false if ($?) { $ExecutionPolicyChanged=$true } else { Write-Warning "Formatting objects does not work. Run the command Set-ExecutionPolicy -ExecutionPolicy RemoteSigned and retry now" } } if ($PSBoundParameters['ShowStatistics'].ispresent) { $BeginFunction=get-date } if ($PSBoundParameters['Credential']) { if (!($Credential.gettype().name -eq "PSCredential")) { $Credential=Get-Credential $Credential } } #Clear Old Job Write-Verbose "Clear old Job" Get-Job | where-object {$_.PSJobTypeName -eq "wmijob"} | Remove-Job -Force #Check registry param try { if ($PSBoundParameters["RegistryKey"] -ne $null -or $PSBoundParameters["RegistryValue"] -ne $null -or $PSBoundParameters["RegistryValueType"] -ne $null) { if ($PSBoundParameters["RegistryKey"] -eq $null) { $RegistryKey=Read-Host -Prompt "RegistryKey" } if ($PSBoundParameters["RegistryValue"] -eq $null) { $RegistryValue=Read-Host -Prompt "RegistryValue" } if ($PSBoundParameters["RegistryValueType"] -eq $null) { $RegistryValueType=Read-Host -Prompt "RegistryValueType" } $Properties+="RegistryValue" } } catch { Write-Error "$_" -ErrorAction Stop } #Collection all Properties $AllPropertiesSwitch=@() $AllPropertiesSwitch+=$PSBoundParameters.Keys | foreach { if ($PSBoundParameters[$_].ispresent -and !($ExcludeParam -eq $_)) { $SwitchConfig[$_] } } if ($AllPropertiesSwitch[0] -eq $Null -and $Properties -eq $null) { $AllPropertiesSwitch=$DefaultInfoConfig } $AllProperties+=$AllPropertiesSwitch+$Properties if ($AllProperties.GetType().name -ne "string") { $AllProperties=0..$AllProperties.Count | foreach {if ($AllProperties[$_] -ne $null){$AllProperties[$_]}} $AllProperties = $AllProperties | Select-Object -Unique } if ($AllProperties -match "\*") { Write-Verbose "Property: $($FunctionConfig.Keys)" $AllProperties=$FunctionConfig.Keys -ne "RegistryValue" } else { Write-Verbose "Property: $AllProperties" } #Parse FunctionConfig $PropertyParams=@{} $AllProperties | foreach { $FunctionProperty=$_ $ArrayHashTableParam=@() if ($FunctionConfig[$FunctionProperty] -eq $Null) { Write-Error "Property $FunctionProperty not found in $('$FunctionConfig')" -ErrorAction Stop } $ArrayHashTableParam+=ParseParam -ParamString $FunctionConfig[$FunctionProperty] -Property $FunctionProperty if ($QueryTmp=$($ArrayHashTableParam | where-object {$_.Query})) { if ($QueryTmp.Query -match ".+from\s(.+?)\s") { $TmpClass="Query_"+$Matches[1]+"_"+$FunctionProperty } else { Write-Error "Wrong query $($QueryTmp.Query)! Check query param." -ErrorAction Stop } if ($TmpClassHash=$ArrayHashTableParam | where-object {$_.class}) { $TmpArrayClass=@() $TmpArrayClass+=$TmpClassHash.Class $TmpArrayClass+=$TmpClass $TmpClassHash.Class=$TmpArrayClass } else { $TmpClassHash=@{ Class="$TmpClass" } $ArrayHashTableParam+=$TmpClassHash } } if ($($ArrayHashTableParam | where-object {$_.class}) -ne $null) { $PropertyParams.Add($FunctionProperty,$ArrayHashTableParam) } else { Write-Error "$FunctionProperty missing -Сlass parameter. Check FunctionConfig" -ErrorAction Stop } # End Foreach } #Check ScriptBlock param $PropertyParams.keys | foreach { try { $UserProperty=$_ $ParamHashTable=$PropertyParams[$UserProperty] $ParamScriptblock=$ParamHashTable | Where-Object {$_.keys -eq "Scriptblock"} if ($ParamScriptblock) { if ($ParamScriptblock.scriptblock -eq $null) { Write-Error "parameter -ScriptBlock is empty. Check FunctionConfig" -ErrorAction Stop } else { if ($ParamScriptblock.scriptblock -match "\$.+\S") { if((get-variable -Name $($ParamScriptblock.scriptblock -replace "\$","") -ValueOnly -ErrorAction Stop).GetType().Name -ne "Scriptblock") { Write-Error "Wrong variable type $($ParamScriptblock.scriptblock). Check FunctionConfig, Use [Scriptblock]" -ErrorAction Stop } } else { Write-Error "Wrong -Scriptblock variable $($ParamScriptblock.scriptblock). Check FunctionConfig" -ErrorAction Stop } } } } catch { Write-Error "$UserProperty $($_.Exception.message)" -ErrorAction Stop } # End Foreach } #Create wmi param $WmiParamArray=@() $PropertyParams.Keys | foreach {$PropertyParams[$_]} | foreach {$_.class} | Sort-Object -Unique | foreach { $Query=$null $WmiParam=@{} $FakeClass=$_ $Class=$_ if ($Class -match "^Query_(.+)?_(.+)") { $Class=$Matches[1] $Query=($PropertyParams[$Matches[2]] | Where-Object {$_.query}).query } if ($ManualNamespace[$Class]) { $ManualNamespaceParams=ParseParam -ParamString $($ManualNamespace[$Class]) $ManualNamespaceParamNamespace= $ManualNamespaceParams | Where-Object {$_.namespace} $ManualNamespaceParamQuery= $ManualNamespaceParams | Where-Object {$_.Query} if ($ManualNamespaceParamNamespace) { $Namespace=$ManualNamespaceParamNamespace["Namespace"] } if ($ManualNamespaceParamQuery -and $query -eq $null) { $Query=$ManualNamespaceParamQuery["Query"] } } else { try { if ((Get-WmiObject -query "SELECT * FROM meta_class WHERE __class = '$Class'").__NAMESPACE -eq "ROOT\cimv2") { $Namespace="ROOT\cimv2" } else { Write-Error 'Cannot retrieve Namespace use $ManualNamespace hashtable' -ErrorAction Stop } } catch { Write-Error "Cannot retrieve Namespace for class $Class check Functionconfig or use hashtable $('$ManualNamespace') " -ErrorAction Stop } } $WmiParam.Add("Class",$FakeClass) $WmiParam.Add("Namespace",$Namespace) if ($Query) { $WmiParam.Add("Query",$Query) $ManualNamespaceParamQuery=$Null } if ($WmiParam.class -ne $Null -and $WmiParam.Namespace -ne $Null) { $WmiParamArray+=$WmiParam } else { Write-Error "Class or Namspace not found" -ErrorAction Stop } #End Foreach } #$WmiParamArray #$PropertyParams $OpenRunspace=$false if (($PropertyParams.keys | foreach {$PropertyParams[$_]} | foreach {$_.keys}) -eq "UseRunspace") { $OpenRunspace=$true } #Import function to runspace $RunspaceImportFunction="RegGetValue","RegEnumKey" if ($OpenRunspace) { Write-Verbose "Use Runspace" $SessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() Get-Command -CommandType Function -Name $RunspaceImportFunction | foreach { $SessionStateFunction = New-Object System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList $_.name, $_.Definition $SessionState.Commands.Add($SessionStateFunction) } if ($?) { Write-Verbose "Runspace Commands Add Successfully" } $RunspacePool = [runspacefactory]::CreateRunspacePool(1,$MaxJob,$SessionState,$Host) $RunspacePool.Open() } #Remove old ps1xml file if (Test-Path $($env:TEMP+"\SystemInfoAutoformat.ps1xml")) { Write-Verbose "Remove ps1xml file $($env:TEMP+"\SystemInfoAutoformat.ps1xml")" Remove-Item -Path $($env:TEMP+"\SystemInfoAutoformat.ps1xml") -Force } $computers=@() $jobs = New-Object System.Collections.ArrayList $GetWmicompletedForComputers = New-Object System.Collections.ArrayList $HashtableResult=@{} $HashtableWMi=@{} $HashtableRunspace=@() $Global:ErrorResult=@() $UpdateFormatData=$true if ($PSBoundParameters["AppendToResult"].IsPresent) { if (!(Get-Variable -Name Result -Scope Global)) { $Global:Result=@() } elseif((Get-Variable -Name Result -Scope Global -ValueOnly).count -eq $null) { $OldRes=$Global:Result $Global:Result=@() $Global:Result+=$OldRes } } else { $Global:Result=@() } $CountComputers=0 } process { $computers=@() if ($Name -ne $null) { $computers+=$Name } $computers| foreach { $ComputerName=$_ $CountComputers++ $TmpObjectProp=@{ ComputerName=$_ } $TmpObjectWmiProp=@{} $AllProperties | foreach { if (!$IsAdmin) { if ($LocalComputer -eq $ComputerName) { if ($AdminRequired -eq $_) { Write-Warning "$ComputerName Information may be incomplete. The $_ property requires administrator privileges. Close powershell and run as administrator" } } } $TmpObjectProp.add($_,$null) } $WmiParamArray | foreach { $WmiParam=$_ $TmpObjectWmiProp.Add($WmiParam["Class"],$null) } $TmpObject=New-Object psobject -Property $TmpObjectProp $TmpObjectWmi=New-Object psobject -Property $TmpObjectWmiProp #$TmpObject | Add-Member -NotePropertyName ComputerName -NotePropertyValue $_ #$TmpObject.ComputerName=$_ if (!($HashtableResult[$_])) { [void]$HashtableResult.Add($_,$TmpObject) } if (!($HashtableWMi[$_])) { [void]$HashtableWMi.Add($_,$TmpObjectWmi) } try{ GetWmi -WmiParamArray $WmiParamArray -ComputerName $_ } catch{ Write-Error "$_ getwmi error" } #End Foreach } } end { do { $repeat=$false GetJob if ($Jobs.Count -ne 0) { $repeat=$true } } while($repeat) $Global:ErrorResult=$Global:ErrorResult | Sort-Object -Property Warning if ($Global:ErrorResult -eq $null) { $ErrResCount=0 } elseif ($Global:ErrorResult.count -eq $null) { $ErrResCount=1 } else { $ErrResCount=$Global:ErrorResult.count } $ResultCount=$Global:Result.count if ($Global:Result.Count -eq 1) { $Global:Result=$Global:Result | foreach {$_} } if ($RunspacePool -ne $null) { $RunspacePool.close() } if ($ExecutionPolicyChanged) { Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy $CurrentExecutionPolicy -Force -Confirm:$false -ErrorAction SilentlyContinue } #Write-Verbose "Clear all failed wmi job" #Get-Job | Where-Object {$_.State -eq "Failed"} | Remove-Job -Force if ($PSBoundParameters['ShowStatistics'].ispresent) { Write-Verbose "Function running $((New-TimeSpan -Start $BeginFunction).TotalSeconds) seconds" -Verbose Write-Verbose "Total Computers $CountComputers" -Verbose Write-Verbose "Success $ResultCount" -Verbose Write-Verbose "Errors $ErrResCount" -Verbose } #End Function } } |