Features
{
get
{
StringBuilder buf = new StringBuilder(256);
for (uint i = 0; ; i++)
{
uint ret = NativeMethods.MsiEnumFeatures(this.ProductCode, i, buf, null);
if (ret != 0)
{
break;
}
yield return new FeatureInstallation(buf.ToString(), this.ProductCode);
}
}
}
///
/// Gets the ProductCode (GUID) of the product.
///
public string ProductCode
{
get { return this.InstallationCode; }
}
///
/// Gets a value indicating whether this product is installed on the current system.
///
public override bool IsInstalled
{
get
{
return (this.State == InstallState.Default);
}
}
///
/// Gets a value indicating whether this product is advertised on the current system.
///
public bool IsAdvertised
{
get
{
return (this.State == InstallState.Advertised);
}
}
///
/// Checks whether the product is installed with elevated privileges. An application is called
/// a "managed application" if elevated (system) privileges are used to install the application.
///
/// True if the product is elevated; false otherwise
///
/// Note that this property does not take into account policies such as AlwaysInstallElevated,
/// but verifies that the local system owns the product's registry data.
///
public bool IsElevated
{
get
{
bool isElevated;
uint ret = NativeMethods.MsiIsProductElevated(this.ProductCode, out isElevated);
if (ret != 0)
{
throw InstallerException.ExceptionFromReturnCode(ret);
}
return isElevated;
}
}
///
/// Gets the source list of this product installation.
///
public override SourceList SourceList
{
get
{
return this.properties == null ? base.SourceList : null;
}
}
internal InstallState State
{
get
{
if (this.properties != null)
{
return InstallState.Unknown;
}
else
{
int installState = NativeMethods.MsiQueryProductState(this.ProductCode);
return (InstallState) installState;
}
}
}
internal override int InstallationType
{
get
{
const int MSICODE_PRODUCT = 0x00000000;
return MSICODE_PRODUCT;
}
}
///
/// The support link.
///
public string HelpLink
{
get
{
return this["HelpLink"];
}
}
///
/// The support telephone.
///
public string HelpTelephone
{
get
{
return this["HelpTelephone"];
}
}
///
/// Date and time the product was installed.
///
public DateTime InstallDate
{
get
{
try
{
return DateTime.ParseExact(
this["InstallDate"], "yyyyMMdd", CultureInfo.InvariantCulture);
}
catch (FormatException)
{
return DateTime.MinValue;
}
}
}
///
/// The installed product name.
///
public string ProductName
{
get
{
return this["InstalledProductName"];
}
}
///
/// The installation location.
///
public string InstallLocation
{
get
{
return this["InstallLocation"];
}
}
///
/// The installation source.
///
public string InstallSource
{
get
{
return this["InstallSource"];
}
}
///
/// The local cached package.
///
public string LocalPackage
{
get
{
return this["LocalPackage"];
}
}
///
/// The publisher.
///
public string Publisher
{
get
{
return this["Publisher"];
}
}
///
/// URL about information.
///
public Uri UrlInfoAbout
{
get
{
string value = this["URLInfoAbout"];
if (!String.IsNullOrEmpty(value))
{
try
{
return new Uri(value);
}
catch (UriFormatException) { }
}
return null;
}
}
///
/// The URL update information.
///
public Uri UrlUpdateInfo
{
get
{
string value = this["URLUpdateInfo"];
if (!String.IsNullOrEmpty(value))
{
try
{
return new Uri(value);
}
catch (UriFormatException) { }
}
return null;
}
}
///
/// The product version.
///
public Version ProductVersion
{
get
{
string ver = this["VersionString"];
return ProductInstallation.ParseVersion(ver);
}
}
///
/// The product identifier.
///
///
/// For more information, see
/// ProductID
///
public string ProductId
{
get
{
return this["ProductID"];
}
}
///
/// The company that is registered to use the product.
///
public string RegCompany
{
get
{
return this["RegCompany"];
}
}
///
/// The owner who is registered to use the product.
///
public string RegOwner
{
get
{
return this["RegOwner"];
}
}
///
/// Transforms.
///
public string AdvertisedTransforms
{
get
{
return this["Transforms"];
}
}
///
/// Product language.
///
public string AdvertisedLanguage
{
get
{
return this["Language"];
}
}
///
/// Human readable product name.
///
public string AdvertisedProductName
{
get
{
return this["ProductName"];
}
}
///
/// True if the product is advertised per-machine;
/// false if it is per-user or not advertised.
///
public bool AdvertisedPerMachine
{
get
{
return this["AssignmentType"] == "1";
}
}
///
/// Identifier of the package that a product is installed from.
///
public string AdvertisedPackageCode
{
get
{
return this["PackageCode"];
}
}
///
/// Version of the advertised product.
///
public Version AdvertisedVersion
{
get
{
string ver = this["Version"];
return ProductInstallation.ParseVersion(ver);
}
}
///
/// Primary icon for the package.
///
public string AdvertisedProductIcon
{
get
{
return this["ProductIcon"];
}
}
///
/// Name of the installation package for the advertised product.
///
public string AdvertisedPackageName
{
get
{
return this["PackageName"];
}
}
///
/// True if the advertised product can be serviced by
/// non-administrators without elevation.
///
public bool PrivilegedPatchingAuthorized
{
get
{
return this["AuthorizedLUAApp"] == "1";
}
}
///
/// Gets information about an installation of a product.
///
/// Name of the property being retrieved.
/// An unknown product or property was requested
/// The installer configuration data is corrupt
///
/// Win32 MSI APIs:
/// MsiGetProductInfo,
/// MsiGetProductInfoEx
///
public override string this[string propertyName]
{
get
{
if (this.properties != null)
{
string value = null;
this.properties.TryGetValue(propertyName, out value);
return value;
}
else
{
StringBuilder buf = new StringBuilder(40);
uint bufSize = (uint) buf.Capacity;
uint ret;
if (this.Context == UserContexts.UserManaged ||
this.Context == UserContexts.UserUnmanaged ||
this.Context == UserContexts.Machine)
{
ret = NativeMethods.MsiGetProductInfoEx(
this.ProductCode,
this.UserSid,
this.Context,
propertyName,
buf,
ref bufSize);
if (ret == (uint) NativeMethods.Error.MORE_DATA)
{
buf.Capacity = (int) ++bufSize;
ret = NativeMethods.MsiGetProductInfoEx(
this.ProductCode,
this.UserSid,
this.Context,
propertyName,
buf,
ref bufSize);
}
}
else
{
ret = NativeMethods.MsiGetProductInfo(
this.ProductCode,
propertyName,
buf,
ref bufSize);
if (ret == (uint) NativeMethods.Error.MORE_DATA)
{
buf.Capacity = (int) ++bufSize;
ret = NativeMethods.MsiGetProductInfo(
this.ProductCode,
propertyName,
buf,
ref bufSize);
}
}
if (ret != 0)
{
return null;
}
return buf.ToString();
}
}
}
///
/// Gets the installed state for a product feature.
///
/// The feature being queried; identifier from the
/// Feature table
/// Installation state of the feature for the product instance: either
/// , ,
/// or .
///
/// Win32 MSI APIs:
/// MsiQueryFeatureState,
/// MsiQueryFeatureStateEx
///
public InstallState GetFeatureState(string feature)
{
if (this.properties != null)
{
return InstallState.Unknown;
}
else
{
int installState;
uint ret = NativeMethods.MsiQueryFeatureStateEx(
this.ProductCode,
this.UserSid,
this.Context,
feature,
out installState);
if (ret != 0)
{
throw InstallerException.ExceptionFromReturnCode(ret);
}
return (InstallState) installState;
}
}
///
/// Gets the installed state for a product component.
///
/// The component being queried; GUID of the component
/// as found in the ComponentId column of the Component table.
/// Installation state of the component for the product instance: either
/// or .
///
/// Win32 MSI API:
/// MsiQueryComponentState
///
public InstallState GetComponentState(string component)
{
if (this.properties != null)
{
return InstallState.Unknown;
}
else
{
int installState;
uint ret = NativeMethods.MsiQueryComponentState(
this.ProductCode,
this.UserSid,
this.Context,
component,
out installState);
if (ret != 0)
{
throw InstallerException.ExceptionFromReturnCode(ret);
}
return (InstallState) installState;
}
}
///
/// Obtains and stores the user information and product ID from an installation wizard.
///
///
/// This method is typically called by an application during the first run of the application. The application
/// first gets the or .
/// If those properties are missing, the application calls CollectUserInfo.
/// CollectUserInfo opens the product's installation package and invokes a wizard sequence that collects
/// user information. Upon completion of the sequence, user information is registered. Since this API requires
/// an authored user interface, the user interface level should be set to full by calling
/// as .
///
/// The CollectUserInfo method invokes a FirstRun dialog from the product installation database.
///
/// Win32 MSI API:
/// MsiCollectUserInfo
///
public void CollectUserInfo()
{
if (this.properties == null)
{
uint ret = NativeMethods.MsiCollectUserInfo(this.InstallationCode);
if (ret != 0)
{
throw InstallerException.ExceptionFromReturnCode(ret);
}
}
}
///
/// Some products might write some invalid/nonstandard version strings to the registry.
/// This method tries to get the best data it can.
///
/// Version string retrieved from the registry.
/// Version object, or null if the version string is completely invalid.
private static Version ParseVersion(string ver)
{
if (ver != null)
{
int dotCount = 0;
for (int i = 0; i < ver.Length; i++)
{
char c = ver[i];
if (c == '.') dotCount++;
else if (!Char.IsDigit(c))
{
ver = ver.Substring(0, i);
break;
}
}
if (ver.Length > 0)
{
if (dotCount == 0)
{
ver = ver + ".0";
}
else if (dotCount > 3)
{
string[] verSplit = ver.Split('.');
ver = String.Join(".", verSplit, 0, 4);
}
try
{
return new Version(ver);
}
catch (ArgumentException)
{
}
}
}
return null;
}
}
}