如何通过msi.dll批量修改MSI表FeatureComponents中Feature_列值?
如何遍历MSI数据库表并批量修改所有记录
你遇到的问题很典型——当前代码只执行了一次MsiViewFetch,所以只会处理FeatureComponents表的第一条记录。要批量修改所有条目,核心是用循环持续获取记录直到表尾,每次获取到记录后执行修改操作。
修改后的完整代码
IntPtr hDb = IntPtr.Zero; int res = MsiInvoke.MsiOpenDatabase(PathToMsi, MsiInvoke.MSIDBOPEN_TRANSACT, out hDb); if (res != 0) // 先检查数据库打开是否成功 { // 这里可以添加错误处理逻辑,比如打印错误码或提示 return; } string sql = "SELECT `Feature_` FROM `FeatureComponents`"; IntPtr hView2 = IntPtr.Zero; res = MsiInvoke.MsiDatabaseOpenView(hDb, sql, out hView2); if (res != 0) { // 错误处理:关闭已打开的数据库句柄 MsiInvoke.MsiCloseHandle(hDb); return; } res = MsiInvoke.MsiViewExecute(hView2, IntPtr.Zero); if (res != 0) { // 错误处理:关闭视图和数据库句柄 MsiInvoke.MsiCloseHandle(hView2); MsiInvoke.MsiCloseHandle(hDb); return; } IntPtr hRec2 = IntPtr.Zero; // 循环获取所有记录,直到没有更多条目 while ((res = MsiInvoke.MsiViewFetch(hView2, out hRec2)) == 0) { // 修改Feature_列的值为"DUMMY" res = MsiInvoke.MsiRecordSetString(hRec2, 1, "DUMMY"); if (res == 0) { // MSIVIEWMODIFY_UPDATE = 4,用于更新当前获取到的记录 res = MsiInvoke.MsiViewModify(hView2, 4, hRec2); } // 必须关闭记录句柄,避免内存泄漏 MsiInvoke.MsiCloseHandle(hRec2); hRec2 = IntPtr.Zero; } // 收尾:关闭视图、提交修改并释放所有句柄 MsiInvoke.MsiViewClose(hView2); MsiInvoke.MsiDatabaseCommit(hDb); MsiInvoke.MsiCloseHandle(hView2); MsiInvoke.MsiCloseHandle(hDb);
关键说明
- 循环遍历逻辑:用
while循环持续调用MsiViewFetch,当返回值不为ERROR_SUCCESS(即0)时退出循环——其中最常见的退出原因是ERROR_NO_MORE_ITEMS(错误码259),表示已经遍历完所有记录。 - 资源释放:每次处理完一条记录后,必须调用
MsiCloseHandle关闭记录句柄,否则会造成内存泄漏。 - 错误检查:添加了关键步骤的错误检查,避免在数据库/视图打开失败的情况下继续执行后续操作,让代码更健壮。
- 修改模式:
MsiViewModify的参数4对应MSIVIEWMODIFY_UPDATE,用于更新当前获取到的记录,这个参数是正确的。
这样修改后,代码就会遍历FeatureComponents表的所有条目,把每条记录的Feature_列值都改成DUMMY了。
内容的提问来源于stack exchange,提问作者Monstryyy
相关产品推荐
相关产品推荐

