Ядро dotnet TopShelf Windows Service не запускается - PullRequest
0 голосов
/ 24 сентября 2019

У меня есть сборка консольного приложения dotnet для подключения к экземпляру Sql Service Broker для отслеживания изменений в таблице.

Приложение отслеживает одну таблицу, которая обновляется из системы ERP, а затем публикует сообщения на нашу шину.

Оно отлично работает при запуске в качестве консольного приложения или отладке в моей IDE.

У меня возникла проблема при использовании TopShelf для настройки его в качестве службы Windows.

Вот точка входа:

        private static void Main(string[] args)
       {
        RegisterComponents();

        var serviceHost = HostFactory.Run(sc =>
        {
            sc.Service<ISalesOrderMonitorService>(s =>
            {
                var sqlListener = _container.ResolveNamed<SqlDependencyEx>(ListenerKey.SalesOrder);
                var changeHandler = _container.Resolve<ISalesOrderChangeHandler>();
                var listenerConfig = _container.ResolveNamed<ListenerConfiguration>(ListenerKey.SalesOrder);
                var logger = _container.Resolve<ILogger<SalesOrder>>();

                s.ConstructUsing(f =>
                    new SalesOrderMonitorService(sqlListener, changeHandler, listenerConfig, logger));

                s.WhenStarted(tc => tc.Start());
                s.WhenStopped(tc => tc.Stop());
            });
        });

        var exitCode = (int) Convert.ChangeType(serviceHost, serviceHost.GetType());

        Environment.ExitCode = exitCode;
    }

Класс «рабочий»:

    public abstract class ServiceBase<T, TZ> : IService<T>
    where T : IChangeHandler
{
    protected readonly IChangeHandler ChangeHandler;
    protected readonly SqlDependencyEx Listener;
    protected readonly ListenerConfiguration ListenerConfiguration;
    protected readonly ILogger<TZ> Logger;

    protected ServiceBase(SqlDependencyEx listener, IChangeHandler changeHandler,
        ListenerConfiguration listenerConfiguration, ILogger<TZ> logger)
    {
        Logger = logger;
        ListenerConfiguration = listenerConfiguration;
        Listener = listener;
        ChangeHandler = changeHandler;
    }

    public virtual void Start()
    {
        try
        {
            Listener.TableChanged += (o, e) => ChangeHandler.Process(e);

            Listener.Start();

            Logger.LogDebug(
                $"Listening to changes on the {ListenerConfiguration.Table} table in the {ListenerConfiguration.Database} database");
        }
        catch (Exception e)
        {
            Logger.LogError(e, e.Message);
            throw;
        }

    }

    public virtual void Stop()
    {
        Listener.Stop();
    }

Установка через TopShelf не проблема:

c:>{ServiceName}.exe install -username "serviceAccount" -password "superSecret" -servicename "ServiceName" -servicedescription "Description" -displayname "Service DisplayName" --autostart

Когда я иду, чтобы запустить службу - я получаю это:

enter image description here

Это вводит в заблуждение, потому что средство просмотра событий показывает это:

enter image description here

Это происходит намного быстрее, чем 30 секунд.Это определенно связано с тем, как я настраиваю TopShelf.

Как уже говорилось - приложение прекрасно работает, когда запускается «отладка» или даже просто как консоль exe.

1 Ответ

0 голосов
/ 26 сентября 2019

Я понял это.На самом деле оба комментария от @DotNetPadawan и @Lex Li косвенно привели меня туда.

Для начала - включение удаленного отладчика подсказало мне, что мой appsetting.json не считывался в мою конфигурацию IConfiguration.Это действительно сбивало с толку, потому что все работает нормально, работая локально с отладчиком или даже просто запуская exe.

Ссылка, на которую указывает Лекс Ли, не дала ответа - однако в этой статье была эта ссылка:

Хост и развертывание aspnetcore в качестве службы Windows

Именно здесь я обнаружил этот маленький слепок:

Текущий рабочий каталог, возвращенный вызовом GetCurrentDirectory дляСлужба Windows - это папка C: \ WINDOWS \ system32.Папка system32 не подходит для хранения файлов службы (например, файлов настроек).Используйте один из следующих подходов для поддержки и доступа к файлам ресурсов и настроек службы.

Ссылка объясняет, как условно установить текущий каталог, если приложение работает как служба.

        var isConsole = args.Contains("-mode:console");

        if (!isConsole)
        {
            var pathToExe = Process.GetCurrentProcess().MainModule?.FileName;
            var pathToContentRoot = Path.GetDirectoryName(pathToExe);
            Directory.SetCurrentDirectory(pathToContentRoot);
        }

Помещение этого для всех, кто сталкивается с этой проблемой.

По общему признанию - netcore 3.0, вероятно, лучший путь, но у меня нет пропускной способности для обновлениявсе это репо (много общего) до 3.0.Мне нужно, чтобы это работало.

...