msiexec在python中编写脚本
大多数是背景,跳过接下来的3段问题:
我开发了一个工具,调用一些安装程序,更改注册表项,并移动文件,以帮助我测试具有相当快的更新周期的产品。到目前为止,我有一个GUI,它在一个单独的进程中运行到业务逻辑,以防止它由于GIL而锁定,一切正常等等,但是我对我的代码的一部分有所顾虑,我调用了msiexec。
具体来说,卸载部分给了我关注的问题。目前GUID没有改变所以我可以使用
os.system('msiexec /x "{GUID}" /passive')
的东西卸载产品。它实际上有点复杂,因为我正在使用subprocess.Popen并轮询它,直到它从一个事件循环中完成,以允许与其他步骤的并发。
我担心的是,如果GUID发生变化,显然这不起作用。我不想直接在安装源上指出msiexec,因为这意味着如果我“丢失”我存储在临时目录中的msi文件它将无法工作。
我正在寻找的是一种通过程序名查询来获取GUID的方法,甚至是msiexec的包装器,它可以完成所有这些,包括卸载,对我来说。我想通过注册表进行扫描,但是_winreg模块看起来很慢,所以如果可能的话,我宁愿避免这种情况。如果有更好的方法来扫描注册表,我会全力以赴,因为这也会加快工具的其他部分。
Update0
在此方面的性能至关重要,因为设计目标之一是使工具遵循的过程比任何其他方法(手动或其他方法)更快,以便获得批量采用。
UPDATE1
我尝试了下面的注册表版本的轻微变化,但它始终返回None
。我不太确定这是怎么回事 - 似乎没有打开相应的密钥,因为我在with
语句之后插入了一个断点,它从未到达...
def get_guid_by_name(name):
from _winreg import (OpenKey,
QueryInfoKey,
EnumKey,
QueryValueEx,
HKEY_LOCAL_MACHINE,
)
with OpenKey(HKEY_LOCAL_MACHINE,
r'SOFTWAREMicrosoftWindowsCurrentVersionUninstall') as key:
subkeys, _0, _1 = QueryInfoKey(key) # The breakpoint here is never reached
del _0, _1
for i in range(subkeys):
subkey = EnumKey(key, i)
if subkey[0] != '{' or subkey[-1] != '}':
continue
with OpenKey(key, subkey) as _subkey:
if name in QueryValueEx(_subkey, 'DisplayName')[0]:
return subkey
return None
print get_guid_by_name('Microsoft Visual Studio')
UPDATE2
罢工 - 我是一个傻瓜谁不彻底检查他的缩进 - print get_guid_by_name('Microsoft Visual Studio')
在get_guid_by_name
...
没有找到相关结果
已邀请:
1 个回复
缮记箔
在我的机器上,查询ActiveState的Komodo Edit(我实际上使用的是正则表达而不是直接值比较),1000次迭代需要8.18秒(使用timeit定时),这对我来说似乎是一个可以忽略不计的时间。更好的是,您可以从注册表中提取UninstallString键并将其直接传递给您的子进程(尽管您可能希望将
开关添加到末尾。 编辑 当然,Microsoft确实提供了一个WMI类(Win32_Product),它提供了一个相当方便的接口来完成所有这些工作。使用Tim Golden的优秀WMI包装器,可以启动这样的安装:
但是,正如本博文中所述,Win32_Product类的使用速度极其缓慢。