Upgrading program

Aug 22, 2016 at 2:10 PM
I use ManagedProgect. How can I do in the UIInitialized event handler:
  1. Detect if my product is installed.
    I use AppSearch.IsProductInstalled(projectGUID), but it returns false if the program is installed.
    How to detect if my product is installed?
  2. If the product is installed, how to find out the version of product and installation folder?
  3. I want to save data from custom dialog in order to use it in the next installation. Where can I save the data?
Aug 23, 2016 at 3:15 AM
1 Detect if my product is installed
IsProductInstalled doesn't do much. It simply decorates and invokes system API IsProductInstalled. Thus if it doesn't return what you expect then most likely your projectGUID is not correct. You can have a look at GenericTest.AppSearchTest of WixSharp.Test projhect where IsProductInstalled is used to check if product "Windows Live Photo Common" is installed.
[DllImport("msi", CharSet = CharSet.Unicode)]
static extern Int32 MsiGetProductInfo(string product, string property, [Out] StringBuilder valueBuf, ref Int32 len);

static public bool IsProductInstalled(string productCode)
{
    var productNameLen = 512;
    var productName = new StringBuilder(productNameLen);
    if (0 == MsiGetProductInfo(productCode, "ProductName", productName, ref productNameLen))
        return !string.IsNullOrEmpty(productName.ToString());
    else
        return false;
}
2 Assming you fixed your problem with productCode you can invoke MsiGetProductInfo with "Version" and it will return you a string of the DWORD value for
version. You can slice it to extract the version components.

The latest code of WixSharp.AppSearch (use git if you need to see it) already has an API for this:
static public Version GetProductVersion(string productCode)
{
    var versionStr = GetProductInfo(productCode, "Version");

    //MMmmBBBB
    if (versionStr.IsNotEmpty())
    {
        int value;
        if (int.TryParse(versionStr, out value))
        {
            var major = (int)(value & 0xFF000000) >> 8 * 3;
            var minor = (int)(value & 0x00FF0000) >> 8 * 2;
            var build = (int)(value & 0x0000FFFF);
            return new Version(major, minor, build);
        }
    }

    return null;
}
3 Where can I save the data?
Anywhere you want. It's C# you can do anything you want. I guess some well-known locations (file system, registry...) can be an obvious choice.
Aug 23, 2016 at 1:50 PM
Edited Aug 23, 2016 at 2:49 PM
When I use in 32-bit program WixSharp.AppSearch.GetProducts and WixSharp.AppSearch.GetProductCode, these functions drops.
In 64-bit version they work right.

When I try to detect if my product is installed I try to use function IsProductInstalled(productCode). Where can I get productCode of my MSI?
I use project.GUID, but it isn't the same as returns AppSearch.GetProductCode(projectName). It differs from project.GUID in last 6 symbols.
Aug 24, 2016 at 2:55 AM
  • I just tested the GetProductCode and in my environment it works for both CPU types just fine:
class Program
{
    static public void Main(string[] args)
    {
        var installed = AppSearch.IsProductInstalled("{1D6432B4-E24D-405E-A4AB-D7E6D088CBC9}");
        Console.WriteLine(installed);
    }
}
As I explained GetProductCode uses native MsiGetProductInfo (from msi.dll) thus troubleshooting CPU type (or environment) implications of msi.dll interop is outside of Wix# scope. It is a generic .NET problem. You have the code (my prev post) so you can create your own interop that works in your conditions. You can even query registry directly if you need to.
 
  • project.GUID is not a product code. But Project.ProductId is. You can assign it explicitly. If you don't then Wix# will auto allocate it for you. It will be derived from project.GUID. After the build Wix# always prints out the all allocated ids:
 ProductName: MyProduct
 Version    : 1.0.0.0
 ProductId  : {6f330b47-2577-43ad-9095-1861ca25889c}
 UpgradeCode: {6f330b47-2577-43ad-9095-1861ba25889b}
You can also retrieve the auto-generated ProductId after the build:
project.BuildMsi();
Console.WriteLine(project.ProductId);
MSI product identity model is described in this Wix# wiki page: https://wixsharp.codeplex.com/wikipage?title=Deployment%20scenarios#_naming
Aug 24, 2016 at 10:43 AM
Thanks a lot.
Is it any way to find out project GUID (UpgradeCode) if I know ProductId.
I can install 2 programs with the same ProductName but different GUIDs. During the upgrading I want to detect program with the same UpgradeCode.
Aug 24, 2016 at 11:24 AM
> Is it any way to find out project GUID (UpgradeCode) if I know ProductId.
Yes there is. Have a look at Project properties. You will find that it has UpgradeCode.

Checking the upgrade code of the installed product most likely is possible (e.g. with MsiGetProductInfo). Though not sure what exactly is involved.

Normally you never ever need to know UpgradeCode. It only plays any role during an upgrade and it is an operation that a developer never implements directly but relies on MSI Minor/Mojor upgrade process. Something tells me that you may be investing into something that is already dome by MSI. Have a look at MajorUpgrade Wix# samples. The documentation (wiki) also describes the topic.