Python无法在特殊情况下导入WMI

时间:2016-08-09 20:50:20

标签: python service wmi pyinstaller

我创建了一个用Python编写并使用pyInstaller构建的独立的exe Windows服务。当我尝试导入wmi时,会抛出异常。

真正令人费解的是,如果在前台exe,前景python脚本或通过pythonservice.exe作为后台服务运行的python脚本中运行代码,我可以毫无问题地执行此操作!

为什么在作为服务exe运行的特殊情况下它会失败?

import wmi

为我生成此错误:

com_error: (-2147221020, 'Invalid syntax', None, None)

这里是追溯:

Traceback (most recent call last):
  File "<string>", line 43, in onRequest
  File "C:\XXX\XXX\XXX.pyz", line 98, in XXX
  File "C:\XXX\XXX\XXX.pyz", line 31, in XXX
  File "C:\XXX\XXX\XXX.pyz", line 24, in XXX
  File "C:\XXX\XXX\XXX.pyz", line 34, in XXX
  File "C:\Program Files (x86)\PyInstaller-2.1\PyInstaller\loader\pyi_importers.py", line 270, in load_module
  File "C:\XXX\XXX\out00-PYZ.pyz\wmi", line 157, in <module>
  File "C:\XXX\XXX\out00-PYZ.pyz\win32com.client", line 72, in GetObject
  File "C:\XXX\XXX\out00-PYZ.pyz\win32com.client", line 87, in Moniker

wmi.py第157行对GetObject进行全局调用:

obj = GetObject ("winmgmts:")

win32com \ client__init.py__包含GetObject(),最终调用Moniker():

def GetObject(Pathname = None, Class = None, clsctx = None):
  """
    Mimic VB's GetObject() function.

    ob = GetObject(Class = "ProgID") or GetObject(Class = clsid) will
    connect to an already running instance of the COM object.

    ob = GetObject(r"c:\blah\blah\foo.xls") (aka the COM moniker syntax)
    will return a ready to use Python wrapping of the required COM object.

    Note: You must specifiy one or the other of these arguments. I know
    this isn't pretty, but it is what VB does. Blech. If you don't
    I'll throw ValueError at you. :)

    This will most likely throw pythoncom.com_error if anything fails.
  """
  if clsctx is None:
    clsctx = pythoncom.CLSCTX_ALL

  if (Pathname is None and Class is None) or \
     (Pathname is not None and Class is not None):
    raise ValueError("You must specify a value for Pathname or Class, but not both.")

  if Class is not None:
    return GetActiveObject(Class, clsctx)
  else:
    return Moniker(Pathname, clsctx)    

Moniker()中的第一行,即MkParseDisplayName()是遇到异常的地方:

def Moniker(Pathname, clsctx = pythoncom.CLSCTX_ALL):
  """
    Python friendly version of GetObject's moniker functionality.
  """
  moniker, i, bindCtx = pythoncom.MkParseDisplayName(Pathname)
  dispatch = moniker.BindToObject(bindCtx, None, pythoncom.IID_IDispatch)
  return __WrapDispatch(dispatch, Pathname, clsctx=clsctx)

注意:我尝试使用

pythoncom.CoInitialize()

显然在一个帖子中解决了这个导入问题,但是没有用......

4 个答案:

答案 0 :(得分:5)

我也面临同样的问题,最后我发现了这个问题, 导入pythoncom和CoInitialize pythoncom.CoInitialize()。他们导入wmi

import pythoncom
pythoncom.CoInitialize ()
import wmi

答案 1 :(得分:0)

我尝试过无数种方式。最后,我全身心投入,不得不找到一种不同的方法来实现与wmi相同的目标。

显然,当尝试创建具有无效&#34;名字对象名称&#34;的对象时,会抛出无效的语法错误,这可能只是意味着系统上不存在服务,应用程序等。在这种情况下&#34; winmgmts&#34;似乎根本无法找到它!是的,我尝试使用其他规格对该名称进行了大量修改,并尝试在不同的用户帐户下运行该服务等。

答案 2 :(得分:0)

错误“ com_error:(-2147221020,'无效语法',None,None)“正是我的情况,因此经过长时间的网上搜索后我才来到这里:

  

在这种情况下根本找不到“ winmgmts”   似乎!

这是正确的提示,因为我只有一个错字,使用了“ winmgmt:”而没有在后面加上“ s”。因此,无效的sythax是指第一个方法参数,而不是python代码本身。 o_0不幸的是,我找不到任何引用,我们可以通过win32com.client.GetObject()获得哪些对象...因此,如果有人暗示“允许”使用参数/应该起作用,请在此处进行移植。 :-)

亲切的问候 克里斯·菲尔(ChrisPHL)

答案 3 :(得分:0)

老实说,我没有挖洞是为了理解为什么会发生这种情况。

无论如何,以下导入解决了我的问题-仅在从Flask实例运行时才发生:

import os
import pythoncom
pythoncom.CoInitialize()
from win32com.client import GetObject
import wmi