python wmi mac变动_Python WMI参数反转

使用python的wmi模块创建vss快照,我发现除非将它们反向,否则这些参数将不起作用:

importwmidefvss_create():shadow_copy_service=wmi.WMI(moniker='winmgmts:\\\\.\\root\\cimv2:Win32_ShadowCopy')res=shadow_copy_service.Create('ClientAccessible','C:\\')

在msdn docs中,应该以这种方式使用该函数:

Win32_ShadowCopy.Create("C:\\","ClientAccessible");

为什么会这样,有没有办法使用预期的订单?

解决方案

摘要

看起来Wmi对象的方法的参数顺序已被PyWin32层颠倒了,这种现象已经存在至少五年了。相关的wmi规范指出,wmi客户端可以按任何顺序传递参数,因此PyWin32这样做不是“错误”,尽管我无法确定这是故意还是偶然。我推测出于向后兼容的原因,它不太可能更改,但是您可以解决此问题,并通过将其指定为关键字参数来按所需顺序放置参数Create(Volume=, Context=)。

细节

注意在下面的详细信息中,我尝试逐层深入研究,从Python WMI模块代码到PyWin32代码中COM访问的WMI对象,再到其他语言中记录和使用的WMI对象,再到MOF文件指定的WMI对象规范,再到规格文件。有多个层次,我经常写“ WMI”,意思是不同层次上的不同事物。

当您说“ Python的wmi模块”时,您是说Tim Golden的基于PyWin32的Python WMI模块(链接到源代码)吗?

当从wmi模块获取Python WMI对象时,它经过的初始化步骤在类内_wmi_object,包括查询基础wmi对象以获取其可用方法:

forminole_object.Methods_:self.methods[m.Name]=None

我将跳过Python的wmi模块,直接使用PyWin32查看在查询WMI COM对象以获取其可用方法时所得到的结果:

>>>fromwin32com.clientimportGetObject>>>vss=GetObject('winmgmts:\\\\.\\root\\cimv2:Win32_ShadowCopy')>>>[method.Nameformethodinlist(vss.Methods_)][u'Create',u'Revert']

并且我们看到Win32_ShadowCopy对象具有方法Create和Revert。这就是Python wmi包装器首先了解Create您所使用的方法的地方。

从那里开始,Python WMI包装器类完成了一些设置工作,但我没有完全对其进行跟踪,但是它似乎为class _wmi_methodCOM对象的每个可用方法初始化了一次。此类包括以下初始化步骤:

self.method=ole_object.Methods_(method_name)self.in_parameter_names=[(i.Name,i.IsArray)foriinself.in_parameters.Properties_]

列表理解,以获取每种方法的可用参数。回到我的测试以探索没有Python WMI层的情况,它给出的输出如下:

>>>CreateMethod=vss.Methods_('Create')>>>[n.Nameforninlist(CreateMethod.InParameters.Properties_)][u'Context',u'Volume']

此示例测试显示了PyWin32,稍后是Win32_ShadowCopy的COM对象,该Create方法-按照您看到的顺序(“错误”顺序)列出其可用参数。Python WMI层正在接受该排序。

当您Create()通过Python WMI的包装器调用Win32_ShadowCopy对象的方法时,将_wmi_method执行以下操作:

def__call__(self,*args,**kwargs):forn_arginrange(len(args)):arg=args[n_arg]parameter=parameters.Properties_[n_arg]parameter.Value=arg

换一种说法;它将传入(*args)的参数与存储的参数列表一对一地配对,按照传递它们的顺序获取参数,并按WMI返回它们的顺序将它们与方法参数配对-即,它不是智能的,它只需将您输入的第一个参数与“上下文”链接起来,将第二个参数与“音量”链接起来,然后将它们向后移动,代码就会崩溃。

调用方法还包括Python**kwargs参数,该参数接受所有给定的关键字,建议您可以

Create(Volume='C:\\',Context="ClientAccessible")

并通过将它们用作关键字参数将它们按所需的顺序排列。(我没有尝试过)。

我尝试.Properties_通过PyWin32com跟踪查找,以尝试确定从较低层来的顺序,并且它经过一连串的动态查找和缓存查找。我看不到会发生什么,而且我对COM或PyWin32的了解不足,无法知道要寻找什么样的东西,所以这对我来说是死胡同。

采用另一种方法并尝试从WMI对象安装文件中查找顺序的来源:运行mofcomp.exeWindows附带的文件并处理托管对象格式(MOF)文件...单击“连接”,创建类“ Win32_ShadowCopy”;单击方法列表中的“创建”方法,然后单击“编辑方法”按钮;然后单击“编辑输入参数”,然后单击“显示MOF”,并得到以下结果:

[abstract]class__PARAMETERS{[in,ID(0):DisableOverrideToInstance]stringVolume;[in,ID(1):DisableOverrideToInstance]stringContext="ClientAccessible";};

这是Windows MOF文件中参数的“正确”顺序,带有参数的数字ID-表示它们的正确顺序为0、1等。

c:\windows\system32\wbem\vss.mof,似乎覆盖“卷影复制”对象的MOF文件包含以下内容:

[static,implemented,constructor]uint32Create([in]stringVolume,[in]stringContext="ClientAccessible",[out]stringShadowID);

MSDN链接的注释中的PowerShell示例包括$class.create("C:\", "ClientAccessible")。

因此,这三件事都以相同的顺序捆绑在一起,并暗示存在正确或标准的顺序。

这让我想到了这些可能性:

有一些订购信息是从PythonCOM发出的,而wmi模块应该查看它,但是没有。-我快速浏览了一下,找不到带有参数列表的ID /订购数据,因此似乎不太可能。

PyWin32 COM层应该查看但我不知道的某个地方有订购信息。-不确定这里。

没有官方订购。为了确认这一点,我们得到了一个有趣的链条:

什么是WMI?DTMF指定的Microsoft标准管理框架WBEM和CIM的实现。(DTMF =分布式管理工作组,WBEM是基于Web的企业管理,CIM是公共信息模型)。

MOF是托管对象格式,是CIM的文本表示形式

570行:

“一种方法可以具有零个或多个参数”。

626至628行:

方法参数是通过名称而不是位置来标识的,并且调用方法的客户端可以按任何顺序传递相应的参数。因此,可以在任何位置将具有默认值的参数添加到方法签名中。

我不确定这是否是权威性的最新规范,也无法阅读所有的规范以查找异常,但是听起来您应该使用命名参数。

WMI对象和方法具有MOF定义,并且MOF规范指出您不应依赖参数排序。但是,通过PyWin32通过COM访问WMI对象显示了不同的顺序(MSDN文档,MOF文件和PowerShell示例)。我仍然不知道为什么。

而谷歌搜索这 使我这个添金,Python的WMI模块的作者的邮件列表的帖子,他说基本上是相同的事情我只是发现,除五年前:

方法定义按照WMI返回它们的顺序来拾取参数[..]我不知道是否有关于参数[..]顺序的任何保证,看上去还有其他一些方法定义,好像WMI始终按照MOF中定义的相反顺序返回参数。

在这一点上,PyWin32似乎将反向列表返回到典型的Windows参数顺序,但是如果CIM受管对象方法参数列表规范文档明确表示不依赖参数顺序,那是否是一个bug?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值