Reputation: 344
I have a problem with calling get_PrimaryKeys()
function from msi.dll
in c#.
I want to fund out what are the primary keys in a given MSI table. I use the following code:
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
installer = (Installer)Activator.CreateInstance(installerType);
database = installer.OpenDatabase(MSIPath, MsiOpenDatabaseMode.msiOpenDatabaseModeTransact);
WindowsInstaller.Record data = null;
data = database.PrimaryKeys[tableName];
string s = data.get_StringData(1);
If I use database.get_PrimaryKeys(tableName)
, it gives the same error which is:
COMexception
Member not found. (Exception from HRESULT: 0x80020003 (DISP_E_MEMBERNOTFOUND))
When I use other functions form msi.dll they works fine.
What is the problem?
Upvotes: 2
Views: 689
Reputation: 2211
I checked the official MSI-sample code from Microsoft here https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/Win7Samples/sysmgmt/msi/scripts/WiTextIn.vbs
I also did a couple of tests with that VBS-samples and it turns out, that the table-name needs EXACTLY as listed in the MSI. E.g. 'file' will not work, but 'File'. It is case-sensitive!
Here a small PS-snippet that shows the sequence:
$installer = New-Object -ComObject WindowsInstaller.Installer
$msi = 'c:\windows\installer\MySampleFile.MSI'
$db = $installer.OpenDatabase($msi, 0)
$keys = $db.PrimaryKeys('Media')
$keys.StringData(1)
Returns "DiskId" as the PrimaryKey-columns for that table.
Upvotes: 0
Reputation: 32270
There's an easier way to query MSI database from C# code. The WiX Toolset includes a well-designed convenient .NET API called DTF (Deployment Tools Foundation), which makes is possible to write the following (C#):
using (var database = new Database("path\\to\\package.msi", DatabaseOpenMode.ReadOnly))
{
var table = database.Tables["someTableName"];
foreach (var column in table.PrimaryKeys)
{
Console.WriteLine("The table {0} defines {1} as primary key", table.Name, column);
}
}
All you have to do:
Microsoft.Deployment.WindowsInstaller.dll
in your C# projectusing Microsoft.Deployment.WindowsInstaller;
namespaceYou don't have to build your MSI with WiX in order to get advantage out of DTF. Reference DTF.chm (installed together with WiX) to know more about it.
Upvotes: 1