开发者

Get feature installation cost prior to installation

开发者 https://www.devze.com 2023-02-06 15:18 出处:网络
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

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:

  1. Pick a Feature that you want to get the cost
  2. Using the FeatureComponents table, get the Component associated with the feature from 1
  3. Using the File table, add the FileSize of the files associated with the component identified in 2
  4. The sum from 3 is the cost of the feature installation

Question:

  1. Is there an API (either from DTF or MSI.DLL) that we can use to get the cost of a feature PRIOR to installation? (There is a 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)
  2. If there is no API, is the procedure given above appropriate or correct to calculate the cost of a feature installation?

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);
  }开发者_StackOverflow
  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();


This isn't the answer you are looking for but I would suggest pre-calculating the sizes of the features at build time and using a precalculated table during install. This is what we do in Burn in WiX v3.6. It is much faster and much more stable.

0

精彩评论

暂无评论...
验证码 换一张
取 消