有条件地停止/开始服务

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有条件地停止/开始服务相关的知识,希望对你有一定的参考价值。

Wix 3.10.3,Installer是一个包装msi的自定义引导程序。我已经实现了安装/卸载和修改功能。

MSI安装了几个服务,其中至少有一个服务与PCI驱动程序接口 - 当我添加或删除PCI组件时,我需要停止并重新启动与所述组件接口的服务,以防止可怕的“必须重新启动“方案。

我发现我可以将ServiceControl元素添加到安装驱动程序的组件中,但是,它也会在卸载应用程序时启动服务。

我读过一些关于“共享组件”的提及,尽管没有太多关于它的文档,这表明这将成为这种情况的一种方式。

<Fragment>
    <Component Id="PCIDriver_SvcCtl" Directory="INSTALLDIR" Guid="{5EAB2128-228D-44BE-950F-5F258B94BFED}" Win64="$(var.Win64)" >
        <CreateFolder/>
        <!-- Any action but uninstall. -->
        <Condition>NOT REMOVE~="ALL"</Condition>
        <ServiceControl Id="Service1_SvcCtl" Name="service1" Start="both" Stop="both" Wait="no" />
        <ServiceControl Id="Service2_SvcCtl" Name="service2" Start="both" Stop="both" Wait="no" />
    </Component>
</Fragment>

然后,在我的Product.wxs中,针对需要它的功能(安装PCI驱动程序),我添加了:

<ComponentRef Id="PCIDriver_SvcCtl" />

可能与我的问题无关,但是,与重启管理器相关,我在Product.wxs中设置了以下Restart Manager属性:

<Property Id="MSIRMSHUTDOWN" Value="1" />

因此,当我通过Modify添加/删除PCI驱动程序时,我的组件运行,停止然后启动服务,但是,当我卸载整个应用程序时,它也会运行。由于有两个服务,当它们被删除并且调用它们来启动它们时,它会为卸载增加两分钟(因为重启尝试两次,每个服务器等待时间为30秒)。

我需要设置什么条件才能避免在MSI卸载时调用此组件,但允许它在修改期间运行?或者,我需要以不同的方式创作吗?谢谢!

答案

如果我理解您正在尝试正确执行的操作,则只需要在ServiceControl表中使用msidbServiceControlEventUninstallStop值进行掩码。这是MSI记录的方式,而不是如何在WiX中进行,但它应该让你开始。

另一答案

我放弃了尝试以“wix方式”解决它并回到自定义操作。

修改自定义操作C#代码以添加两个方法来停止和启动命名服务:

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;
}

接下来,在我的Product.wxs中,自定义操作定义(两个服务,每个服务要停止和启动,另外一个用于设置要对其执行操作的服务名称):

<!-- 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" />

最后,在InstallExecuteSequence中对自定义操作进行排序。停止的条件是:PCI功能的状态和操作正在发生变化,并且安装了服务组件本身。对于启动,与停止相同的基本检查,以及检查以确保我们不卸载应用程序。

<!-- 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>

解决手头的问题。批判?建议改善?

以上是关于有条件地停止/开始服务的主要内容,如果未能解决你的问题,请参考以下文章

条件片段和导航重用

Laravel 5.8 有条件地插入 sql 片段

有条件地导入 python 类的片段

自动刷新android片段,直到满足条件

创新永不停止—甲骨文自治数据仓库云服务

如何清除片段中的参数?