We're making a custom boostrapper / external UI for our installation.
We want to provide a "Custom Installation" dialog (like in MSI) to allow the user to choose feature(s) they want to install or remove.
Currently, we are able to read the features (and other feature details like description) from the MSI database itself (by running an SQL query on the Feature
table).
However, we also want to display the cost of installing a feature. Windows Installer "Custom Installation" dialog is capable of doing this.
I think we can mimic the behavior by doing the following:
Feature
that you want to get the costFeatureComponents
table, get the Component
associated with the feature from 1File
table, add the FileSize
of the files associated with the component identified in 2Question:
FeatureInfo.GetCost
method in DTF but you can't use that directly. The product must be installed first before you can call FeatureInfo.GetCost
from ProductInstallation
)Thanks! :)
UPDATE # 1
I think there's a way to get the cost of a feature installation through the API even PRIOR to starting installation. Here's how I did it:
Installer.SetInternalUI(InstallUIOptions.Silent);
Session s = Installer.OpenPackage(@"C:\a.msi", false);
foreach (FeatureInfo info in s.Features)
{
MessageBox.Show(info.Name);
MessageBox.Show(info.GetCost(false, false, InstallState.Unknown).ToString());
}
s.Close();
calling info.name
successfully returns the name of the feature. However, calling info.GetCost
will return an InvalidHandlerException
with a message: "selection manager not initialized".
Here's where I'm currently at.
Update #2:
I was getting the InvalidHandlerException
because I am not invoking the needed file costing routines before I call info.GetCost
. Here's my modified code:
Installer.SetInternalUI(InstallUIOptions.Silent);
Session s = Installer.OpenPackage(@"C:\1.msi", false);
s["ROOTDRIVE"] = @"C:\";
s.DoAction("CostInitialize");
s.DoAction("FileCost");
s.DoAction("CostFinalize");
foreach (FeatureInfo info in s.Features)
{
long cost = info.GetCost(false, false, InstallState.Local);
MessageBox.Show(info.Title + " " + cost);
}
s.Close();
I am no longer getting the InvalidHandlerException but all file cost being returned is -1099511627776.
Yes, there is an API. You need to get an MSI Session by calling OpenPackage. By doing so, you will have access to the Feature list which will give you access to the GetCost method.
1 Gotcha: You need to perform 4 standard actions before calculating the cost: CostInitialize, FileCost, CostFinalize and InstallValidate.
Installer.SetInternalUI(InstallUIOptions.Silent);
Session s = Installer.OpenPackage(@"C:\1.msi", false);
s.DoAction("CostInitialize");
s.DoAction("FileCost");
s.DoAction("CostFinalize");
s.DoAction("InstallValidate");
foreach (FeatureInfo info in s.Features)
{
long cost = info.GetCost(false, false, InstallState.Local);
MessageBox.Show(info.Title + " " + cost);
}
s.Close();