使用 comtypes.client.CreateObject() 后释放安装程序对象
Release Installer Object after using comtypes.client.CreateObject()
我在 python 中使用 comtypes.client
模块编写了一个函数,该函数应该从 .msi 文件打开数据库并写入一个特殊的(键,值)对。到目前为止我的问题是一旦调用函数没有问题,我尝试使用 os.rename()
重命名 .msi 文件然后得到权限错误:
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process
我的理解是我的 COM 对象仍在使用中,因此我无法访问该文件,函数和函数调用看起来像(显然这非常简化,但看起来应该这样工作):
import comtypes.client
import os, shutil
def setInstallerAttribute(installer_path, attribute_key, attribute_value):
installerCOM = comtypes.client.CreateObject("WindowsInstaller.Installer")
installerDatabase = installerCOM.OpenDatabase (installer_path, 1)
view = installerDatabase.OpenView ("INSERT INTO Property (Property, Value) VALUES ('{0}', '{1}')".format(attribute_key, attribute_value))
view.Execute
installerDatabase.Commit
view = None
installerDatabase = None
installerCOM = None
if __name__ == "__main__":
input = '{}'.format(msi_fullapth)
key = "Build"
value = "test_value"
if os.path.exists(input):
setInstallerAttribute(input, key, value)
os.rename(input, {some other path})
写这个函数是因为我之前使用VBScript来设置这个(键,值)对:
Option Explicit
Dim installer, database, view, myproperty, stdout, key
Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase (WScript.Arguments.Item(0), 1)
' Update Property'
'Set view = database.OpenView ("UPDATE Property SET Value = '" & myproperty & "' WHERE Property = 'MYPROPERTY'")'
myproperty = WScript.Arguments.Item(2)
key = WScript.Arguments.Item(1)
' Add/Insert Property'
Set view = database.OpenView ("INSERT INTO Property (Property, Value) VALUES ('" & key & "', '" & myproperty & "')")
view.Execute
database.Commit
Set database = Nothing
Set installer = Nothing
Set view = Nothing
我会在我的 python 代码中使用 os.system(cscript {VBScript} {path} {Key} {Value})
调用它,但是我希望我的 python 代码尽可能减少外部依赖。我四处寻找一些答案,我查看了 comtypes
文档以查看我是否可以显式释放或“解耦”我的 COM 对象。我尝试使用 installerCOM.Quit()
和 installerCOM.Exit()
,它们似乎不是 WindowsInstaller.Installer
对象的选项。
最后,我在 Whosebug 上阅读了几个以前的非 python(主要是 C#)答案,指出将 COM 对象变量设置为 null
可以解决这个问题,这在 VBScript 中也很清楚但这似乎不适用于 python 和 None
也许:
import gc
def setInstallerAttribute(installer_path, attribute_key, attribute_value):
installerCOM = comtypes.client.CreateObject("WindowsInstaller.Installer")
installerDatabase = installerCOM.OpenDatabase (installer_path, 1)
view = installerDatabase.OpenView ("INSERT INTO Property (Property, Value) VALUES ('{0}', '{1}')".format(attribute_key, attribute_value))
view.Execute
installerDatabase.Commit
del view
del installerDatabase
del installerCOM
gc.collect()
我在 python 中使用 comtypes.client
模块编写了一个函数,该函数应该从 .msi 文件打开数据库并写入一个特殊的(键,值)对。到目前为止我的问题是一旦调用函数没有问题,我尝试使用 os.rename()
重命名 .msi 文件然后得到权限错误:
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process
我的理解是我的 COM 对象仍在使用中,因此我无法访问该文件,函数和函数调用看起来像(显然这非常简化,但看起来应该这样工作):
import comtypes.client
import os, shutil
def setInstallerAttribute(installer_path, attribute_key, attribute_value):
installerCOM = comtypes.client.CreateObject("WindowsInstaller.Installer")
installerDatabase = installerCOM.OpenDatabase (installer_path, 1)
view = installerDatabase.OpenView ("INSERT INTO Property (Property, Value) VALUES ('{0}', '{1}')".format(attribute_key, attribute_value))
view.Execute
installerDatabase.Commit
view = None
installerDatabase = None
installerCOM = None
if __name__ == "__main__":
input = '{}'.format(msi_fullapth)
key = "Build"
value = "test_value"
if os.path.exists(input):
setInstallerAttribute(input, key, value)
os.rename(input, {some other path})
写这个函数是因为我之前使用VBScript来设置这个(键,值)对:
Option Explicit
Dim installer, database, view, myproperty, stdout, key
Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase (WScript.Arguments.Item(0), 1)
' Update Property'
'Set view = database.OpenView ("UPDATE Property SET Value = '" & myproperty & "' WHERE Property = 'MYPROPERTY'")'
myproperty = WScript.Arguments.Item(2)
key = WScript.Arguments.Item(1)
' Add/Insert Property'
Set view = database.OpenView ("INSERT INTO Property (Property, Value) VALUES ('" & key & "', '" & myproperty & "')")
view.Execute
database.Commit
Set database = Nothing
Set installer = Nothing
Set view = Nothing
我会在我的 python 代码中使用 os.system(cscript {VBScript} {path} {Key} {Value})
调用它,但是我希望我的 python 代码尽可能减少外部依赖。我四处寻找一些答案,我查看了 comtypes
文档以查看我是否可以显式释放或“解耦”我的 COM 对象。我尝试使用 installerCOM.Quit()
和 installerCOM.Exit()
,它们似乎不是 WindowsInstaller.Installer
对象的选项。
最后,我在 Whosebug 上阅读了几个以前的非 python(主要是 C#)答案,指出将 COM 对象变量设置为 null
可以解决这个问题,这在 VBScript 中也很清楚但这似乎不适用于 python 和 None
也许:
import gc
def setInstallerAttribute(installer_path, attribute_key, attribute_value):
installerCOM = comtypes.client.CreateObject("WindowsInstaller.Installer")
installerDatabase = installerCOM.OpenDatabase (installer_path, 1)
view = installerDatabase.OpenView ("INSERT INTO Property (Property, Value) VALUES ('{0}', '{1}')".format(attribute_key, attribute_value))
view.Execute
installerDatabase.Commit
del view
del installerDatabase
del installerCOM
gc.collect()