[wix-users] Problem Updating

Jon Earle earlej at hotmail.com
Tue Mar 6 13:59:37 PST 2018


I gave up trying to solve it the "wix way" and fell back to custom actions.
Modifications to the Custom Action C# code to add two methods to Stop and Start a named service:

    using System.ServiceProcess;

    /**************************************************************************\
    *
    * Function:  StopService
    *
    * Purpose:  Stops the named service.
    *
    ***************************************************************************/
    [CustomAction]
    public static ActionResult StopService(Session session)
    {
        session.Log("Begin StopService Custom Action");
        string serviceName = session.CustomActionData["SERVICENAME"];
        try
        {
            if (!string.IsNullOrEmpty(serviceName))
            {
                ServiceController sc = new ServiceController(serviceName);
                // Start the service if the current status is any state other than running or start pending.
                if (!(sc.Status.Equals(ServiceControllerStatus.Stopped))
                 && !(sc.Status.Equals(ServiceControllerStatus.StopPending)))
                {
                    sc.Stop();
                }
            }
        }
        catch (Exception ex)
        {
            session.Log("Failed to stop service " + serviceName + " : " + ex.ToString());
            return ActionResult.Failure;
        }
        finally
        {
            session.Log("End StopService Custom Action");
        }
        return ActionResult.Success;
    }

    /**************************************************************************\
    *
    * Function:  StartService
    *
    * Purpose:  Starts the named service.
    *
    ***************************************************************************/
    [CustomAction]
    public static ActionResult StartService(Session session)
    {
        session.Log("Begin StartService Custom Action");
        string serviceName = session.CustomActionData["SERVICENAME"];
        try
        {
            if (!string.IsNullOrEmpty(serviceName))
            {
                ServiceController sc = new ServiceController(serviceName);
                // Start the service if the current status is any state other than running or start pending.
                if (!(sc.Status.Equals(ServiceControllerStatus.Running))
                 && !(sc.Status.Equals(ServiceControllerStatus.StartPending)))
                {
                    sc.Start();
                }
            }
        }
        catch (Exception ex)
        {
            session.Log("Failed to control service " + serviceName + " : " + ex.ToString());
            return ActionResult.Failure;
        }
        finally
        {
            session.Log("End StartService Custom Action");
        }
        return ActionResult.Success;
    }

Next, in my Product.wxs, custom action definitions (two services, each to be stopped and started, plus one to set the service name to be acted upon):

    <!-- These next CA's relate to stopping and starting key services prior to Modifying the PCI feature state. -->
    <CustomAction Id="CAL_StopService_Service1.SetProperty" Property="CAL_StopService_Service1"
                  Value="SERVICENAME=$(var.Service1_Service_Name)" />
    <CustomAction Id="CAL_StopService_Service1" DllEntry="StopService" BinaryKey="CAL_dll" Execute="deferred" Return="ignore" />
    <CustomAction Id="CAL_StopService_Service2.SetProperty" Property="CAL_StopService_Service2"
                  Value="SERVICENAME=$(var.Service2_Service_Name)" />
    <CustomAction Id="CAL_StopService_Service2" DllEntry="StopService" BinaryKey="CAL_dll" Execute="deferred" Return="ignore" />
    <CustomAction Id="CAL_StartService_Service1.SetProperty" Property="CAL_StartService_Service1"
                  Value="SERVICENAME=$(var.Service1_Service_Name)" />
    <CustomAction Id="CAL_StartService_Service1" DllEntry="StartService" BinaryKey="CAL_dll" Execute="deferred" Return="ignore" />
    <CustomAction Id="CAL_StartService_Service2.SetProperty" Property="CAL_StartService_Service2"
                  Value="SERVICENAME=$(var.Service2_Service_Name)" />
    <CustomAction Id="CAL_StartService_Service2" DllEntry="StartService" BinaryKey="CAL_dll" Execute="deferred" Return="ignore" />

Finally, the sequencing of the custom actions in InstallExecuteSequence. The conditions for Stopping are: state and action are changing for the PCI feature and the service component itself is installed.  For starting, the same basic check as for stopping, plus, a check to ensure we're not uninstalling the app.

    <!-- Manage services affected by PCI feature. -->
    <Custom Action="CAL_StopService_Service1.SetProperty" Before="CAL_StopService_Service1" />
    <Custom Action="CAL_StopService_Service2.SetProperty" Before="CAL_StopService_Service2" />
    <Custom Action="CAL_StartService_Service1.SetProperty" Before="CAL_StartService_Service1" />
    <Custom Action="CAL_StartService_Service2.SetProperty" Before="CAL_StartService_Service2" />
    <Custom Action="CAL_StopService_Service1" Before="StopServices">
        <![CDATA[(&PCI <> !PCI) AND (?Service1_service = 3)]]>
    </Custom>
    <Custom Action="CAL_StopService_Service2" Before="StopServices">
        <![CDATA[(&PCI <> !PCI) AND (?Service2_service = 3)]]>
    </Custom>
    <Custom Action="CAL_StartService_Service1" After="StartServices">
        <![CDATA[((&PCI <> !PCI) AND (?Service1_service = 3)) AND NOT REMOVE~="ALL"]]>
    </Custom>
    <Custom Action="CAL_StartService_Service2" After="StartServices">
        <![CDATA[((&PCI <> !PCI) AND (?Service2_service = 3)) AND NOT REMOVE~="ALL"]]>
    </Custom>

Solves the issue at hand.  Critique? Suggestions to improve?

________________________________
From: wix-users <wix-users-bounces at lists.wixtoolset.org> on behalf of Jon Earle via wix-users <wix-users at lists.wixtoolset.org>
Sent: Tuesday, March 6, 2018 11:22 AM
To: Nir Bar
Cc: Jon Earle; Jon Earle via wix-users
Subject: Re: [wix-users] Problem Updating

Right... during Install, REMOVE is definitely not ALL.  That's fine and what I want.  However, during Uninstall, REMOVE would be set to ALL, yet the component continues to be applied.

I  tried setting the Start to just "install" and it does not start the service...

Here is my flow:

  1.  Install the MSI with all features selected.
  2.  De-select the PCI component and click Modify (to remove it).
  3.  Select the PCI component and click Modify (to add it).
  4.  Click Uninstall.

Results:

  1.  App is installed, with all features, drivers and services. Services are started.
  2.  Services are stopped. PCI feature and drivers are removed. Services are not restarted -- PROBLEM.
  3.  Services are stopped (already were). PCI feature and drivers are installed. Services are started.
  4.  Entire app, incl all features, drivers and services, is removed.

With the condition set to NOT REMOVE~="ALL" and the service controls set to Start = Stop = "both", the services are stopped and restarted in steps 2 and 3, which is correct, however, the services are also started during Uninstall, which is not correct.

If the Condition does not help in this case, I'll yank it out.  How then, would I author the control to stop and start the services only when Modifying and not Uninstalling?  Custom Action?  Didn't want to go there if there is a "Wix" way.

Cheers!
Jon




________________________________
From: Nir Bar <nir.bar at panel-sw.com>
Sent: Tuesday, March 6, 2018 3:11 AM
To: Jon Earle
Cc: Hoover, Jacob; Jon Earle via wix-users
Subject: Re: [wix-users] Problem Updating

Component condition just says whether or not the component is to be installed.
So setting it to 'NOT REMOVE="ALL"' will always evaluate to true since during install REMOVE is definitely not "ALL".

Setting ServiceControl Start="both" is odd since it means you want to start the service during uninstall. This is required only when you're stopping services that are not part of your MSI (such as IIS).

I think you only need to change Start="install" and remove the condition altogether.

--
Nir Bar, Independent WiX Expert. Creator of-
JetBA: WiX WPF Bootstrapper User Interface Framework
JetBA++: WiX Native Bootstrapper User Interface Framework



____________________________________________________________________
WiX Toolset Users Mailing List provided by FireGiant http://www.firegiant.com/



More information about the wix-users mailing list