【发布时间】:2015-03-10 09:04:56
【问题描述】:
我完全不明白。
当我尝试以非只读模式打开 MSI 文件时,出现异常:
System.Runtime.InteropServices.COMException 未被用户代码处理 HelpLink=Msi.chm#9006 HResult=-2147467259 Message=OpenDatabase,DatabasePath,OpenMode Source=Msi API 错误 错误代码=-2147467259 堆栈跟踪:在 System.RuntimeType.ForwardCallToInvokeMember(字符串成员名称, BindingFlags 标志、对象目标、Int32[] aWrapperTypes、MessageData& msgData) 在 WindowsInstaller.Installer.OpenDatabase(String DatabasePath, Object OpenMode) 在基于 Web 的版本中 manager.AjaxFileHandler.updateMSIProperty(字符串 msiFile,字符串 msiProperty,字符串值)在 C:\Users\obfuscated\documents\visual studio 2010\Projects\基于网络的发布 manager\AjaxFileHandler.ashx.cs:line 28 at web based release manager.AjaxFileHandler.ProcessRequest(HttpContext context) 在 C:\Users\obfuscated\documents\visual studio 2010\Projects\web based 发布管理器\AjaxFileHandler.ashx.cs:第 143 行 System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 在 System.Web.HttpApplication.ExecuteStep(IExecutionStep 步骤, Boolean & completedSynchronously)
我可以使用下面的工作代码从 msi 读取属性,所以我知道文件路径是正确的:
public static string GetMSIProperty(string msiFile, string msiProperty)
{
string retVal = string.Empty;
Type classType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Object installerObj = Activator.CreateInstance(classType);
WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer;
Database database = installer.OpenDatabase(msiFile, 0);
string sql = String.Format("SELECT `Value` FROM `Property` WHERE `Property`='{0}'", msiProperty);
View view = database.OpenView(sql);
WindowsInstaller.Record record = null;
view.Execute(record);
record = view.Fetch();
if (record != null)
{
retVal = record.get_StringData(1).ToString();
}
else
retVal = "Property Not Found";
Marshal.FinalReleaseComObject(installer);
return retVal;
}
导致问题的代码:
public void updateMSIProperty(string msiFile, string msiProperty, string value)
{
Type classType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Object installerObj = Activator.CreateInstance(classType);
WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer;
var mode = MsiOpenDatabaseMode.msiOpenDatabaseModeDirect;
Database database = installer.OpenDatabase(msiFile, mode); //throws the exception!
string sql = String.Format("UPDATE `Property` SET `Value`='{0}' WHERE `Property`='{1}'", value, msiProperty);
View view = database.OpenView(sql);
view.Execute();
return;
}
这两个函数是从同一段代码运行的:
if(GetMSIProperty(path, "UpgradeCode") != theProductsUpgradeCode)
updateMSIProperty(path, "UpgradeCode",theProductsUpgradeCode);
我工作的公司正在迁移到以 msi 的形式发布软件。 没问题,除了公司由很多擅长他们所做的工程师组成,其中一部分是用于计算的编程工具。 他们不是计算机科学家,他们中的大多数人都不知道 OS2 和 Office 365 之间的区别...
到目前为止,大多数部门已经创建了一些发布系统,可以创建一个 msi,并安装产品,但是他们还没有真正掌握所有这些产品/包属性的作用。
我想我会帮助他们,在他们发布 msi 的我们的网络前端,通过替换 UpgradeCodes (guid) 并插入他们通常忘记的一些其他数据,例如制造商..证书等。
但我无法获取更新 MSI 的代码。
更新:
- 对产品名称进行更多混淆,以保护工作。
- 已尝试添加
Marshal.FinalReleaseComObject(installer),但没有成功
【问题讨论】:
-
OpenDatabase: "如果方法失败,可以通过LastErrorRecord方法获取扩展错误信息。" -
好吧,我已经尝试过了,但是得到... 找不到成员。 (HRESULT 的异常:0x80020003 (DISP_E_MEMBERNOTFOUND))也在任何人想知道之前.. 是的,我有权写入文件..
标签: c# windows-installer