# Jeffery Hicks # http://jdhitsolutions.com/blog # follow on Twitter: http://twitter.com/JeffHicks # # Learn more Windows PowerShell with a copy of Windows PowerShell 2.0: TFM (SAPIEN Press 2010) # # "Those who forget to script are doomed to repeat their work." # **************************************************************** # * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED * # * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF * # * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, * # * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. * # **************************************************************** function Get-ParentProcess { #requires -version 2.0 <# .SYNOPSIS Get parent and child process information using WMI. .DESCRIPTION Connect to a computer and create an object for each parent process that includes a property of all child processes. A parent process with no name most likely indicates a process that is no longer running, although it's child processes are. .PARAMETER Computername The name of a computer to connect to using WMI. The default is the local computer. The function assumes you have administrative privileges on any remote computer. .EXAMPLE PS C:\> get-parentprocess server01 .EXAMPLE PS C:\> get-parentprocess | where {$_.ParentProcess -eq "explorer.exe"} | Select-object -ExpandProperty Children .EXAMPLE PS C:\> get-content computers.txt | get-parentprocess .EXAMPLE PS C:\> get-content computers.txt | get-parentprocess | sort NumberofChildren | select Computername,ParentProcess,NumberOfChildren .INPUTS String .OUTPUTS A custom object .LINK Get-WMIObject .NOTES NAME: Get-ParentProcess VERSION: 1.1 AUTHOR: Jeffery Hicks LASTEDIT: May 21, 2010 Learn more Windows PowerShell with a copy of Windows PowerShell 2.0: TFM (SAPIEN Press 2010) #> [cmdletBinding()] Param( [Parameter(Position=0,ValueFromPipeline=$True,HelpMessage="Enter a computername")] [string[]]$computername=$env:computername) Begin { write-verbose "Starting $($myinvocation.mycommand)" #capture some performance metrics $start=Get-Date $total=0 } Process { foreach ($computer in $computername) { Write-Verbose "Testing $computer" if (Test-Connection -ComputerName $computer -quiet) { #only process if ping returns true Write-Verbose "Connecting to $computer" Get-WmiObject -Class win32_process -ComputerName $computer -outvariable data | Sort-Object -Property ParentProcessID | Group-Object -Property ParentProcessID | foreach { $ParentID=$_.Name $ParentProcess=$data | where {$_.processID -eq $parentID} if (-not $parentProcess) { write-verbose "nothing found for $parentID" } else { Write-Verbose "Parent process $($parentProcess.name)" } #convert creationdate to a friendly format if found if ($parentProcess.CreationDate) { $ParentCreation=$ParentProcess.ConvertToDateTime($parentProcess.CreationDate) } else { $ParentCreation=$null } #use computername from process object if it exists, otherwise #use the value from $computer if ($parentProcess.CSName) { $ParentComputerName=$parentProcess.CSName } else { $ParentComputerName=$computer } $NumberChildren=$_.group.count Write-Verbose "Found $NumberChildren child process(es)" $Children=$_.group | Select -property ProcessID,ProcessName,` @{Name="Created"; Expression={$_.ConvertToDateTime($_.CreationDate)}} Write-Verbose "Creating custom object" New-Object PSObject -Property @{ Computername=$ParentComputerName ParentID=$ParentID ParentProcess=$ParentProcess.Name ParentCreated=$ParentCreation NumberofChildren=$NumberChildren Children=$Children } } #end foreach } #end if Test-Connection else { Write-Warning "Failed to connect to $computer" } $total+=$data.count } #end foreach $computer }#Process End { $finish=Get-Date $msg="Processed {0} processes from {1} computers in {2}" -f ` $total,$computername.count,($finish-$start) write-verbose $msg write-verbose "Ending $($myinvocation.mycommand)" } } #end Function #optionally set an alias for this function Set-Alias gpp Get-ParentProcess