You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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);

关键说明

  1. 循环遍历逻辑:用while循环持续调用MsiViewFetch,当返回值不为ERROR_SUCCESS(即0)时退出循环——其中最常见的退出原因是ERROR_NO_MORE_ITEMS(错误码259),表示已经遍历完所有记录。
  2. 资源释放:每次处理完一条记录后,必须调用MsiCloseHandle关闭记录句柄,否则会造成内存泄漏。
  3. 错误检查:添加了关键步骤的错误检查,避免在数据库/视图打开失败的情况下继续执行后续操作,让代码更健壮。
  4. 修改模式:MsiViewModify的参数4对应MSIVIEWMODIFY_UPDATE,用于更新当前获取到的记录,这个参数是正确的。

这样修改后,代码就会遍历FeatureComponents表的所有条目,把每条记录的Feature_列值都改成DUMMY了。

内容的提问来源于stack exchange,提问作者Monstryyy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:40:45