# requires -version 2.0 <# ----------------------------------------------------------------------------- Script: Select-PropertyValue-v2.ps1 Version: 2.0 Author: Jeffery Hicks http://jdhitsolutions.com/blog http://twitter.com/JeffHicks http://www.ScriptingGeek.com Date: 8/12/2011 Keywords: Object, Property, Get-Member, Select-Object Comments: "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 Select-PropertyValue { <# .SYNOPSIS Select only object properties with values. .DESCRIPTION Using an expression like: get-process PowerShell | select * is a handy way to see all properties and their values. But sometimes you may only want to see properties that have actual values. For those situations, use this function. This function can be used in a pipelined expression to return all properties of a given object that have a defined value. get-process PowerShell | Select-PropertyValue When looking at WMI objects you can use -NoSystem to filter out WMI system properties like __PATH. The function assumes that all input objects are of the same type. .PARAMETER InputObject The pipelined object. .PARAMETER NoSystem Filter out system properties for WMI objects like __PATH .PARAMETER Inquire When used in conjuction with -Debug, sets the debug preference to Inquire which will prompt you for each line. If you use -Debug alone then you'll get all the debug messages, but no prompting. .EXAMPLE PS C:\> get-service | select-propertyvalue CanStop : True DisplayName : Application Experience MachineName : . Name : AeLookupSvc ServiceHandle : SafeServiceHandle ServiceName : AeLookupSvc ServiceType : Win32ShareProcess Status : Running Type : System.ServiceProcess.ServiceController DisplayName : Application Layer Gateway Service MachineName : . Name : ALG ServiceHandle : SafeServiceHandle ServiceName : ALG ServiceType : Win32OwnProcess Status : Stopped Type : System.ServiceProcess.ServiceController DisplayName : Application Identity MachineName : . Name : AppIDSvc RequiredServices : {CryptSvc, RpcSs, AppID} ServiceHandle : SafeServiceHandle ServiceName : AppIDSvc ServicesDependedOn : {CryptSvc, RpcSs, AppID} ServiceType : Win32ShareProcess Status : Stopped Type : System.ServiceProcess.ServiceController ... Get only populated properties for the service object. .EXAMPLE PS C:\> get-wmiobject win32_bios | select-propertyvalue -nosystem BiosCharacteristics : {4, 7, 8, 9...} BIOSVersion : {TOSQCI - 6040000, Ver 1.00PARTTBL} Caption : Ver 1.00PARTTBL Description : Ver 1.00PARTTBL Manufacturer : TOSHIBA Name : Ver 1.00PARTTBL PrimaryBIOS : True ReleaseDate : 20101210000000.000000+000 SerialNumber : Z9131790W SMBIOSBIOSVersion : V2.90 SMBIOSMajorVersion : 2 SMBIOSMinorVersion : 6 SMBIOSPresent : True SoftwareElementID : Ver 1.00PARTTBL SoftwareElementState : 3 Status : OK Version : TOSQCI - 6040000 Type : System.Management.ManagementObject#root\cimv2\Win32_BIOS Get all populated properties for the WMI object, filtering out system properties. .NOTES NAME : Select-PropertyValue VERSION : 2.0 LAST UPDATED: 8/12/2011 AUTHOR : Jeffery Hicks .LINK http://jdhitsolutions.com/blog/2011/08/select-object-properties-with-values .LINK Get-Member Select-Object .INPUTS Any object .OUTPUTS A custom object #> [cmdletbinding()] Param( [Parameter(Position=0,ValueFromPipeline=$True)] [object]$InputObject, [Switch]$NoSystem, [Switch]$Inquire = $False ) Begin { Write-Verbose "Starting $($myinvocation.mycommand)" #define a variable we will be using to keep StrictMode happy. $properties=@() } #begin Process { <# set debug preference to continue when using -Debug unless user has also used -Inquire. Otherwise, PowerShell will prompt for each command. Due to scoping issues I found the best solution was to set the debug preference for each object in the pipeline #> if (($PSCmdlet.MyInvocation.BoundParameters.ContainsKey("debug")) -AND (-NOT $Inquire)) { $DebugPreference="Continue" } Write-Debug "In process" Write-Debug "Checking for `$properties" <# because this only takes pipelined objects, we only need to get the properties from Get-Member once. When the second object is processed, this IF block will get skipped. The assumption that all pipelined objects are of the same type. #> if (-Not $properties) { Write-Verbose "Creating property list" Write-Debug "Creating property list for pipelined object" #get properties for the pipelined object sorted by property name $properties=$_ | Get-Member -membertype Properties | sort Name $typename=($_ |Get-Member)[0].TypeName Write-Debug "Typename =$typename" #filter out WMI System properties if -NoSystem if ($NoSystem) { Write-Verbose "Filtering out WMI System properties" Write-Debug "Filtering out WMI System properties." $properties=$properties | where {$_.name -notlike "__*"} } Write-Verbose "Found $($properties.count) properties" Write-Debug "Found $($properties.count) properties" } #create an empty custom object Write-Debug "Creating empty object" $obj=New-Object PSObject #enumerate the list of properties Write-Verbose "Checking properties for values" foreach ($property in $properties) { Write-Debug "Checking $($property.name)" #if object has a value for the current property if ($_.($property.name)) { Write-Debug "found value for: $($_.($property.name))" #assign properties to the custom object Write-Debug "Adding property and value to custom object" $obj | Add-Member -MemberType Noteproperty -name $property.Name -value ($_.($property.name)) } #end If } #end ForEach #Add the typename to the object Write-Debug "Adding typename to custom object" $obj | Add-Member -MemberType Noteproperty -Name "Type" -Value $typename #write the custom object to the pipeline Write-Debug "Writing custom object to the pipeline" Write $obj } #end process End { Write-Verbose "Ending $($myinvocation.mycommand)" } } #end function #define an optional alias #Set-Alias -Name spv -value Select-PropertyValue