【问题标题】:Consuming Python COM Server from .NET从 .NET 使用 Python COM 服务器
【发布时间】:2010-11-06 11:48:58
【问题描述】:

我想使用 win32com 扩展实现 python com 服务器。 然后从 .NET 中使用服务器。 我使用以下示例来实现 com 服务器,它运行时没有问题,但是当我尝试使用 C# 使用它时,我收到 FileNotFoundException 并显示以下消息“Retrieving the COM class factory for component with CLSID {676E38A6-7FA7-4BFF-9179 -AE959734DEBB} 由于以下错误而失败:8007007e。” .我也发布了 C# 代码。我想知道我是否遗漏了一些我希望得到帮助的东西。

谢谢, 莎拉

#PythonCOMServer.py

import pythoncom
class PythonUtilities:
    _public_methods_ = [ 'SplitString' ]
    _reg_progid_ = "PythonDemos.Utilities"
    # NEVER copy the following ID

    # Use"print pythoncom.CreateGuid()" to make a new one.
    _reg_clsid_ = pythoncom.CreateGuid()
    print _reg_clsid_
    def SplitString(self, val, item=None):
        import string
        if item != None: item = str(item)
        return string.split(str(val), item)

# Add code so that when this script is run by
# Python.exe,.it self-registers.

if __name__=='__main__':        
    print 'Registering Com Server'
    import win32com.server.register
    win32com.server.register.UseCommandLine(PythonUtilities)


// the C# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {

              Type pythonServer;
              object pythonObject;
              pythonServer = Type.GetTypeFromProgID("PythonDemos.Utilities");
              pythonObject = Activator.CreateInstance(pythonServer);

        }
    }
}

【问题讨论】:

  • 注意 python 代码中的警告,不要在每次调用时使用新的 GUID。只创建一次 GUID。
  • 您发布的代码是用于注册COM服务器的;您是否还实现(并运行)了实际的服务器?
  • 我认为注册服务器意味着它正在运行。你能给我更多的指导吗?谢谢

标签: .net python com


【解决方案1】:

COM 服务器只是一个软件(DLL 或可执行文件),它将通过定义的协议接受远程过程调用 (RPC)。协议的一部分规定服务器必须有一个唯一的 ID,存储在 Windows 的注册表中。 在我们的例子中,这意味着您“注册”了一个不存在的服务器。因此错误(未找到组件)。

所以,它应该是这样的(和往常一样,这是未经测试的代码!):

import pythoncom

class HelloWorld:
    _reg_clsctx_ = pythoncom.CLSCTX_LOCAL_SERVER
    _reg_clsid_ = "{B83DD222-7750-413D-A9AD-01B37021B24B}"
    _reg_desc_ = "Python Test COM Server"
    _reg_progid_ = "Python.TestServer"
    _public_methods_ = ['Hello']
    _public_attrs_ = ['softspace', 'noCalls']
    _readonly_attrs_ = ['noCalls']
    # for Python 3.7+
    _reg_verprogid_ = "Python.TestServer.1"
    _reg_class_spec_ = "HelloWorldCOM.HelloWorld"

    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 + str(who)

if __name__ == '__main__':
    if '--register' in sys.argv[1:] or '--unregister' in sys.argv[1:]:
        import win32com.server.register
        win32com.server.register.UseCommandLine(HelloWorld)
    else:
        # start the server.
        from win32com.server import localserver
        localserver.serve(['{B83DD222-7750-413D-A9AD-01B37021B24B}'])

然后你应该从命令行运行(假设脚本名为 HelloWorldCOM.py):

HelloWorldCOM.py --register
HelloWorldCOM.py

类 HelloWorld 是服务器的实际实现。它公开了一个方法(Hello)和几个属性,其中一个是只读的。 使用第一个命令,注册服务器;对于第二个,您运行它,然后它就可以在其他应用程序中使用。

【讨论】:

  • 为了正确运行前面的代码,我调用了方法 localserver.main() 而不是 localserver.serve('B83DD222-7750-413D-A9AD-01B37021B24B')。我启动了服务器并将 reg_progid 作为参数。
  • localserver.serve('B83DD222-7750-413D-A9AD-01B37021B24B') 几乎是正确的。您需要包含大括号并将其放入列表中:localserver.serve(['{B83DD222-7750-413D-A9AD-01B37021B24B}'])。否则工作完美。
  • 不注册可以运行吗?看我的问题。:stackoverflow.com/questions/41975659/…
  • 使用 Python 3.7(和最新版本的 PyWin32)的,需要添加变量:_reg_verprogid__reg_class_spec_。第一个与_reg_progid_ 大致相同(例如Python.TestServer.2),第二个应该是.(类似于Python 模块)。
  • 如何优雅地停止正在运行的服务器localserver.serve([{clsid}])? @EndreBoth
【解决方案2】:

您需要在您的 C# 可执行文件上运行 Process Monitor 以追踪未找到的文件。

【讨论】:

    猜你喜欢
    • 2011-06-23
    • 2010-09-15
    • 2011-09-18
    • 1970-01-01
    • 2017-06-17
    • 2011-08-23
    • 2015-08-18
    • 1970-01-01
    • 2010-12-17
    相关资源
    最近更新 更多