cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
BizerbaDev
Level 6

Find out which features are installed (Basic msi) from outside a setup?

Hi!

I'm having a Basic msi setup that is often executed by a separate software in order to allow our users to install different products sequentially. We call that software out install wizard as it makes the installations for our users easier. Now we have come to a point that it is necessary that our install wizard needs to know which features of an existing installation are installed/selected.

I've searched my registry with Product and UpdateCodes for my installed setup but never saw any hint on which featrures are actually installed. When doing a web search I only found threads on how to detect the installed state of a feature from wihtin a setup. Could anyone please point me in the right direction?

I'm quite sure there is a way to find out which features were installed for a setup, but where is that information kept and how can I access it from a regular application?

Regards

Ralf
Labels (1)
0 Kudos
(5) Replies
MichaelU
Level 12 Flexeran
Level 12 Flexeran

There are several Windows Installer APIs designed for querying the state of a machine; in particular you might be able to use MsiQueryFeatureState. However a lot of the functions are not supported from within custom actions, so there are limitations in what you can safely perform during an installation. Those limitations shouldn't apply from your application.
0 Kudos
BizerbaDev
Level 6

Hi MichaelU,

I think you misunderstood me: I want to check the installed features of a installed MSI setup from outside the setup/installer (in my case it would be a .Net application that would need to know what features are installed)

Regards

Ralf
0 Kudos
MichaelU
Level 12 Flexeran
Level 12 Flexeran

I did miss that on my first read through, but when I noticed it I added the last bit about the limitations not applying to your application.

It is a little more work to call these things from .NET unless you choose to use the COM layer, but I'm unfamiliar with where the COM layer exposes the same information that's available with MsiQueryFeatureState. You can use resources like pinvoke.net to help invoke C++ APIs correctly. MsiQueryFeatureState will still be the core function you need to call.
0 Kudos
MarkusLatz
Level 8

I recommend the book "VB/VBA Developer's Guide to the Windows Installer" from Mike Gunderloy.

May be it is sufficient for you to download the source code from ftp://ftp.sybex.com/2745/

Chapter 8 is with a sample about MsiQueryFeatureState.

regards

Markus
0 Kudos
BizerbaDev
Level 6

Hi MichaelU,

you pointed me to the right direction! Thank you!

After a little research I ended up on the website pinvoke.com, which describes how .Net applications can access native dlls such as the msi.dll which holds the said MSIQueryFeatureState. While the access to native dlls from .Net itself is not a big deal I'm happy with the fact that this site provides a lot of example code. Equipped with the knowledge of this website I was quickly able to create a small C# test application that does exactly what I was looking for.

For the highly unrealistic case that someone else ever runs into the same or a similar problem I post the relevant code of the said test application here:

[CODE]
namespace MSITestApplication
{
public partial class MainWindow : Window
{
public enum INSTALLSTATE
{
INSTALLSTATE_NOTUSED = -7, // component disabled
INSTALLSTATE_BADCONFIG = -6, // configuration data corrupt
INSTALLSTATE_INCOMPLETE = -5, // installation suspended or in progress
INSTALLSTATE_SOURCEABSENT = -4, // run from source, source is unavailable
INSTALLSTATE_MOREDATA = -3, // return buffer overflow
INSTALLSTATE_INVALIDARG = -2, // invalid function argument
INSTALLSTATE_UNKNOWN = -1, // unrecognized product or feature
INSTALLSTATE_BROKEN = 0, // broken
INSTALLSTATE_ADVERTISED = 1, // advertised feature
INSTALLSTATE_REMOVED = 1, // component being removed (action state, not settable)
INSTALLSTATE_ABSENT = 2, // uninstalled (or action state absent but clients remain)
INSTALLSTATE_LOCAL = 3, // installed on local drive
INSTALLSTATE_SOURCE = 4, // run from source, CD or net
INSTALLSTATE_DEFAULT = 5, // use default, local or source
}

[DllImport("msi.dll", CharSet = CharSet.Unicode)]
static extern Int32 MsiGetProductInfo(string product, string property, [Out] StringBuilder valueBuf, ref Int32 len);

[DllImport("msi.dll", CharSet = CharSet.Unicode)]
static extern INSTALLSTATE MsiQueryFeatureState(string product, string feature);

public MainWindow()
{
InitializeComponent();
}

private void Button_Click(object sender, RoutedEventArgs e)
{
//Int32 len = 512;
//System.Text.StringBuilder builder = new System.Text.StringBuilder(len);
//MsiGetProductInfo("{6F113CFE-83BC-4311-AE7E-098B182C89C4}", "InstallSource", builder, ref len);
//MessageBox.Show(builder.ToString());

INSTALLSTATE res = MsiQueryFeatureState("{6F113CFE-83BC-4311-AE7E-098B182C89C4}", "CommonFiles");
MessageBox.Show(res.ToString());
}
}
}
[/CODE]

Cheers!

Ralf
0 Kudos