如何启动 COM 服务器?代码在 Python

How do I start a COM server? Code is in Python

我想 运行 Python 代码作为 COM 服务器。最终我想 运行 一个可用的 RTD 服务器 here. But first I want to know what exactly you have to do to getting any COM server running. So let's focus on this example

class HelloWorld:
    _reg_clsid_ = "{7CC9F362-486D-11D1-BB48-0000E838A65F}"

    _reg_desc_ = "Python Test COM Server"

    _reg_progid_ = "Python.TestServer"


    _public_methods_ = ['Hello']

    _public_attrs_ = ['softspace', 'noCalls']

    _readonly_attrs_ = ['noCalls']

    def __init__(self):
        self.softspace = 1
        self.noCalls = 0

    def Hello(self, who):
        self.noCalls = self.noCalls + 1
        # insert "softspace" number of spaces
        return "Hello" + " " * self.softspace + who


if __name__=='__main__':

    import win32com.server.register
    win32com.server.register.UseCommandLine(HelloWorld)

好的,它的工作方式是没有错误并且服务器已注册,因此它在 HKEY_CLASSES_ROOT 注册表中可用。但是我能用它做什么呢?有人说您必须编译一个实例并拥有一个 .dll 或 .exe 文件。我还需要做什么?

嗯,我运行你的榜样。服务器的注册表项位于:

HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{7CC9F362-486D-11D1-BB48-0000E838A65F}

它有两个子项...一个用于 LocalServer32,一个用于 InProcServer32

我在 Excel 中创建了一个简单的 VBA 宏:

Sub d()
Set obj = CreateObject("Python.TestServer")

MsgBox obj.Hello("joe")
End Sub

宏运行就好了。我的 Excel 版本是 64 位。我 运行 宏,然后在显示消息框时启动任务管理器。我可以在后台看到 pythonw.exe 运行。

我的 python 脚本和你的脚本之间的唯一区别可能是名称,而且我添加了一行要打印以确保我正在执行函数:

if __name__=='__main__':

    import win32com.server.register
    print("Going to register...")
    win32com.server.register.UseCommandLine(HelloWorld)

当我 运行 64 位 csript.exe 测试时,它工作......正如预期的那样......当我 运行 32 位版本时它失败了。

我知道为什么……有点…… InProcServer32 的注册表项是 pythoncom36.dll

那可不行。这是一条不完整的道路。我尝试修改我的 shell 上的路径变量,以将其添加到系统中存在 DLL 的 3 个位置之一,但它没有用。此外,尝试对 InProcServer32 中的路径进行编码。那没用..一直说找不到文件。

我 运行 procmon,然后我观察到它无法加载 vcruntime140.dll。在 python 下找到这些文件所在的目录,并将其添加到我的路径中。它走得更远。如果我足够关心,我可能会尝试更多。最终使用 procmon,我可以找到所有问题。但你可以做到。

我的简单解决方案是将 CLSID 的键 InProcServer32 重命名为 _InProcServer32。这是如何运作的?好吧,系统找不到 InProcServer32 所以它总是使用 LocalServer32——对于 32 位和 64 位进程。如果您需要进程中的速度,那么您需要通过使用 procmon 来解决问题并坚持不懈,直到您解决所有未找到文件错误等。但是,如果您不需要处理速度,那么使用 LocalServer32 可能会解决问题。

注意事项我使用的是我的雇主限制访问的 Anaconda 发行版,我只能从员工商店安装它。 YMMV.