Wix# CustomAction bug if Sequence is NotInSequence

Mar 1, 2016 at 10:21 AM
Merge 2 Samples:
-ProductInfo
-CustomMSIDialog

bug in Compiler.cs:2353 ProcessCustomActions
first action is NotInSequence.
lastActionName must be null.
Coordinator
Mar 2, 2016 at 5:40 AM
CustomMSIDialog sample belongs to the 'Native MSI UI' support, which was a research-only effort. After WiX team released by far superior support for EmbeddedUI model the "Native MSI UI" functionality has been deprecated and moved into WixSharp.Lab.dll assembly. Thus it may or may not work with the rest of the system. Meaning that it's unlikely for the module that has been effectively discontinued to get fixed. Unless of course the problem exist for other use-cases (samples).

You have two options now.
  • You can migrate your UI on EmbeddedUI. It is actually quite simple and intuitive and you will not be limited in your UI development as you do with Native MSI UI. The samples are available.
  • You may analyse the produced wxs file, identify the offending XML element(s) and use project on-XML generated event to fix the problem. If you go this way and share your solution I may have a look at it and possibly integrate it with the project validation routine so it can be fixed automatically as part of the MSI build procedure.
Mar 2, 2016 at 8:22 AM
Я всего лишь хотел сказать, что я нашел багу в создании WIX файла:
если выставить
    project.ControlPanelInfo.InstallLocation = "[INSTALLDIR]";
    project.ControlPanelInfo.NoModify = true;
то создаются 2 Action, и 2 записи в <InstallExecuteSequence><Custom Action="Set_ARPINSTALLLOCATION" after="InstallInitialize">
если в добавок к этому создать свой Action
    new ManagedAction("ValidateLicenceKey") { Id = "ValidateLicenceKey", Sequence = Sequence.NotInSequence },
то оно испортит первую запись <InstallExecuteSequence><Custom Action="Set_ARPINSTALLLOCATION" after="ValidateLicenceKey">
Но по логике ValidateLicenceKey нигде не должен упоминать в InstallExecuteSequence.
Чтобы исправить данный баг я предлагаю заменить 1 строчку в Compiler.cs:2353 ProcessCustomActions
               string step = wAction.Step.ToString();

                if (wAction.When == When.After && wAction.Step == Step.PreviousAction)
                {
                    if (lastActionName == null)
                        throw new Exception("Step.PreviousAction is specified for the very first 'Custom Action'.\nThere cannot be any previous action as it is the very first one in the sequence.");
                    step = lastActionName;
                }
                else if (wAction.When == When.After && wAction.Step == Step.PreviousActionOrInstallFinalize)
                    step = lastActionName ?? Step.InstallFinalize.ToString();
                else if (wAction.When == When.After && wAction.Step == Step.PreviousActionOrInstallInitialize)
                    step = lastActionName ?? Step.InstallInitialize.ToString();

                lastActionName = wAction.Id;

                List<XElement> sequences = new List<XElement>();

                if (wAction.Sequence != Sequence.NotInSequence)
                {
                    foreach (var item in wAction.Sequence.GetValues())
                        sequences.Add(product.SelectOrCreate(item));
                }
на
               string step = wAction.Step.ToString();

                if (wAction.When == When.After && wAction.Step == Step.PreviousAction)
                {
                    if (lastActionName == null)
                        throw new Exception("Step.PreviousAction is specified for the very first 'Custom Action'.\nThere cannot be any previous action as it is the very first one in the sequence.");
                    step = lastActionName;
                }
                else if (wAction.When == When.After && wAction.Step == Step.PreviousActionOrInstallFinalize)
                    step = lastActionName ?? Step.InstallFinalize.ToString();
                else if (wAction.When == When.After && wAction.Step == Step.PreviousActionOrInstallInitialize)
                    step = lastActionName ?? Step.InstallInitialize.ToString();

                if(wAction.Sequence != Sequence.NotInSequence)
                    lastActionName = wAction.Id;

                List<XElement> sequences = new List<XElement>();

                if (wAction.Sequence != Sequence.NotInSequence)
                {
                    foreach (var item in wAction.Sequence.GetValues())
                        sequences.Add(product.SelectOrCreate(item));
                }
Coordinator
Mar 2, 2016 at 10:10 AM
OK. I see. Lucky me I understand Russian :)

I thought the behavior is specific to CustomMSIDialog use-case. Thank you for suggestion I will see if it doesn't break any other scenarios, Will let you know the outcome.

Cheers
Mar 2, 2016 at 10:51 AM
I previously read your biography on http://www.codeproject.com/ :)
Coordinator
Mar 2, 2016 at 11:43 AM
Your fix indeed address the issue and exhibits no side effects whatsoever. Yes it very simple. :)

I have created an issue on your behalf. The fix will be available in the next release.

Though I would like to ask you a question. What is the objective for your non-sequenced CA?

Usually it is for actions to be invoked from MSI UI. But today you have a much better option embedded or External UI from which you can invoke the managed actions/routines directly without the need for setting up an MSI custom action. Am I missing something?
Mar 4, 2016 at 7:30 AM
it's my first Installer.

Были требования: чтобы был MSI и чтобы можно было администраторам удаленно устанавливать на машину. Это я сейчас понимаю, что это просто настраивается параметрами, а тогда нужно было с чего-то начать.
Coordinator
Mar 4, 2016 at 11:40 AM
OK. I see. Not a problem.

BTW I wanted to tell this... I feel bad for not responding to you in your language. I have no problems with Russian speaking and reading but typing on English keyboard is really killing me. And what is even more difficult is that I posses absolutely no knowledge of Russian technical terminology. Thus I hope this "mixed mode" wasn't too annoying for you. :)

Cheers,
Oleg