boot_com_servers.py 4.36 KB
# This support script is executed as the entry point for py2exe.

import sys
import win32api

if 0:
    ################################################################
    # XXX Remove later!
    class LOGGER:
        def __init__(self):
            self.softspace = None
            self.ofi = open(r"c:\comerror.txt", "w")
        def write(self, text):
            self.ofi.write(text)
            self.ofi.flush()
    sys.stderr = sys.stdout = LOGGER()
    sys.stderr.write("PATH is %s\n" % sys.path)
################################################################
# tell the win32 COM registering/unregistering code that we're inside
# of an EXE/DLL
import pythoncom
if not hasattr(sys, "frozen"):
    # standard exes have none.
    sys.frozen = pythoncom.frozen = 1
else:
    # com DLLs already have sys.frozen set to 'dll'
    pythoncom.frozen = sys.frozen

# Add some extra imports here, just to avoid putting them as "hidden imports"
# anywhere else - this script has the best idea about what it needs.
# (and hidden imports are currently disabled :)
import win32com.server.policy, win32com.server.util

# Patchup sys.argv for our DLL
if sys.frozen=="dll" and not hasattr(sys, "argv"):
    sys.argv = [win32api.GetModuleFileName(sys.frozendllhandle)]
# We assume that py2exe has magically set com_module_names
# to the module names that expose the COM objects we host.
# Note that here all the COM modules for the app are imported - hence any
# environment changes (such as sys.stderr redirection) will happen now.
com_modules = []
try:
    for name in com_module_names:
        __import__(name)
        com_modules.append(sys.modules[name])
except NameError:
    print "This script is designed to be run from inside py2exe"
    sys.exit(1)
del name

def get_classes(module):
    return [ob
            for ob in module.__dict__.values()
            if hasattr(ob, "_reg_progid_")
            ]

def DllRegisterServer():
    # Enumerate each module implementing an object
    import win32com.server.register
    for mod in com_modules:
        # register each class
        win32com.server.register.RegisterClasses(*get_classes(mod))
        # see if the module has a custom registration function.
        extra_fun = getattr(mod, "DllRegisterServer", None)
        if extra_fun is not None:
            extra_fun()

def DllUnregisterServer():
    # Enumerate each module implementing an object
    import win32com.server.register
    for mod in com_modules:
        # see if the module has a custom unregister function.
        extra_fun = getattr(mod, "DllUnregisterServer", None)
        if extra_fun is not None:
            extra_fun()
        # and unregister each class
        win32com.server.register.UnregisterClasses(*get_classes(mod))

def DllInstall(bInstall, cmdline):
    # Enumerate each module implementing an object
    for mod in com_modules:
        # see if the module has the function.
        extra_fun = getattr(mod, "DllInstall", None)
        if extra_fun is not None:
            extra_fun(bInstall, cmdline)

# Mainline code - executed always
# If we are running as a .EXE, check and process command-line args
if sys.frozen != "dll":
    import win32com.server.localserver
    for i in range(1, len(sys.argv)):
        arg = sys.argv[i].lower()
        # support "exe /regserver"
        if arg.find("/reg") > -1 or arg.find("--reg") > -1 \
               or arg.find("-regserver") > -1:
            DllRegisterServer()
            break

        # support "exe /unreg...r"
        if arg.find("/unreg") > -1 or arg.find("--unreg") > -1 \
               or arg.find("-unregserver") > -1:
            DllUnregisterServer()
            break
        
        # MS seems to like /automate to run the class factories.
        if arg.find("/automate") > -1:
            clsids = []
            for m in com_modules:
                for k in get_classes(m):
                    clsids.append(k._reg_clsid_)
            # Fire up the class factories, and run the servers
            win32com.server.localserver.serve(clsids)
            # All servers dead - we are done!
            break
    else:
        # You could do something else useful here.
        win32api.MessageBox(0,
                            "This program hosts a COM Object and\r\n"
                            "is started automatically\r\n"
                            "(or maybe you want /register or /unregister?)",
                            "COM Object")