Python win32com – Class not registered error

Question:

I’m trying to control a device (Gamry Interface 5000 Potentiostat) via its COM interface using win32com.

# Imports
import win32com.client as client

# Get device list
devices = client.Dispatch('GamryCOM.GamryDeviceList')

# Iterate through devices
for i in range(devices.Count()):
    # Get device (this wors as we only have one connected yet)
    device = devices.EnumSections()[i]
    print(device)
    
# Setup potentiostat object
potentiostat = client.Dispatch('GamryCOM.GamryPstat')

When I run this, I got the following error message:

IFC5000-10519
Traceback (most recent call last):
  File "c:UsersRobAppDataLocalProgramsPythonPython39-32libsite-packageswin32comclientdynamic.py", line 86, in _GetGoodDispatch
    IDispatch = pythoncom.connect(IDispatch)
pywintypes.com_error: (-2147221021, 'Operation unavailable', None, None)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:Users[...]gamry_control_01.py", line 23, in <module>
    potentiostat = client.Dispatch('GamryCOM.GamryPstat', clsctx = pythoncom.CLSCTX_LOCAL_SERVER )
  File "c:UsersRobAppDataLocalProgramsPythonPython39-32libsite-packageswin32comclient__init__.py", line 117, in Dispatch
    dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch, userName, clsctx)
  File "c:UsersRobAppDataLocalProgramsPythonPython39-32libsite-packageswin32comclientdynamic.py", line 106, in _GetGoodDispatchAndUserName
    return (_GetGoodDispatch(IDispatch, clsctx), userName)
  File "c:UsersRobAppDataLocalProgramsPythonPython39-32libsite-packageswin32comclientdynamic.py", line 88, in _GetGoodDispatch
    IDispatch = pythoncom.CoCreateInstance(
pywintypes.com_error: (-2147221164, 'Class not registered', None, None)

Funnily enough, the first dispatch-statement just works fine, Just the second one fails.

I’m using a 64 Bit Windows 11 setup and tested different Python environments:

  • Python 3.10 64 Bit, win32com-303 64 Bit
  • Python 3.9 32 Bit, win32com-303 32 Bit

I also tried using comtypes instead of win32com which resulted in the same error.

Thank you very much for your help!

Regards

Asked By: Rob

||

Answers:

"Class not registered" means it cannot find the class factory for the class. That’s an error independent of Python and has nothing to do with it…other than the bitness of Python (whether it is 32 or 64-bit, and whether the COM server is 32 or 64-bit). It also matters whether the server is In Process (a DLL) or Out of Process (EXE). For EXE, it really doesn’t matter, but for an In-Process server, the bitness of the calling program and the COM server have to match. In order to see if you have a bitness problem, do this…

Create the following VB Script, call it test.vbs

set obj = CreateObject("GamryCOM.GamryDeviceList")
MsgBox TypeName(obj)

Call the script two times from the command line, one with the 64-bit VB Script engine, and once with the 32-bit engine. If you’re running from a directory other where test.vbs is located, you’ll have to supply the path to test.vbs as well.

64-bit engine:

c:windowssystem32wscript.exe test.vbs

32-bit engine:

c:windowssyswow64wscript.exe test.vbs

If the object is correctly registered and an EXE server, it should succeed for the script run both as 32 and 64-bit. If the object is correctly registered and a DLL server, it will succeed for only one run of the above script. If the object is incorrectly registered, it will fail for the script run with both engines.

In the case of double failure, you will have to figure out how the producer of the COM object expects you to call it. It could be licensing is involved.

In the case of single failure, you will have to use a different bitness of Python to match the server, or if you’re truly running 64-bit Python as you say, then maybe figure a way to host the 32-bit DLL in 64-bits using something like DllHost. I’ve never done it, but there are articles online on how to do it.

Answered By: Joseph Willcoxson

I had the same problem and contacted a Salesman.
He sent me a document, saying that on some devices you have to use
pstat = client.CreateObject('GamryCOM.GamryPC5Pstat') for the Reference family and
pstat = client.CreateObject('GamryCOM.GamryPC6Pstat') for the Interface family.
For me, at least the OSError: [WinError -2147221164] Class not registered disappears.
I’ve used "comtypes".

Answered By: David

To add on to the 64bit VS 32bit COM objects this article was helpful
https://www.codeproject.com/Tips/267554/Using-32-bit-COM-Object-from-64-bit-Application

I will list out the steps in case of internet decay

Using a 32-bit COM Object from a 64-bit Application:

  1. Locate your COM object GUID under HKey_Classes_Root/Wow6432Node/CLSID.
  2. Once located, add a new REG_SZ (string) value. The name should be AppID and
    the data should be the same COM object GUID you have just searched for.
  3. Add a new key under HKey_Classes_Root/Wow6432Node/AppID. The new key should
    be called the same as the COM object GUID.
  4. Under the new key you just added, add a new REG_SZ (string) value, and call
    it DllSurrogate. Leave the value empty.
  5. Create a new key under HKey_Local_Machine/Software/Classes/AppID, if it
    doesn’t already exist. Again, the new key should be called the same as the
    COM object’s GUID. No values
    are necessary to be added under this key.

Using these steps I created the necessary .reg files to automate the process in cases like switching computers etc..

Answered By: Jothan Kelepolo
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.