Subscribe via Email

Subscribe via RSS


Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan

How to get a list of COM objects from the registry

Today I was looking for the COM ProgID for Excel on my machine and my previous approach of using WMI didn’t work.

That’s not correct as I can create a new COM object by referring to Excel.Application.

Since ProgIDs are found in the registry under HKEY_LOCAL_MACHINE\SOFTWARE\Classes I figured that would be a good place to get an exhaustive list from. Under this key there are three types of subkeys:

  1. Subkeys for each file extension registered with the system, each of which has a (Default) entry with the ProgID and also a subkey with the ProgID. Not all these ProgIDs seem to be valid though (based on my testing), so it’s best to go by the other set of subkeys detailed below.
  2. Subkeys for each ProgID – usually of both ProgID formats <Program>.<Component>.<Version> and <Program>.<Component> – again, not all valid, but a good test of validity (based on my testing) being whether they contain a subkey called CLSID.
  3. Subkeys such as “Unknown”, “Undecided”, etc and also some that look like ProgIDs but are not in the correct format (for instance: they don’t contain the <Component>.<Version> bit, or contain spaces and underscores (not allowed)

So a sensible way to filter out ProgIDs seems to be to check for subkeys of the format <Program>.<Component>.<Version> (the <Version> being optional) and to further filter out those which have a CLSID subkey.

Thus we have the following:

And to search for a specific application, one can do:

How to get a list of COM objects via WMI & PowerShell

Let’s see what WMI can tell us about COM objects on the system.

Get a list of all WMI classes with the word “COM” in them (doing a case sensitive match to avoid entries like “computer”).

Win32_COMApplication gives me about 386 results. It includes the AppID of the application associated with the COM object.

I am not a programmer so I won’t be going further into AppIDs and such, but it’s worth knowing about this and related COM terminology so here’s a quick rundown:

  1. All COM objects have a CLSID which is basically a 128-bit hexadecimal Globally Unique IDentifier (GUID) for the COM object. This way COM objects can be referred to independent of their installation path. The CLSID is unique across network computers too (relevant, when used with DCOM).

    WMI objects refer to this as ComponentID. They can also be found in the registry under HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID. For example, the CLSID for WordPad is {73FDDC80-AEA9-101A-98A7-00AA00374959}

  2. CLSIDs are not easy to remember, and sometimes COM objects with different CLSIDs can be used interchangeably (for instance: different versions of Internet Explorer will have different CLSIDs but you need some way of referring to the Internet Explorer COM object such that whatever version is installed on the system is used). For this reason you have ProgIDs (Programmatic IDentifier).

    ProgIDs can be found in the registry under HKEY_LOCAL_MACHINE\SOFTWARE\Classes. The format of a ProgID is <Program>.<Component>.<Version>, separated by periods and with no spaces. For example, the ProgID for WordPad is WordPad.Document.1.

    PowerShell’s New-Object cmdlet uses ProgID when creating new objects that refer to COM objects so ProgIDs are relevant to us.

  3. While not relevant to the current topic, there’s also an AppID which is yet another 128-bit hexadecimal GUID. You can read more about it here.

Now let’s get a list of how many objects are returned by each WMI class.

The biggest results are from the Win32_COMSetting class. Let’s compare the results of this with the Win32_ClassicCOMClassSetting class (which has the second largest number of results) to see what’s different. Since the ProgID property is what’s relevant to PowerShell, let’s filter the results to objects where ProgID is not $null.

There’s no difference. So in terms of ProgID both classes contain the same number of objects. Now let’s recreate the above table to only consider results where ProgID is not $null.

The interesting thing to note is that all the other classes have 0 objects now. In fact, we can see that the number of objects returned by the Win32_COMSetting class is equal to the number returned by Win32_ClassicCOMClassSetting plus Win32_COMApplication or Win32_DCOMApplication or Win32_DCOMApplicationSetting or Win32_COMApplicationSettings. Something to investigate later?

So, the best way to get COM objects via WMI & PowerShell is to use the Win32_COMSetting class. And to get the ProgID or any application (such as Internet Explorer in the previous post) something along the following lines will do:

If there’s only one version, the version number can be skipped in ProgID which is why InternetExplorer.Application too works.

Update: In fact, only the Win32_COMSetting and Win32_ClassicCOMClassSetting classes contain ProgID in their output. So these are the only two classes one can use. And since the only difference them is that Win32_COMSetting contains objects without any ProgID (of no use in our case!) it’s ok to use either class.

Update2: Turns out WMI is not a good way to get the list of COM objects. A better approach is to query the registry. See my next post.

Get a list of links in a web page (part 2)

A continuation to my previous post on getting links.

Internet Explorer is an application with a rich COM interface. And PowerShell can work with COM objects. Thus you can do the following:

The Document property is very powerful and lets you see a lot of details of the page. It has a subproperty Link that gives all the link elements in the page (it has nearly 800 properties, methods, and events!). The output is as objects, and since we are only interested in the actual link href elements we can select that property.

If you are PowerShell v3 things are even easier. There’s a cmdlet called Invoke-WebRequest who is your friend.

To get an object representing the website do:

To get all the links in that website:

And to just get a list of the href elements:

Like the System.Net.Webclient class Invoke-WebRequest has parameters to specify proxy, headers, encoding, etc.