0

Following this question, I want to list all the methods and properties exposed by a Component Object Model (COM) object, given its ProgID. From here I can list all the COM object ProgIDs available from the registry:

dir  REGISTRY::HKEY_CLASSES_ROOT\CLSID -include PROGID -recurse | foreach {$_.GetValue(“”)}

though it adds some numbers (e.g., .1) at the end of some exported strings.

And here proposes a small script that does the job given the CLSID. Pseudocode:

[activator]::CreateInstance([type]::GetTypeFromCLSID($CLSID)) | Get-Member

One caveat, I don't know PowerShell and the above oneliner is most probably wrong.

I would appreciate it if you could help me know how I can get the list of methods and properties of a COM object knowing its ProgID (e.g., WScript.Shell), using the above snippets or any other way.

P.S. It doesn't have to be necessarily a PowerShell solution. cmd/batch, JScript, and VBScript solutions are also appreciated.

Foad S. Farimani
  • 12,396
  • 15
  • 78
  • 193
  • 1
    Are you looking for this: `[activator]::CreateInstance([type]::GetTypeFromProgID("WScript.Shell")) | get-member` (PS: Not all COM objects are "discoverable" as you seem to assume, only those with a "Type Library" registered). – Simon Mourier Nov 26 '20 at 08:29
  • @SimonMourier yes. that seems to be the correct answer. I need to test it on more COM objects though. I don't have a clue what is the difference between the COM objects with and without a Type Library. Is there also a way to list the methods and properties of the COM objects who don't have a Type Library? you are awesome. – Foad S. Farimani Nov 26 '20 at 08:37
  • 1
    No. Lots of COM objects just don't expose programmatically what they can do, or expose it only partially. They can be documented only by C++ header files (.h) or/and .idl, or just plain human-readable documentation. A Type Library is a metadata file that describes the object. It can created by tooling (IDL compiler, .NET, etc.) when a developer creates a COM object, but it's not mandatory to create it nor use it as a client. – Simon Mourier Nov 26 '20 at 08:51
  • @SimonMourier maybe we can look into binary's `.pdb` file as I have asked [here](https://reverseengineering.stackexchange.com/q/26374/24943) or their `.manifest` file as I have asked [here](https://www.reddit.com/r/windows/comments/k0gurh/what_is_the_difference_between_the_manifest_and/?utm_source=share&utm_medium=web2x&context=3)? – Foad S. Farimani Nov 26 '20 at 09:02
  • 2
    PDBs are debugging database files, produced by compilers and are generally not distributed by developers. Manifest is optional and just gives some information to Windows about an application. Just read the documentation/google. Not sure what you're trying to do. – Simon Mourier Nov 26 '20 at 09:06

1 Answers1

1

Public methods and properties are exposed if you instanciate an object from the COM Object

New-Object -ComObject WScript.Shell | Get-Member

will return

Name                     MemberType            Definition                                   
----                     ----------            ----------                                   
AppActivate              Method                bool AppActivate (Variant, Variant)          
CreateShortcut           Method                IDispatch CreateShortcut (string)            
Exec                     Method                IWshExec Exec (string)                       
ExpandEnvironmentStrings Method                string ExpandEnvironmentStrings (string)     
LogEvent                 Method                bool LogEvent (Variant, string, string)      
Popup                    Method                int Popup (string, Variant, Variant, Variant)
RegDelete                Method                void RegDelete (string)                      
RegRead                  Method                Variant RegRead (string)                     
RegWrite                 Method                void RegWrite (string, Variant, Variant)     
Run                      Method                int Run (string, Variant, Variant)           
SendKeys                 Method                void SendKeys (string, Variant)              
Environment              ParameterizedProperty IWshEnvironment Environment (Variant) {get}  
CurrentDirectory         Property              string CurrentDirectory () {get} {set}       
SpecialFolders           Property              IWshCollection SpecialFolders () {get}

The @Simon Mourrier strategy will work fine too

CFou
  • 978
  • 3
  • 13
  • Thanks a lot. Could you be kind to elaborate on the difference between your oneliner and @simon-mourier 's `[activator]::CreateInstance([type]::GetTypeFromProgID("WScript.Shell")) | get-member`? – Foad S. Farimani Nov 26 '20 at 21:53
  • They do/return the same thing. One is just using the defined cmdlet for the task, and the other is just calling the .Net namespace. Powershell is .Net/.Net Core (in the case of cross-platform PowerShell Core) based, use whatever ever method/approach you choose. There are many times, where you need to use the .Net namespace for a given use case; this is not really one of them. Also of note the -Force switch on the Get-Member call on both woudl provide more details. – postanote Nov 26 '20 at 23:32