#Filename: Get-PC.ps1 #This is the primary function for get-pc. All functionality is accessed through this function #See documentation for how to use this module #region Module Import Block $ErrorActionPreference = 'SilentlyContinue' #DevStage can take either Dev or Prod as values $devStage = 'Dev' #Locations for dev build and prod build $getPCDevBuildPath = '\\int.samhealth.net\files\TEAM\SHSISDesktopSolutions\Powershell\Get-PC_Update_2023\Prod\Get-PC\Get-PC.psd1' $getPCProdBuildPath = "\\shscm01\packages\SHS Custom\Get-PC\Prod\Get-PC\Get-PC.psd1" #grabs the version number out of the module manifest and compares it to the current production version $modulemanifest = Join-Path (get-item $PSScriptRoot).Parent.FullName 'Get-PC.psd1' $Version = (Test-ModuleManifest $modulemanifest).version if ($devStage -eq "Prod") { $deployedVersion = (Test-ModuleManifest $getPCProdBuildPath).Version } elseif ($devStage -eq "Dev") { $deployedVersion = (Test-ModuleManifest $getPCDevBuildPath).Version } $getPCWrappedPath = '\\int.samhealth.net\files\TEAM\SHSISDesktopSolutions\Powershell\Get-PC_Update_2023\Get-PC-Wrapped\backlog.txt' #lets user know when get-pc has been imported and what version they are running Write-Host "`nGet-PC Module Version $Version [$devStage] Loaded." -ForegroundColor Green if ($Version -ne $deployedVersion) { Write-Host 'New version of Get-PC is available. Please run Get-PC -Update' -ForegroundColor Yellow } Write-Host "Enter 'Help Get-PC' for available commands.`n" -ForegroundColor Green #endregion Function Get-PC { <# .Synopsis Get-PC is a custom Powershell module that contains many useful features for querying details about workstations and also performing many useful/common functions on those computers remotely. .DESCRIPTION Using get-pc hostname will query a workstation (or multiple workstations, comma separated) for information such as model, SSO client, currently logged in user, OS version, RAM, installed printers, etc… Expanded functionality can be accessed using these flags -Apps | shows the installed applications on the computer -AppDiff | shows the installed applications that are not in the standard image -Bypass | used in conjuction with remote viewer will bypass user prompt -ClearCCMCache | clears CCM cache, may fix software center -CMDB | only queries CMDB for info -Devices | shows connected monitors and usb devices -EventLog | pulls up errors in the event log for the last x days -Excel | exports collected data to csv and opens it with excel -Filesystem | access the file system -GPUpdate | runs a gpupdate -InstallNet35 | installs .Net 3.5 -LogOffUser | remotely logs off user -Monitor | monitors computers for changes in status -NextPrinterName | generates next open printer name -Orion | opens orion to the mac address of the pc -PCCleanup | removes temp files and inactive user profiles -PCReboot | reboots computer -PCRename | renames computer -RemoteDesktopApp | remote into computer using RDP -ResetRepository | remotely resets repository -Resources | more details about system resources -PrinterPurge | removes printer from all online computers -SCCM | queries sccm for the computer information -SHSPrinter | pulls data about a printer using snmp -SHSPrinterweb | pulls data about a printer and opens web interface and orion -SHSUser | get data about a user from AD, can accept username or employee number -Tableview | output the results in a table -UninstallProgram | remotely uninstall a program from a pc -Usb | shows installed usb devices -UserProfileBackup | backups and restores user profiles -ViewerRemote | remote into the computer using RemoteViewer -Wake | attempts to wake on LAN -WinProfileRebuild | rebuilds user profiles For more detailed help please see the documentation on AppDoc .EXAMPLE Get-PC [Hostname], [Hostname], [Hostname] .EXAMPLE Get-PC [Hostname] -TableView -Apps .EXAMPLE Get-PC [Hostname] -FileSystem #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)] [string[]]$ComputerName = $env:COMPUTERNAME, [Switch]$Apps, [Switch]$AppDiff, [Switch]$Bypass, [Switch]$ClearCCMCache, [Switch]$CMDB, [switch]$Devices, [Switch]$EventLog, [switch]$Excel, [Switch]$FileSystem, [Switch]$GPUpdate, [Switch]$HostnamesByPrinter, [switch]$InstallNet35, [switch]$Jobsprinters, [Switch]$LogOffUser, [Switch]$Monitor, [Switch]$NextPrinterName, [switch]$Orion, [Switch]$PatchNotes, [Switch]$PCCleanup, [Switch]$PCReboot, [Switch]$PCRename, [Switch]$Quiet, [Switch]$RemoteDesktopApp, [Switch]$ResetRepository, [Switch]$Resources, [Switch]$PrinterPurge, [Switch]$SCCM, [Switch]$SHSPrinter, [switch]$SHSPrinterWeb, [Switch]$SHSUser, [Switch]$TableView, [Switch]$UninstallProgram, [switch]$Update, [switch]$Usb, [Switch]$UserProfileBackup, [Switch]$ViewerRemote, [Switch]$Wake, [Switch]$WinProfileRebuild ) #Data collection for Get-PC Wrapped TM $invokeData = @{ Hostname = $env:COMPUTERNAME Username = $env:USERNAME Datetime = Get-Date -Format 'yyyy-MM-ddThh:mm:ss.fffffff' Parameters = $MyInvocation.BoundParameters } Add-Content -Path $getPCWrappedPath -Value $(ConvertTo-Json -Compress $invokeData) ## Define which Spark Record Properties are Returned $Spark_Property_Return = @( "Name", "ivnt_assetfulltype", "ivnt_location", "SHS_LocationDetails", "AssetTag", "SerialNumber", "Owner", "Status" ) <# if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Write-Warning "Get-PC requires powershell to be run as administrator. Please re-launch powershell as administrator." break } #> # Stuff only run once if ($Update) { #updates get pc Update-GetPC return } if ($PatchNotes) { $scriptparent = (get-item $PSScriptRoot ).parent.FullName Write-Host "`n" Get-Content $scriptparent\patchnotes.txt break } if ($Jobsprinters) { #runs the printer query as a set of jobs $outPutArray = Get-PCBatchJob($ComputerName) -printers Write-Output $outPutArray return } if($locationSearch){ Write-Host 'Please enter a partial location like a room number.' $searchInput = Read-Host 'Location' Write-Host "Searching CMDB for $searchInput ..." <# $ComputerName if($ComputerName.count -gt 1){ Write-Host 'Can only search a single location at a time' -ForegroundColor Yellow return } #> if($searchInput.ToCharArray().Length -lt 3){ Write-Host 'Location searches much contain more than 2 characters' -ForegroundColor Yellow return } $searchResults = Search-CMDB -Location $searchInput | Sort-Object -Property Hostname if($null -eq $searchResults){ Write-Host 'No results for given search' -ForegroundColor Yellow return } Write-Output $searchResults return } $charA = $ComputerName.ToCharArray() if($charA -contains '*'){ if($charA -lt 4){ Write-Host "Wildcard searches need to be at least 4 characters long" -ForegroundColor Red return } Write-Host "Starting CMDB Wildcard Search..." # $searchResults = Search-CMDB -hostname $ComputerName.Replace('*','') | Sort-Object -Property Hostname $output = @() foreach ($comp in $ComputerName) { $searchResults = Find-ISMBO -BusinessObject "cis" -SearchQuery $comp | Sort-Object -Property Name $output += Write-Output $searchResults | Select-Object $Spark_Property_Return } #$searchResults = Find-ISMBO -BusinessObject "cis" -SearchQuery $ComputerName.Replace('*','') | Sort-Object -Property Name if($TableView){ $output | Out-GridView -Title 'Get-PC Wildcard Search' } return $output } $getPCComputers = @() #List of computers that will get a batch query $outPutArray = @() #For use near the end of the script to output to users screen in a specified format $PCID = 1 #This is a helper variable for the progress bar $NumberofComputers = $ComputerName.Count foreach ($comp in $ComputerName) { #Pulls user data from AD if ($SHSUser) { $user = Get-SHSUser $comp $outPutArray += $user continue } $comp,$msg = Get-Hostname $comp if ($msg -and -not $SHSPrinter) { Write-Host "`n$msg" -ForegroundColor Red $props = [Ordered]@{ Hostname = "$msg" Status = "" 'Current User' = "" 'Last User(s)' = "" 'IP | MAC' = "" Model = "" 'OS' = "" 'OS Build' = "" 'BIOS Ver' = "" Encryption = "" 'Free Space' = "" RAM = "" 'SSO Client' = "" 'Kiosk Role' = "" 'Citrix Ver' = "" 'Asset Tag' = "" 'Service Tag' = "" 'Last Reboot' = "" 'TPM Status' = "" 'MBAM GPO' = "" Printers = "" } $obj = New-Object -TypeName PSObject -Property $props $outPutArray += $obj continue } if ($CMDB) { $outputArray += Get-CMDBFallback $comp continue } #DREW SUCKS #Pulls basic SNMP Data from printer $comp if ($SHSPrinter) { Write-Progress -Activity "Querying Printers" -Status "$comp ($PCID/$NumberofComputers)" -PercentComplete (($PCID / $NumberofComputers) * 100) $printer = Get-SHSPrinter $comp $outPutArray += $printer $PCID++ continue } if ($SHSPrinterWeb) { $printer = Get-SHSPrinter $comp Write-Output $printer Start-SHSPrinterWeb $printer break } #Grabs all hostnames that have the requested printer installed on it if ($HostnamesByPrinter) { $printers = HostnamesByPrinter $comp $out = @() foreach ($printer in $printers) { if ($printer -notlike '*EPIC*') { $out += $printer } } if ($TableView) { $out | Out-GridView -Title "Workstations Associated with $comp" } else { Write-Output $out } continue } if ($PrinterPurge) { Invoke-PrinterPurge $comp continue } #Generates an available printer hostname. Useful for supplying a new hostname in new printer requests if ($NextPrinterName) { Find-NextPrinterName $comp break } if ($Wake) { Invoke-Wake $comp continue } #PING HERE - All commands after here either require the computer to be online or need to know #------------------------------------------------------------------------------------------------------------------------------------------------------------------# $Connection = Test-Connection -ComputerName $comp -Count 1 Write-Progress -Activity "Connecting to computers" -Status "$comp ($PCID/$NumberofComputers)" -PercentComplete (($PCID / $NumberofComputers) * 100) if ($Connection) { $compStatus = 'Online' } else { $compStatus = 'Offline' } #grabs some basic usb info from the wmi if ($Usb) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" break } Get-USB $comp break } #grabs info on attached monitors and usb devices if ($Devices) { ProgressBar -CurrentPC $comp -NumberofComputers $NumberofComputers -Percent $PCID -CurrentLocationText 'Devices' -CurrentPCNumber $PCID $PCID++ if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus skipping monitor query" } $out = Get-Devices $comp $compStatus if ($null -eq $out) { Write-Warning "Unable to get device info for $comp" continue } $outPutArray += $out continue } #Pulls the event log for the past x days if ($EventLog) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" break } Get-PCEventLog $comp break } #Will remove selected users profile from C:\Users\ and cleans the registry of their profile if ($WinProfileRebuild) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" break } Get-WinProfileRebuild $comp break } if ($ResetRepository) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" continue } Get-ResetRepository $comp continue } #Backs up user profile to specified destination if ($UserProfileBackup) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" break } Get-UserProfileBackup $comp break } #Remotely renames and restarts the computer. if ($PCRename) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" break } Get-PCRename $comp break } #removes temp, cache files, and inactive user profiles if ($PCCleanup) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" break } Get-PCCleanup $comp Get-PCProfileCleanup $comp break } #Will reboot the users selected PC if ($PCReboot) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" break } Get-PCReboot $comp break } #Pulls brief overview of system resources if ($Resources) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" continue } get-resources $comp continue } #Pulls a list of installed programs from SCCM and Get-Package if ($Apps) { Get-Apps $comp $TableView continue } if ($AppDiff) { Get-AppDiff $comp $TableView continue } if ($UninstallProgram) { Invoke-UninstallProgram $comp break } if ($GPUpdate) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" continue } Get-GPUpdate $comp continue } #Will not notify the user that another user is about to remote onto their PC if ($Bypass) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" break } Get-Bypass $comp } #Removes any indicator that another user is remoted onto their PC (like the green bar) if ($Quiet) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" break } Invoke-Quiet $comp } #Runs Remote Viewer, Thick Client Only if ($ViewerRemote) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" break } Get-ViewerRemote $comp break } #Runs Remote Desktop Connection Application if ($RemoteDesktopApp) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" break } Get-RemoteDesktopApp $comp break } #Same as C$ into a workstation if ($FileSystem) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" continue } Get-FileSystem $comp continue } if ($ClearCCMCache) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" continue } Invoke-ClearCCMCache $comp continue } #Will log off the current logged in user for the designated PC #Adapted from Josh Gobens Logoff Script if ($LogOffUser) { if ($compStatus -ne 'Online') { Write-Warning "$comp is $compStatus unable to proccess command" break } Get-LogOffUser $comp break } if ($InstallNet35) { Get-InstallNet35 $comp continue } #Checks if there is a WinRM service error #TODO Re-evaluate where we want the WSNetwork test #$WSNetworkTest = Test-WSMan -ComputerName $comp #-or ($null -eq $WSNetworkTest) #checks to see if the computer is in AD or the disabled computers OU and warns the user if (get-module -ListAvailable -Name 'ActiveDirectory') { Write-Progress -Activity "Looking up computer in AD" -Status "$comp ($PCID/$NumberofComputers)" -PercentComplete (($PCID / $NumberofComputers) * 100) try { $adTest = ((Get-ADComputer $comp).DistinguishedName -match "Disabled Computers") } catch { $adTest = $true } if ($adTest) { Write-Warning "$comp is either disabled or off the domain" } Write-Progress -Activity "Looking up computer in AD" -Completed } #Direct SCCM Queries if ( $SCCM ) { $result = Get-SCCMQuery $comp $NumberofComputers $PCID $PCID++ $outPutArray += $result } else { #Checks if local computer if ($comp -eq $env:COMPUTERNAME) { $result = Get-PCLocal $comp $NumberofComputers $PCID #$PCID++ #$result = get-PCremoteCleaned $comp $Connection $NumberofComputers $PCID $outPutArray += $result #$getPCComputers += $comp } else { #$result = Get-PCRemote $comp $NumberofComputers $PCID #$result = get-PCremoteCleaned $comp $Connection $NumberofComputers $PCID #$PCID++ #$outPutArray += $result #Write-Output $result $getPCComputers += $comp } } if ($Orion) { break } } # Monitor list of PCs for change in online status or if ($Monitor) { Invoke-PCMonitor $getPCComputers return } #This is the get-pc of get-pc. It collects all the data from the computers and puts it in an array to be outputed $outPutArray += Get-PCBatchInvoke($getPCComputers) if ($Orion) { $mac = $outPutArray[0].'IP | MAC' -split " " if ($mac) { $mac = $mac[2] -split "," $mac = $mac[0] Write-Host "Launching Orion page to $mac" Start-Process "https://shsorion/Orion/UDT/EndpointDetails.aspx?NetObject=UE-MAC:VAL=$mac" } else { Write-Host "Unable to validate MAC" } } Write-Output $outPutArray #Creats an out grid view of all the data collected if ($TableView) { $outPutArray | Out-GridView -Title "Get-PC Grid" } #Takes the outputed data and exports it to a csv in the user's temp folder. Then opens that file with default csv viewer. It should be excel for most users if ($Excel) { ExportToExcel $outPutArray } } Function ProgressBar($Percent, $CurrentPC, $CurrentLocationText, $NumberofComputers, $CurrentPCNumber) { Write-Progress -Activity "Scanning PC $CurrentPC ($CurrentPCNumber/$NumberofComputers)" -Status "Querying: $CurrentLocationText" -PercentComplete (($Percent / 29) * 100) }