我尝试更新MSI中功能表中的现有条目。更具体地说,功能标识符本身(第一列 - 功能)。
String featureQuery = "SELECT * FROM `Feature`";
view = db.OpenView(featureQuery);
view.Execute();
rec = view.Fetch();
rec.SetString("Feature", "NewName"); <- error here "Function failed during execution"
view.Modify(ViewModifyMode.Update, rec);
然而,当我做同样但只改变&#34;功能&#34;列到&#34;标题&#34; (在发生错误的行中),例如,MSI中的标题列正在更改为&#34; NewName&#34;。
所以,我的问题是 - 这甚至是可能还是我在某个地方犯了错误?如果以后,请指出我在哪里,我将非常感激。无论如何,任何建议都非常感谢,谢谢!
答案 0 :(得分:1)
我的这个例子并不完全相同,因为它是我愚蠢的C#P / Invoke测试,但它确实有效并且更改了Feature.Feature值,因此API允许这样做,也许还有DTF的东西包装类具有需要更改的默认值等。明显的区别在于SetString / MsiRecordSetString代码,其中本机API需要字段编号。我为没有查看DTF而道歉,但SetString可能会将“Feature”字符串映射到实际的字段编号以更新记录的第一个字段。如果它有一个带有字段编号的重载,请尝试使用该字段。我将补充说,您实际上没有选择特定功能,因此您可能会修改“第一个”功能,因为select *将全部返回。
IntPtr hDb = IntPtr.Zero;
int res = MsiInvoke.MsiOpenDatabase("C:\\Phil\\MyDD\\Samples Setup\\InsertRTF\\setup.msi", MsiInvoke.MSIDBOPEN_TRANSACT, out hDb);
string qinsert = "SELECT * FROM `Feature`";
IntPtr hView =IntPtr.Zero;
res = MsiInvoke.MsiDatabaseOpenView(hDb, qinsert, out hView);
res = MsiInvoke.MsiViewExecute(hView, 0);
IntPtr hRec= IntPtr.Zero;
res = MsiInvoke.MsiViewFetch(hView, out hRec);
res = MsiInvoke.MsiRecordSetString(hRec, 1, "Whatever");
res = MsiInvoke.MsiViewModify(hView, 4, hRec); // 4 = msimodify_replace 3 = modify_assign
res = MsiInvoke.MsiViewClose(hView);
res = MsiInvoke.MsiDatabaseCommit(hDb);
MsiInvoke只是我创建的一个愚蠢的P / invoke类,从这开始:
public class MsiInvoke
{
//Oops MSIHandles are not IntPtrs.
[DllImport("msi", CharSet = CharSet.Auto)]
public static extern int MsiOpenDatabase(string filename, int persist, out IntPtr dbhandle);
public const int MSIDBOPEN_DIRECT = 2;
public const int MSIDBOPEN_TRANSACT = 1;