【问题标题】:Windows service installation and starting inside another serviceWindows 服务安装并在另一个服务中启动
【发布时间】:2016-05-27 14:59:11
【问题描述】:

我安装了一个主机应用程序作为 win 服务。该主机支持在自己的域中安装插件。启用了程序集卷影复制的域。本质上,插件也是赢服务。所以在插件安装过程中有以下几个阶段:

  1. 创建域,影子加载插件的程序集

  2. 使用依赖注入实例化插件的服务

  3. 执行服务安装

  4. 启动插件服务

第三和第四阶段:

public class ServiceCommander : MarshalByRefObject
{
    public Exception InstallWinService()
    {
        var assembly = service.GetType().Assembly;
        var account = AccountStore.GetAccount().Split(' ');
        var installer = new AssemblyInstaller(assembly, 
            new [] { $"/user={account[0]}", $"/password={account[1]}", $"/LogFile={TracksSinkHost.InstallLogPath}" });
        try
        {
            installer.UseNewContext = true;
            installer.Install(null);
            installer.Commit(null);
            return null;
        }
        catch (Exception ex)
        {
            installer.Rollback(null);
            return new Exception(ex.Message) { Source = ex.Source }; 
        }
    }

    public Exception StartWinService(bool ignoreManualStartType = false)
    {
        try
        {
            ServiceBase.Run(service);
            var serviceController = new ServiceController(service.ServiceName);
            if (serviceController.Status != ServiceControllerStatus.Running &&
                (serviceController.StartType == ServiceStartMode.Automatic || ignoreManualStartType))
                serviceController.Start();
            return null;
        }
        catch (Exception ex)
        {
            return new Exception(ex.Message) { Source = ex.Source };
        }
    }
}

service 对象是 ServiceBase

虽然所有阶段都成功了,但第四阶段却没有。 serviceController.Start() 立即 throws "服务因以下错误无法启动: 服务没有及时响应启动或控制请求。” 我还在系统事件日志中看到 “在等待服务连接时达到了超时(30000 毫秒)。”

对我来说似乎服务控制管理器找不到插件的入口点,所以我在插件的项目中提供了启动对象:

static class Program
{
    public static ServiceBase Service;

    static void Main(string[] args)
    {
        if (Service != null)
            ServiceBase.Run(Service);
    }
}

但 Main 从未执行。

如果手动启动安装插件的服务或禁用子域上的卷影复制,我也会看到相同的事件日志。那怎么了?

【问题讨论】:

  • 新进程真的启动了吗? (如果您不确定,Process Monitor 可能是一个合适的故障排除工具。)新服务是如何配置的,即sc qc 显示什么?
  • 我不明白,为什么你已经有了“ServiceBase.Run(service)”,然后用ServiceController重新启动它?您是否尝试再次启动服务(正在启动时)?
  • @HoàngLong:好点,我没注意到。 ServiceBase.Run() 在当前进程正在运行的服务停止之前不会返回,并且根本不能保证返回(进程可能只是被终止)所以虽然我不确定 OP 试图做什么,但代码肯定是错的。
  • 我不确定您的总体目标是什么 - 您谈论的是卷影复制,但您知道一旦注册服务,Windows 将负责用于启动将来运行服务的进程,并且在执行此操作时不会使用卷影复制创建应用程序域。
  • @Damien_The_Unbeliever 你说得对,我错过了 Windows 在serviceController.Start() 之后启动新进程并希望它在我的引导进程中运行

标签: c# windows-services


【解决方案1】:

从代码来看,我的猜测是它正在尝试启动一个正在启动的服务,因此导致了异常。

要确认,在StartWinService功能中,请记录serviceController.Status的状态。我怀疑它目前可能是StartPending,因为您已经调用了ServiceBase.Run(service)

如果正确,请尝试删除 serviceController 部分。

说明:ServiceBase.Run() 只是注册服务(又名:标记为启动),因此无法保证当您使用 serviceController 检查状态时,您的服务已经启动完毕。

【讨论】:

    猜你喜欢
    • 2015-01-10
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多