CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-comtypes

Pure Python COM package for Windows COM automation and interoperability

88

0.98x
Overview
Eval results
Files

server.mddocs/

Server Development

Framework for implementing COM servers in Python, including class factories, object registration, connection point support for events, and both in-process and local server architectures.

Capabilities

Base Server Classes

Foundation classes for implementing COM objects and coclasses with proper COM lifetime management.

class COMObject:
    """Base class for implementing COM objects in Python."""
    
    def __init__(self):
        """Initialize COM object with reference counting."""
    
    def QueryInterface(self, interface):
        """
        Query for interface implementation.
        
        Args:
            interface (type): Interface class to query for
        
        Returns:
            Interface implementation or None
        """
    
    def AddRef(self):
        """
        Increment reference count.
        
        Returns:
            int: New reference count
        """
    
    def Release(self):
        """
        Decrement reference count.
        
        Returns:
            int: New reference count (0 if object destroyed)
        """

class CoClass(COMObject):
    """Base class for COM coclasses with metaclass support."""
    
    _reg_clsid_: str        # Class identifier for registration
    _reg_progid_: str       # Programmatic identifier
    _reg_desc_: str         # Description for registry
    _reg_clsctx_: int       # Class context flags
    
    def __init__(self):
        """Initialize coclass with proper COM semantics."""

Class Factory

Standard COM class factory interface for creating object instances.

class IClassFactory(IUnknown):
    """Standard interface for creating COM object instances."""
    
    def CreateInstance(self, outer, interface):
        """
        Create new instance of COM object.
        
        Args:
            outer (IUnknown, optional): Outer object for aggregation
            interface (type): Interface to query for on new instance
        
        Returns:
            New COM object instance
        
        Raises:
            COMError: If creation fails or aggregation not supported
        """
    
    def LockServer(self, lock):
        """
        Lock server in memory to prevent unloading.
        
        Args:
            lock (bool): True to lock, False to unlock
        """

Object Registration

Functions for registering COM objects in the Running Object Table and with the system.

def RegisterActiveObject(comobj, weak=True):
    """
    Register COM object as active for client access.
    
    Args:
        comobj: COM object instance to register
        weak (bool): Use weak reference to allow object cleanup
    
    Returns:
        int: Registration token for later revocation
    """

def RevokeActiveObject(token):
    """
    Remove object from Running Object Table.
    
    Args:
        token (int): Registration token from RegisterActiveObject
    """

Server Types

Different server implementation patterns supported by comtypes.

In-Process Server

# From comtypes.server.inprocserver module

def DllCanUnloadNow():
    """
    Determine if DLL can be unloaded.
    
    Returns:
        HRESULT: S_OK if can unload, S_FALSE if still in use
    """

def DllGetClassObject(clsid, iid):
    """
    Get class factory for specified class.
    
    Args:
        clsid (GUID): Class identifier
        iid (GUID): Interface identifier (usually IClassFactory)
    
    Returns:
        Class factory instance
    """

# Note: DllRegisterServer and DllUnregisterServer are not implemented
# in comtypes. These functions would need to be implemented by the 
# application developer for COM server registration.

Local Server

# From comtypes.server.localserver module

class LocalServer:
    """Framework for implementing local (out-of-process) COM servers."""
    
    def run(self, classobjects):
        """
        Start local server with registered class objects.
        
        Args:
            classobjects (dict): Mapping of CLSIDs to class factory objects
        """
    
    def run_sta(self):
        """Run server in single-threaded apartment mode."""
    
    def run_mta(self):
        """Run server in multi-threaded apartment mode."""
    
    def Lock(self):
        """Increment server lock count."""
    
    def Unlock(self):
        """Decrement server lock count."""

Connection Points

Support for COM events and callbacks through connection point interfaces.

class IConnectionPointContainer(IUnknown):
    """Container interface for managing connection points."""
    
    def EnumConnectionPoints(self):
        """
        Get enumerator for all connection points.
        
        Returns:
            IEnumConnectionPoints: Connection point enumerator
        """
    
    def FindConnectionPoint(self, iid):
        """
        Find connection point for specific interface.
        
        Args:
            iid (GUID): Event interface identifier
        
        Returns:
            IConnectionPoint: Connection point for interface
        """

class IConnectionPoint(IUnknown):
    """Individual connection point for specific event interface."""
    
    def GetConnectionInterface(self):
        """
        Get interface ID for this connection point.
        
        Returns:
            GUID: Event interface identifier
        """
    
    def GetConnectionPointContainer(self):
        """
        Get parent connection point container.
        
        Returns:
            IConnectionPointContainer: Parent container
        """
    
    def Advise(self, sink):
        """
        Connect event sink to receive events.
        
        Args:
            sink: Object implementing event interface
        
        Returns:
            int: Connection cookie for later disconnection
        """
    
    def Unadvise(self, cookie):
        """
        Disconnect event sink.
        
        Args:
            cookie (int): Connection cookie from Advise
        """
    
    def EnumConnections(self):
        """
        Get enumerator for active connections.
        
        Returns:
            IEnumConnections: Active connection enumerator
        """

Registration Utilities

Helper functions for COM server registration and unregistration.

# From comtypes.server.register module

def register(cls):
    """
    Register COM class in system registry.
    
    Args:
        cls (type): CoClass to register (must have registration attributes)
    """

def unregister(cls):
    """
    Remove COM class from system registry.
    
    Args:
        cls (type): CoClass to unregister
    """

Usage Examples

Basic COM Object Implementation

import comtypes
from comtypes.server import COMObject

class MyComObject(COMObject):
    """Simple COM object implementation."""
    
    # Define supported interfaces
    _com_interfaces_ = [comtypes.IUnknown]
    
    def __init__(self):
        super().__init__()
        print("COM object created")
    
    def my_method(self):
        """Custom method implementation."""
        return "Hello from COM object"

# Create and use object
obj = MyComObject()
result = obj.my_method()
print(result)

CoClass with Registration

import comtypes
from comtypes.server import CoClass
from comtypes.GUID import GUID

# Define custom interface
class IMyInterface(comtypes.IUnknown):
    _iid_ = GUID("{12345678-1234-5678-9ABC-123456789ABC}")
    _methods_ = [
        comtypes.STDMETHOD(comtypes.HRESULT, "DoSomething", 
                          (['in'], comtypes.c_int, "value"))
    ]

class MyCoClass(CoClass):
    """COM coclass with registration information."""
    
    # Registration metadata
    _reg_clsid_ = "{87654321-4321-8765-CBA9-987654321CBA}"
    _reg_progid_ = "MyApp.MyCoClass.1"
    _reg_desc_ = "My COM CoClass"
    _reg_clsctx_ = comtypes.CLSCTX_INPROC_SERVER
    
    # Supported interfaces
    _com_interfaces_ = [IMyInterface]
    
    def DoSomething(self, value):
        """Implementation of interface method."""
        print(f"DoSomething called with value: {value}")
        return comtypes.S_OK

# Register the class (requires admin privileges)
from comtypes.server.register import register_class
register_class(MyCoClass)

Event Source Implementation

import comtypes
from comtypes.server import COMObject
from comtypes.connectionpoints import IConnectionPointContainer, IConnectionPoint

# Define event interface
class IMyEvents(comtypes.IUnknown):
    _iid_ = GUID("{11111111-2222-3333-4444-555555555555}")
    _methods_ = [
        comtypes.COMMETHOD([], comtypes.HRESULT, "OnSomethingHappened",
                          (['in'], comtypes.BSTR, "message"))
    ]

class MyEventSource(COMObject):
    """COM object that fires events."""
    
    _com_interfaces_ = [IConnectionPointContainer]
    _outgoing_interfaces_ = [IMyEvents]
    
    def __init__(self):
        super().__init__()
        self._connections = {}
    
    def fire_event(self, message):
        """Fire event to all connected sinks."""
        for sink in self._connections.values():
            try:
                sink.OnSomethingHappened(message)
            except Exception as e:
                print(f"Error firing event: {e}")
    
    # Connection point implementation would go here
    # (simplified for example)

In-Process Server

# myserver.py - In-process COM server
import comtypes
from comtypes.server.inprocserver import *

class MyInProcServer(CoClass):
    _reg_clsid_ = "{AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE}"
    _reg_progid_ = "MyServer.Application.1"
    _reg_desc_ = "My In-Process COM Server"
    
    _com_interfaces_ = [comtypes.IUnknown]
    
    def get_message(self):
        return "Hello from in-process server"

# Register exported classes
_reg_classes_ = [MyInProcServer]

# Build as DLL and register with:
# regsvr32 myserver.dll

Local Server

# localserver.py - Local COM server
import comtypes
from comtypes.server.localserver import LocalServer

class MyLocalServer(CoClass):
    _reg_clsid_ = "{FFFFFFFF-EEEE-DDDD-CCCC-BBBBBBBBBBBB}"
    _reg_progid_ = "MyLocalServer.Application.1"
    _reg_desc_ = "My Local COM Server"
    
    _com_interfaces_ = [comtypes.IUnknown]
    
    def get_data(self):
        return "Data from local server"

if __name__ == "__main__":
    # Create and run local server
    server = LocalServer()
    server.register_class(MyLocalServer)
    
    print("Starting local COM server...")
    server.run()  # Blocks until shutdown

Class Factory Implementation

import comtypes
from comtypes.server import IClassFactory, COMObject

class MyClassFactory(COMObject):
    """Custom class factory implementation."""
    
    _com_interfaces_ = [IClassFactory]
    
    def __init__(self, target_class):
        super().__init__()
        self.target_class = target_class
    
    def CreateInstance(self, outer, interface):
        """Create new instance of target class."""
        if outer is not None:
            raise comtypes.COMError(comtypes.hresult.CLASS_E_NOAGGREGATION)
        
        # Create instance
        instance = self.target_class()
        
        # Query for requested interface
        return instance.QueryInterface(interface)
    
    def LockServer(self, lock):
        """Lock/unlock server in memory."""
        # Implementation depends on server type
        pass

Install with Tessl CLI

npx tessl i tessl/pypi-comtypes

docs

automation.md

client-api.md

core-com.md

index.md

server.md

utilities.md

tile.json