1

When I execute this powershell command to get a list of running COM objects that match the prefix "Python", I get the following output:

PS C:\Users\{path-to-arbitrary-directory}> Get-ChildItem HKLM:\Software\Classes | Where-Object {
        $_.PSChildName -match '^Python[\.a-zA-Z]*$' } | Select-Object


    Hive: HKEY_LOCAL_MACHINE\Software\Classes


Name                           Property                                                                                                                                                                     
----                           --------                                                                                                                                                                     
Python                         (default) : Python ActiveX Scripting Engine                                                                                                                                  
Python.Dictionary              (default) : Python Dictionary                                                                                                                                                
Python.Interpreter             (default) : Python Interpreter                                                                                                                                               
Python.TestServer              (default) : Python Test COM Server            

What I would like to do is just get a list of the Name and Description.

Currently I am able to get the names with this command:

PS C:\Users\{path-to-arbitrary-directory}> Get-ChildItem HKLM:\Software\Classes | Where-Object {
            $_.PSChildName -match '^Python[\.a-zA-Z]*$' } | Select-Object PSChildName,Property

PSChildName        Property   
-----------        --------   
Python             {(default)}
Python.Dictionary  {(default)}
Python.Interpreter {(default)}
Python.TestServer  {(default)}

But I can't for the life of me figure out how to show the Descriptions that I see when I execute the 1st command?

This is the output I would want:

Name                           Description
----                           --------                                                                                                                                                                     
Python                         Python ActiveX Scripting Engine                                                                                                                                  
Python.Dictionary              Python Dictionary                                                                                                                                                
Python.Interpreter             Python Interpreter                                                                                                                                               
Python.TestServer              Python Test COM Server  

(if it helps anyone, I am also able to view the description with this command)

PS C:\Users\{path-to-arbitrary-directory}> Get-ChildItem HKLM:\Software\Classes | Where-Object {
            $_.PSChildName -match '^Python[\.a-zA-Z]*$' } | Get-ItemProperty


(default)    : Python ActiveX Scripting Engine
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Classes\Python
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Classes
PSChildName  : Python
PSProvider   : Microsoft.PowerShell.Core\Registry

...
takanuva15
  • 1,286
  • 1
  • 15
  • 27

3 Answers3

2

One way to do this is the use of calculated properties. You can use Get-ItemProperty to get the value of the (default) registry key property. Then you can show this value as a calculated property.

Get-ChildItem HKLM:\software\Classes\ | 
Where-Object {$_.PSChildName -match 'document'} | 
Select-Object PSChildName, @{Name = "Default"; Expression = {($_ | Get-ItemProperty)."(default)"}}
vrdse
  • 2,899
  • 10
  • 20
2

Try this out. Things like this are better in functions.

function Get-COMDescription {
    Param(
        [parameter(Mandatory=$true)][string]$Search
    )
    Get-ChildItem HKLM:\Software\Classes | Where-Object { 
        # Match naming convention for COM Object ensure they key has a CLSID folder.
        $_.PSChildName -match "^$Search\.\w+$" -and (Test-Path -Path "$($_.PSPath)\CLSID") } | 
            Select-Object PSChildName,@{l="Description";e={$_ | Get-ItemProperty | select -ExpandProperty "(default)" }}
}

Usage example:

PS C:\> Get-COMDescription -Search GoogleUpdate

PSChildName                                  Description
-----------                                  -----------
GoogleUpdate.CoCreateAsync                   CoCreateAsync
GoogleUpdate.CoreClass                       Google Update Core Class
GoogleUpdate.CoreMachineClass                Google Update Core Class
GoogleUpdate.CredentialDialogMachine         GoogleUpdate CredentialDialog
GoogleUpdate.OnDemandCOMClassMachine         Google Update Broker Class Factory
GoogleUpdate.OnDemandCOMClassMachineFallback Google Update Legacy On Demand
GoogleUpdate.OnDemandCOMClassSvc             Google Update Legacy On Demand
GoogleUpdate.PolicyStatus                    Google Update Policy Status Class
GoogleUpdate.ProcessLauncher                 Google Update Process Launcher Class
GoogleUpdate.Update3COMClassService          Update3COMClass
GoogleUpdate.Update3WebMachine               Google Update Broker Class Factory
GoogleUpdate.Update3WebMachineFallback       GoogleUpdate Update3Web
GoogleUpdate.Update3WebSvc                   GoogleUpdate Update3Web
Ash
  • 3,030
  • 3
  • 15
  • 33
1

The existing answers are helpful, but let me add some background information:

The reason that the default output shows the target keys' values is that the default output formatting enumerates them, as this command reveals:

(Get-FormatData Microsoft.Win32.RegistryKey -PowerShellVersion $PSVersionTable.PSVersion).FormatViewDefinition.Control.Rows.Columns.DisplayEntry.Value

This shows:

PSChildName # column 1 - below is the script block that defines column 2
    $result = (Get-ItemProperty -LiteralPath $_.PSPath |
        Select * -Exclude PSPath,PSParentPath,PSChildName,PSDrive,PsProvider |
        Format-List | Out-String | Sort).Trim()
    $result = $result.Substring(0, [Math]::Min($result.Length, 5000) )
    if($result.Length -eq 5000) { $result += "..." }
    $result

As you can see, Get-ItemProperty is called behind the scenes to enumerate a key's values.

As an aside: This method of enumerating values as part of the formatting leads to incorrect output when retrieving values from a remote registry - see this answer.


While calling Get-ItemProperty in the script block of a calculated property, as shown in the other answers, definitely works, there is a more efficient alternative: You can call the .GetValue() method of the Microsoft.Win32.RegistryKey instances that Get-Item outputs:

Get-ChildItem HKLM:\Software\Classes |
  Where-Object PSChildName -match '^Python[\.a-z]*$' |
    Select-Object @{ n='Name'; e='PSChildName' }, 
                  @{ n='(default)'; e={ $_.GetValue('') } }
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • @takanuva15 Sorry - a final `}` was missing - please see my update. – mklement0 May 16 '20 at 21:19
  • Thanks. I noticed you mentioned that the function shows the available objects, but not the running ones. How would I see just the running objects? – takanuva15 May 17 '20 at 13:42
  • @takanuva15 Your question is an example of an [XY problem](http://meta.stackexchange.com/a/66378/248777): You wanted to get _running_ components, and thought that information in the _registry_ would help, so you asked about that; however, the registry doesn't track information about _running_ components, only _available_ ones (as noted in my comment on the question). Given that all answers here are registry-focused, I suggest you accept an answer here, and then ask a _new_ question, focused on your actual problem. – mklement0 May 17 '20 at 21:40