function Get-PCBatchInvoke { [CmdletBinding()] param ( [Parameter()] [string[]] $Computers ) $SparkEnabled = Get-SparkEnabled if ($SparkEnabled) { Connect-ISM } #Region Script Block $sblock = { Write-Progress -Activity "Retrieving data from online computers" -Status $Env:COMPUTERNAME -PercentComplete 10 try {$win32_networkadapterconfiguration = Get-CimInstance -Class win32_networkadapterconfiguration} catch {$win32_networkadapterconfiguration = $null} #| MAC Address, try {$win32_LogicalDisk = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType=3" } catch {$win32_LogicalDisk = $null} #| Diskspace, try {$win32_SystemEnclosure = Get-CimInstance -ClassName Win32_SystemEnclosure} catch {$win32_SystemEnclosure = $null} #| Asset Tag Write-Progress -Activity "Retrieving data from online computers" -Status $Env:COMPUTERNAME -PercentComplete 20 try {$bitlocker = manage-bde -status C:} catch {$bitlocker = $null} # | Bitlocker Status try {$PCInfo = get-computerinfo} catch {$PCInfo = $null} Write-Progress -Activity "Retrieving data from online computers" -Status $Env:COMPUTERNAME -PercentComplete 30 try {$physicalDisk = Get-PhysicalDisk} catch {$physicalDisk = $null} # | Disk Type try {$win32_printer = (Get-CimInstance -ClassName win32_printer | Where-Object {$_.PortName -ne 'PORTPROMPT:' -and $_.PortName -ne 'nul:' -and $_.PortName -ne 'SHRFAX:'} | Select-Object -ExpandProperty Name) -join ' || ' } catch{ $win32_printer = $null} # | Printers try {$imprivataRegEntry = Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\SSOProvider\ISXAgent} catch {$imprivataRegEntry = $null} Write-Progress -Activity "Retrieving data from online computers" -Status $Env:COMPUTERNAME -PercentComplete 40 try {$kioskRegEntry = Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\SHSCustom} catch {$kioskRegEntry = $null} try {$win32_tpm = Get-CimInstance -Namespace root\cimv2\security\microsofttpm -Class win32_tpm} catch{$win32_tpm = $null} # | TPM $gpoPath = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\FVE\MDOPBitLockerManagement" $gpoValue = Get-ItemPropertyValue -Path $gpoPath -Name "KeyRecoveryServiceEndPoint" Switch($GpoValue -eq "https://shsmbam1.int.samhealth.net/MBAMRecoveryAndHardwareService/CoreService.svc") { $true {$gpoStatus = "GPO Applied"} $false {$gpoStatus = "GPO Not Applied (Check if system is member of group MBAM_Default on ADUC"} Default {$gpoStatus = "Error...GPOTEST Line PCRemote Line 276"} } Write-Progress -Activity "Retrieving data from online computers" -Status $Env:COMPUTERNAME -PercentComplete 50 $CitrixViewer = "C:\Program Files (X86)\Citrix\ICA Client\CDViewer.exe" #$LastUser = Get-ChildItem -Path C:\Users -Directory -Force -Exclude Public,Default,'Default User','All Users' | Sort-Object -Property LastWriteTime -Descending | Select-Object -First 3 # | Last Users try {$CPU = (Get-CimInstance -ClassName Win32_processor ).Name } catch {$CPU = $null} #MAC Address $MAC = ($win32_networkadapterconfiguration | Where-Object {$_.IpEnabled -Match "True"} | Select-Object -Expand macaddress) -join "," #IP $ip = ($win32_networkadapterconfiguration | Where-Object {$_.IpEnabled -Match "True"} | Select-Object -Expand IPAddress) if($ip -is [array]){ $ip = $ip[0] } #Adapter $adapter = ($win32_networkadapterconfiguration | Where-Object {$_.IpEnabled -Match "True"} | Select-Object -Expand Description) <# if($adapter -is [array]){ $adapter = $adapter[0] } #> #UserName $Username = $PCInfo.CSUserName if($null -eq $Username){ $Username = (Invoke-Command -SessionOption (New-PSSessionOption -NoMachineProfile) -ScriptBlock {Get-Process Explorer -IncludeUsername | Where-Object { $_.Username -notlike "*SYSTEM" }} ).Username if($null -ne $Username){ $Username = "$Username (RDP/Inactive)" } else{ $Username = '**None**' } } #Collecting most recent users from the registry $lastuser = @() $profiles = Get-CimInstance -Class Win32_UserProfile $profiles | Where-Object {$_.SID.length -gt 10} | Foreach-Object { $sid = $_.SID $prop = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$sid\" if($prop.LocalProfileUnLoadTimeHigh -and $prop.LocalProfileUnLoadTimeLow){ $a = '{0:x}' -f $prop.LocalProfileUnLoadTimeHigh $b = '{0:x}' -f $prop.LocalProfileUnLoadTimeLow $dec = [bigint]::Parse("$a$b",'AllowHexSpecifier') $time = w32tm /ntte $dec $lastTime = [datetime]($time -split ' - ')[1] } else{ $lastTime = "Unknown" } $obj = [PSCustomObject]@{ Name = ($_.LocalPath -split 'C:\\Users\\')[1] LocalPath = $_.LocalPath LastLoginTime = $lastTime } $lastuser += $obj } $lastuser = $lastuser | Where-Object LastLoginTime -ne 'Unknown' | Sort-Object LastLoginTime -Descending #Last User if($lastUser.Count -gt 1){ $lastUser1 = ($lastUser[0].Name + " (" + $lastUser[0].LastLoginTime + ")") $lastUser2 = ($lastUser[1].Name + " (" + $lastUser[1].LastLoginTime + ")") $lastUser3 = ($lastUser[2].Name + " (" + $lastUser[2].LastLoginTime + ")") $TotalLastUsers = "$lastUser1 $lastUser2 $lastUser3" }else{ $TotalLastUsers = $lastUser.Name + " (" + $lastUser.LastLoginTime + ")" } #ComputerModel $Model = $PCInfo.CsModel #RAM $totalram = $PCInfo.CsTotalPhysicalMemory $totalram = [math]::Round(($totalram / 1GB)) $ram = "$totalram GB" #Drive Type $DriveType = $physicalDisk.MediaType Write-Progress -Activity "Retrieving data from online computers" -Status $Env:COMPUTERNAME -PercentComplete 60 #Free Harddrive Space $CompFreeSpace = @([math]::Round($win32_LogicalDisk.FreeSpace / 1gb,2),[math]::Round($win32_LogicalDisk.Size / 1gb,2)) $free = $compFreeSpace[0] $max = $compfreeSpace[1] $freespace = "$free GB / $max GB" #Service Tag #$serviceTag = $win32_bios.SerialNumber $serviceTag = $PCInfo.BiosSeralNumber #BIOS #$biosVersion = $win32_bios.SMBIOSBIOSVersion $biosVersion = $PCInfo.BiosName #Last Reboot $lastbootTime = $PCInfo.OsLastBootUpTime #Asset Tag $assetTag = $win32_SystemEnclosure.SMBiosAssetTag #Bitlocker Status $PercentageEncrypted = (($bitlocker | Select-String "Percentage Encrypted") -split ': ')[1] [int]$IntPercentageEncrypted = $PercentageEncrypted.Substring(0,4) $EncryptionStatus = $null If($bitlocker -like '*error*') { $EncryptionStatus = 'BitLocker - Error - Please investigate' } Elseif($IntPercentageEncrypted -eq 100) { $EncryptionStatus = "BitLocker - Encrypted ($PercentageEncrypted)" } ElseIf($IntPercentageEncrypted -gt 1) { $EncryptionStatus = "BitLocker - Encrypting ($PercentageEncrypted)" } Else { $EncryptionStatus = "BitLocker - Decrypted ($PercentageEncrypted)" } #OS $os = $PCInfo.OSName + " (" + $PCInfo.OSArchitecture + ")" #OS Build $osVer = $PCInfo.WindowsVersion if($osVer -gt 2004){ $osVer = (Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion").DisplayVersion } $osBuild = $PCInfo.OSBuildNumber $osBuild = "Vers $osVer | Build #$osBuild" Write-Progress -Activity "Retrieving data from online computers" -Status $Env:COMPUTERNAME -PercentComplete 70 #Printers $printers = $win32_printer# ($win32_printer | Where-Object {$_.PortName -ne 'PORTPROMPT:' -and $_.PortName -ne 'nul:' -and $_.PortName -ne 'SHRFAX:'} | Select-Object -ExpandProperty Name) -join ' || ' if(!$printers){ $printers = "No Local/Networked Printer (Check Printer Mappings)" } #Imprivata $ImprivataType = $imprivataRegEntry | Select-Object -ExpandProperty Type if(!$imprivataType){ $ImprivataType = "Not Installed" } else{ Switch($ImprivataType){ 1 { $ImprivataType = $imprivataRegEntry | Select-Object -ExpandProperty FUS_Enabled Switch($ImprivataType){ 0 {$ImprivataType = "SUD"} 1 {$ImprivataType = "MUD"} } } 2 {$ImprivataType = "Kiosk"} Default {$ImprivataType = "Not Installed"} } } $kioskRole = try {$kioskRegEntry | Select-Object -ExpandProperty KioskRole} catch{ $null } if (!$kioskRole) { $kioskRole = "None"} #TPM if($win32_tpm){ $tpmVersion = " | Vers " + $win32_tpm.ManufacturerVersionFull20 $tpmStatus = "On" if($win32_tpm.IsActivated_InitialValue){ $tpmStatus += ", Activated" } else{ $tpmStatus += ", Not Activated" } if($win32_tpm.IsEnabled_InitialValue){ $tpmStatus += ", Enabled" } else { $tpmStatus += ", Disabled" } if($win32_tpm.IsOwned_InitialValue){ $tpmStatus += ", Owned" } else{ $tpmStatus += ", Not Owned" } $tpmStatus += $tpmVersion } else { $tpmStatus = "Off" } Write-Progress -Activity "Retrieving data from online computers" -Status $Env:COMPUTERNAME -PercentComplete 80 #Citrix Version if( !(Test-path $CitrixViewer)){ $CitrixVersion = "Not Installed" } else{ #Checks this default install path $CitrixVersion = Get-Command $citrixViewer | select-object -ExpandProperty Version #Grabs Citrix version number } #Chassis Type Switch -Wildcard($Model) { "Optiplex*" { Switch -Wildcard($CPU) { "Intel(R) Core(TM) i5-9500 CPU*" {$chassisType = "SFF"} #5070 "Intel(R) Core(TM) i5-6500 CPU*" {$chassisType = "SFF"} #7040 "Intel(R) Core(TM) i5-6500T*" {$chassisType = "Micro"} #7040 "Intel(R) Core(TM) i7-6700 CPU*" {$chassisType = "SFF"} #7040 "Intel(R) Core(TM) i7-6700T*" {$chassisType = "Micro"} #7040 "Intel(R) Core(TM) i5-10500T*" {$chassisType = "Micro"} #5080 "Intel(R) Core(TM) i5-9500T*" {$chassisType = "Micro"} #5070 "Intel(R) Core(TM) i5-8500 CPU*" {$chassisType = "SFF"} #5060 "Intel(R) Core(TM) i5-8500T*" {$chassisType = "Micro"} #5060 "Intel(R) Core(TM) i5-7500*" {$chassisType = "SFF"} #5050 "Intel(R) Core(TM) i5-4670 CPU*" {$chassisType = "SFF"} #9020 "Intel(R) Core(TM) i5-4590 CPU*" {$chassisType = "SFF"} #9020 "Intel(R) Core(TM) i5-4590T CPU*" {$chassisType = "Micro"} #9020M "Intel(R) Core(TM) i5-4690 CPU*" {$chassisType = "SFF"} #9020 "Intel(R) Core(TM) i5-3550 CPU*" {$chassisType = "SFF"} #9010 "Intel(R) Core(TM) i5-2400 CPU*" {$chassisType = "SFF"} #990 Default {$chassisType = "Optiplex - Chassis Type - Unknown"} } } "Latitude*" { $chassisType = "Laptop" } "Precision*"{ $chassisType = "Laptop" } "M24*" { $chassisType = "Anesthesia Cart" } "Medix*"{ $chassisType = "Anesthesia Cart" } Default {$chassisType = "Unknown Model/Chassis"} } if (${using:SparkEnabled}) { $uri = "${using:SparkURL}/api/odata/businessobject/CIs`?`$filter=Name+eq+%27$($Env:COMPUTERNAME)%27" try{ $Query = Invoke-RestMethod -Method GET -uri $uri -headers ${using:SparkHeaders} } catch { $ExceptionErrors += $_.Exception.Message } $cmdbData = $Query.Value if ($cmdbData.SHS_IsException -eq 'True') { Write-host "***NOTICE: $($Env:COMPUTERNAME) is a Device Exception computer. Please check CMDB/Asset Mgmt prior to supporting this workstation. ***" -BackgroundColor Black -ForegroundColor Yellow if($cmdb.SHS_IsVendorPC -eq 'True'){ $vendor = "Yes | Non-standard SHS Image/Hardware" } else{ $vendor = "No | Standard SHS Hardware" } $delInfo = [PSCustomObject]@{ Contact = $cmdbData.SHS_ExceptionContact Vendor = $vendor Description = $cmdbData.AssignedDescription } } $locationData = $cmdbData.SHS_Floor + ' - ' + $cmdbData.SHS_Department + ' - ' + $cmdbData.SHS_LocationDetails } Write-Progress -Activity "Retrieving data from online computers" -Status $Env:COMPUTERNAME -PercentComplete 90 #Output # $i++ | ProgressBar $i $comp 'Generating Output' $NumberofComputers $PCID $obj = New-Object -TypeName PSObject $obj | Add-Member -MemberType NoteProperty -Name 'Hostname' -Value $Env:COMPUTERNAME $obj | Add-Member -MemberType NoteProperty -Name 'Status' -Value "Online" $obj | Add-Member -MemberType NoteProperty -Name 'Current User' -Value "$userName" $obj | Add-Member -MemberType NoteProperty -Name 'Last User(s)' -Value "$TotalLastUsers" $obj | Add-Member -MemberType NoteProperty -Name 'IP | MAC' -Value "$ip | $mac" $obj | Add-Member -MemberType NoteProperty -Name 'Adapter' -Value "$adapter" $obj | Add-Member -MemberType NoteProperty -Name 'Model' -Value "$Model ($chassisType)" $obj | Add-Member -MemberType NoteProperty -Name 'OS' -Value $os $obj | Add-Member -MemberType NoteProperty -Name 'OS Build' -Value $osBuild $obj | Add-Member -MemberType NoteProperty -Name 'BIOS Ver' -Value "$biosVersion" $obj | Add-Member -MemberType NoteProperty -Name 'Encryption' -Value "$EncryptionStatus" $obj | Add-Member -MemberType NoteProperty -Name 'Free Space' -Value "$freespace | $driveType" $obj | Add-Member -MemberType NoteProperty -Name 'RAM' -Value "$ram" $obj | Add-Member -MemberType NoteProperty -Name 'SSO Client' -Value "$imprivataType" $obj | Add-Member -MemberType NoteProperty -Name 'Kiosk Role' -Value "$kioskRole" $obj | Add-Member -MemberType NoteProperty -Name 'Citrix Ver' -Value "$citrixVersion" $obj | Add-Member -MemberType NoteProperty -Name 'Asset Tag' -Value "$assetTag" $obj | Add-Member -MemberType NoteProperty -Name 'Service Tag' -Value "$serviceTag" $obj | Add-Member -MemberType NoteProperty -Name 'Last Reboot' -Value "$lastbootTime" $obj | Add-Member -MemberType NoteProperty -Name 'TPM Status' -Value "$tpmStatus" $obj | Add-Member -MemberType NoteProperty -Name 'MBAM GPO' -Value "$gpostatus" $obj | Add-Member -MemberType NoteProperty -Name 'Printers' -Value "$printers" if (${using:SparkEnabled}) { $obj | Add-Member -MemberType NoteProperty -Name 'CMDB Location' -Value "$locationData" } if ($delInfo) { $obj | Add-Member -MemberType NoteProperty -Name 'DEL Owner' -Value $delInfo.Contact $obj | Add-Member -MemberType NoteProperty -Name 'DEL Vendor PC' -Value $delInfo.Vendor $obj | Add-Member -MemberType NoteProperty -Name 'DEL Description' -Value $delInfo.Description } return $obj } #endregion $OnlineComputers = @() $OfflineComputers = @() $output = @() $itemIndex = 0 foreach($comp in $Computers){ $itemIndex++ BatchInvokesProgressBar -item $comp -currentItemIndex $itemIndex -TotalItems $Computers.Count -stage 1 $Connection = Test-Connection -ComputerName $comp -Count 1 if($Connection){ $OnlineComputers += $comp } else{ $OfflineComputers += $comp } } BatchInvokesProgressBar -stage 2 $invokeJob = Invoke-Command -ScriptBlock $sblock -ComputerName $OnlineComputers -SessionOption (New-PSSessionOption -NoMachineProfile -OpenTimeout 45000) -AsJob BatchInvokesProgressBar -stage 3 $offlineJobs = @() if($OfflineComputers.count -gt 0){ foreach($computer in $OfflineComputers){ $offlineJobs += Start-Job -ScriptBlock ${function:Get-SCCMQueryBlock} -ArgumentList $computer } } BatchInvokesProgressBar -stage 4 $output += $invokeJob | Receive-Job -Wait -AutoRemoveJob | Select-Object * -ExcludeProperty RunspaceId, PSComputerName, PSShowComputerName, PSSourceJobInstanceId $output += $offlineJobs | Receive-Job -Wait -AutoRemoveJob | Select-Object * -ExcludeProperty RunspaceId, PSComputerName, PSShowComputerName, PSSourceJobInstanceId $itemIndex = 0 $contactedhosts = $output.Hostname BatchInvokesProgressBar -stage 5 $missedhosts = $OnlineComputers | Where-Object -FilterScript {$_ -notin $contactedhosts} $missedJobs = @() if($missedhosts.count -gt 0){ foreach($computer in $missedhosts){ $missedJobs += Start-Job -ScriptBlock ${function:Get-SCCMQueryBlock} -ArgumentList $computer } } $output += $missedJobs | Receive-Job -Wait -AutoRemoveJob | Select-Object * -ExcludeProperty RunspaceId, PSComputerName, PSShowComputerName, PSSourceJobInstanceId return $output } Function Get-CMDBLocation { [CmdletBinding()] param ( [Parameter()] $cmdb ) if($null -eq $cmdb){ $location = "*CMDB Mismatch - check CMDB*" return $location } if($cmdb.values._SHSCalcLocationString.length -gt $cmdb.values._SHSLocation3.length){ $location = $cmdb.values._SHSCalcLocationString } else{ $location = $cmdb.values._SHSLocation3 } if($null -eq $location -or '' -eq $location){ $location = "*No location data - Please update CMDB*" } return $location } function BatchInvokesProgressBar { param ( $item, $currentItemIndex, $TotalItems, $stage ) switch ($stage) { 1 { Write-Progress -Activity "Connecting to computers" -Status "$item ($currentItemIndex/$TotalItems)" -PercentComplete (($currentItemIndex/$TotalItems) * 100)} 2 { Write-Progress -Activity "Spinning up jobs" -PercentComplete ((20/100) * 100)} 3 { Write-Progress -Activity "Querying SCCM for offline computers" -PercentComplete ((30/100) * 100)} 4 { Write-Progress -Activity "Awaiting Jobs" -PercentComplete ((60/100)*100)} 5 { Write-Progress -Activity "Querying SCCM for missed computers" -PercentComplete ((75/100) * 100)} Default {} } }