wixsharp icon indicating copy to clipboard operation
wixsharp copied to clipboard

How to set or use Launchcondition Action in Wix#

Open Torchok19081986 opened this issue 1 year ago • 9 comments

morning, i struggle on create msi, where i can perform launchcondition action after appsearch. Following scenario : before Plugin starts installation, it should check if mainprogramm installed and if so, check also .exe fileversion if this not versions, comes from me , are not equals cancel installation. i done some research


public class Program
{
    static void Main()
    {
        var project = new ManagedProject("MyProduct",
                         new Dir(@"%ProgramFiles%\My Company\My Product",
                             new File("Program.cs")));

        project.GUID = new Guid("9d84f407-58c5-485d-985d-451b21f51598");

        //custom set of standard UI dialogs
        project.ManagedUI = new ManagedUI();

        project.ManagedUI.InstallDialogs.Add<WelcomeDialog>()
                                        .Add<LicenceDialog>()
                                        .Add<SetupTypeDialog>()
                                        .Add<FeaturesDialog>()
                                        .Add<InstallDirDialog>()
                                        .Add<ProgressDialog>()
                                        .Add<ExitDialog>();

        project.ManagedUI.ModifyDialogs.Add<MaintenanceTypeDialog>()
                                       .Add<FeaturesDialog>()
                                       .Add<ProgressDialog>()
                                       .Add<ExitDialog>();

        //project.SourceBaseDir = "<input dir path>";
        //project.OutDir = "<output dir path>";
        var launchCondition = new LaunchCondition();
        launchCondition.Value = "Vesion of Installed App";
        launchCondition.Message = "Application not installed or Condition are not fulfilled.";
      
        project.LaunchConditions.Add(launchCondition); <-- ??? posiblity to Add CustomAction 

        project.BuildMsi();
    }
}

public static class CusotmActions
{
    [CustomAction]
    public static ActionResult SetLaunchCondition(Session session)
    {
        return ActionResult.Success;
    }

    [CustomAction]
    public static ActionResult RegSearch(Session session)
    {
        var appKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\application").GetValue("ProgramDir").ToString();
    
        if (string.IsNullOrEmpty(appKey))
        {
            return ActionResult.Failure;
        }
    
        session["INSTALLDIR"] = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\applicationRegs").GetValue("ProgramDir").ToString();
    
        session["APPVERSION"] = FileVersionInfo.GetVersionInfo(session["INSTALLDIR"] + "\\app.exe").FileVersion;
    
        Version version = Version.Parse(session["APPVERSION"]);
    
        if(version.Major != 1 && version.Minor != 2)
        {
            return ActionResult.Failure;
        }
    
        return ActionResult.Success;
    }
}

WixToolset v4 info : https://wixtoolset.org/docs/schema/wxs/launchconditions/

for any suggestions or code , thanks.

Torchok19081986 avatar Sep 18 '24 09:09 Torchok19081986

project.Load += ... event is scheduled before AppSearch, so you can do your checking and then either abort or allow further installation. You do not have to use LaunchConditions, that don't really allow you use anything beyond simle WiX runtime constants checking.

Load          -> When.Before, Step.AppSearch, Execute.Immediate

oleg-shilo avatar Sep 18 '24 12:09 oleg-shilo

thanks for quick answer, oleg. Any idea, how add cancel installation message if conditions are not fullfilled ? something like shell.customdesriptionerror = "Application is not installed or versions are equal fir plugin " ? This property is exists only in exitdialog.

Torchok19081986 avatar Sep 18 '24 12:09 Torchok19081986

found it on Load Event and just tested.


try
{
    var appKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\application").GetValue("ProgramDir").ToString();

    if (string.IsNullOrEmpty(appKey))
    {
        e.ManagedUI.Shell.CustomErrorDescription = "Programm not installed.";
        e.ManagedUI.Shell.ErrorDetected = true;
    }

    e.Session["INSTALLDIR"] = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\applicationRegs").GetValue("ProgramDir").ToString();

    e.Session["APPVERSION"] = FileVersionInfo.GetVersionInfo(e.Session["INSTALLDIR"] + "\\app.exe").FileVersion;

    Version version = Version.Parse(e.Session["APPVERSION"]);

    if (version.Major != 1 && version.Minor != 2)
    {
        e.ManagedUI.Shell.CustomErrorDescription = "Condition for Installation not fullfilled.";
        e.ManagedUI.Shell.ErrorDetected = true;
    }
}
catch(Exception ex) <--- This Exception executed.
{
    e.ManagedUI.Shell.CustomErrorDescription = "Exception " + ex.ToString();
    e.ManagedUI.Shell.ErrorDetected = true;
}

i also added extra DefaulDeferedProperty APPVERSION to

project.DefaultDeferredProperties = ",APPVERSION";

appears shomehow, only exeception , not Condition for Installation not fullfilled. Versions of exe are not 1.2, but 24.3.15.20511. Any Idea why?

also even i remove this code from Load Event - i see nullref exception and msi error 1602 in windows EventLog. Now i curious. 😵‍💫😵‍💫😵‍💫😵‍💫

Torchok19081986 avatar Sep 19 '24 06:09 Torchok19081986

i think i run in issue. Created new wix Sharp v3 - Custom UI Project. Wait for nuget restore and rebuild project , without changes. Msi is created, but if start it on testsystem appears See the end of this message for details on invoking just-in-time (JIT) debugging instead of this dialog box.

************** Exception Text ************** System.NullReferenceException: Object reference not set to an instance of an object. at WixSharp_Setup3.Dialogs.WelcomeDialog.ResetLayout() at WixSharp_Setup3.Dialogs.WelcomeDialog.WelcomeDialog_Load(Object sender, EventArgs e) at System.Windows.Forms.Form.OnLoad(EventArgs e) at System.Windows.Forms.Form.OnCreateControl() at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible) at System.Windows.Forms.Control.CreateControl() at System.Windows.Forms.Control.WmShowWindow(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ScrollableControl.WndProc(Message& m) at System.Windows.Forms.Form.WmShowWindow(Message& m) at System.Windows.Forms.Form.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

************** Loaded Assemblies ************** mscorlib Assembly Version: 4.0.0.0 Win32 Version: 4.8.4749.0 built by: NET48REL1LAST_B CodeBase: file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/mscorlib.dll

Microsoft.Deployment.WindowsInstaller Assembly Version: 3.0.0.0 Win32 Version: 3.14.0.6526 CodeBase: file:///C:/Users/administrator.TESTDOM/AppData/Local/Temp/2/MSI14977/Microsoft.Deployment.WindowsInstaller.DLL

WixSharp.UI Assembly Version: 1.25.2.0 Win32 Version: 1.25.2.0 CodeBase: file:///C:/Users/administrator.TESTDOM/AppData/Local/Temp/2/MSI14977/WixSharp.UI.DLL

WixSharp Assembly Version: 1.25.2.0 Win32 Version: 1.25.2.0 CodeBase: file:///C:/Users/administrator.TESTDOM/AppData/Local/Temp/2/MSI14977/WixSharp.DLL

System.Windows.Forms Assembly Version: 4.0.0.0 Win32 Version: 4.8.4739.0 built by: NET48REL1LAST_B CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms/v4.0_4.0.0.0__b77a5c561934e089/System.Windows.Forms.dll

System Assembly Version: 4.0.0.0 Win32 Version: 4.8.4749.0 built by: NET48REL1LAST_B CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System/v4.0_4.0.0.0__b77a5c561934e089/System.dll

System.Drawing Assembly Version: 4.0.0.0 Win32 Version: 4.8.4390.0 built by: NET48REL1LAST_C CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Drawing/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll

System.Core Assembly Version: 4.0.0.0 Win32 Version: 4.8.4749.0 built by: NET48REL1LAST_B CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Core/v4.0_4.0.0.0__b77a5c561934e089/System.Core.dll

WixSharp Setup3 Assembly Version: 1.9.19.2024 Win32 Version: 1.9.19.2024 CodeBase: file:///C:/Users/administrator.TESTDOM/AppData/Local/Temp/2/MSI14977/WixSharp%20Setup3.EXE

System.Xml.Linq Assembly Version: 4.0.0.0 Win32 Version: 4.8.3761.0 built by: NET48REL1 CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Xml.Linq/v4.0_4.0.0.0__b77a5c561934e089/System.Xml.Linq.dll

System.Xml Assembly Version: 4.0.0.0 Win32 Version: 4.8.3761.0 built by: NET48REL1 CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Xml/v4.0_4.0.0.0__b77a5c561934e089/System.Xml.dll

System.Configuration Assembly Version: 4.0.0.0 Win32 Version: 4.8.4190.0 built by: NET48REL1LAST_B CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Configuration/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll

************** JIT Debugging ************** To enable just-in-time (JIT) debugging, the .config file for this application or computer (machine.config) must have the jitDebugging value set in the system.windows.forms section. The application must also be compiled with debugging enabled.

For example:

When JIT debugging is enabled, any unhandled exception will be sent to the JIT debugger registered on the computer rather than be handled by this dialog box.

also tried on current system, work pc, same error. 😧😧😧😧

Torchok19081986 avatar Sep 19 '24 09:09 Torchok19081986

i checked my originall project for creation msi. i had added


public static class CustomActions
{
    [CustomAction]
    public static ActionResult SetWVToolDir(Session session)
    {
        try
        {
            //x64 - 64 Bit
            session["INSTALLDIR"] = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\app").GetValue("ModuleDir").ToString();

            string path = session["INSTALLDIR"];

            session["DIR2"] = path + @"\Extension\Addins";

            return ActionResult.Success;
        }
        catch (Exception)
        {
            return ActionResult.Failure;
        }
    }

    [CustomAction]
    public static ActionResult SetExtensionManualsDir(Session session)
    {
        session["INSTALLDIR"] = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\App").GetValue("ModuleDir").ToString();
        string path = session["INSTALLDIR"];
        session["DIR3"] = path + @"\Extension\Addins\Manuals";
        return ActionResult.Success;
    }
}

this code works for setting installdr property, but on Load Event apears nullreference Exception. Is Load Event broken or something wrong with it ?

I invistigate some research further, Looks like in Custom UI Template ResetLayout Method is broken. After i commented in each dialog this method out, now it works.

Any recent changes in Custom UI Template ?

Torchok19081986 avatar Sep 19 '24 11:09 Torchok19081986

add cancel installation message if conditions are not fullfilled ?

Off the top of my head, you just set result to the user-exit. you can also logg the details to the session log.

args.result = UserExit;
session.Log();

As for ResetLayout. Indeed, I think it was a fix in the latest release of the template. Ensure you are using the latest: image

oleg-shilo avatar Sep 19 '24 12:09 oleg-shilo

thanks, again. I just checked. VS 2022 doesnt show any Updates for WixSharp Template, i intalled latest template version on my work machine.

Screenshot 2024-09-19 144902

is this somehow related to changes in https://github.com/oleg-shilo/wixsharp/issues/1490 ?

Torchok19081986 avatar Sep 19 '24 12:09 Torchok19081986

Yes, it is related. Unfortunately, the original defect has crippled back to the template. Maintaining two editions WiX4 and WiX3 comes with the risks. In this case, I accidentally used the binaryId of WiX4 in the WiX3 template during the packaging.

Since it happened a second time I am converting this in the CI defect.

In the meantime please use this simple workaround that will be the essence of the future fix. In the all void *Dialog_Load(object sender, EventArgs e) methods use this routine for initializing the image:

image.Image = Runtime.Session.GetResourceBitmap("WixSharpUI_Bmp_Dialog") ??
              Runtime.Session.GetResourceBitmap("WixUI_Bmp_Dialog");

oleg-shilo avatar Sep 19 '24 23:09 oleg-shilo

morning, i tested recent, 30 min ago, workaround works. Many thanks.

Torchok19081986 avatar Sep 20 '24 07:09 Torchok19081986