Как запустить службу в учетной записи сетевой службы на сервере, когда клиент входит в систему?

У нас есть существующая система, в которой служба Windows, в которой включена сетевая служба, размещается на учетной записи сетевой службы на сервере. На каждом клиенте установлены службы Windows, которые запускаются автоматически после входа пользователя в систему через каждого клиента, и эти службы на клиенте запускают службу на сервере, сообщая ей, что, например, клиент A вошел в систему.

То, что я хочу сделать, это создать сетевой сервис и разместить его на сервере, и запускать его напрямую, не устанавливая отдельную службу Windows на каждом клиенте. Является ли это возможным? Я хочу, чтобы каждый клиент использовал существующую сетевую службу и сообщал ей при входе в систему, что он находится в сети. Вроде как ведение журнала входа пользователя на сервер со временем.

1 ответ

Я сделал это с помощью Simple Impersonation Library. Вот фрагмент, который я использую на своем клиенте WPF.

public static async Task ToggleServiceStatus(this EdiServiceInfo serviceInfo)
        {
            await Task.Factory.StartNew(() =>
            {
                using (
                    Impersonation.LogonUser(serviceInfo.Domain, serviceInfo.User, serviceInfo.Pswd,
                        Environment.MachineName.Equals(serviceInfo.ComputerName,
                            StringComparison.InvariantCultureIgnoreCase)
                            ? LogonType.Network
                            : LogonType.Interactive))
                {
                    var service = new ServiceController(serviceInfo.ServiceName, serviceInfo.ComputerName);
                    if (service.Status == ServiceControllerStatus.Stopped)
                    {
                        service.Start();
                        service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(60));
                    }
                    else
                    {
                        service.Stop();
                        service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(60));
                    }
                }
            });
        }

Это полезно, если вы хотите запустить службу с вашего клиента. Но если служба уже работает и просто хочет ответить на вход в систему, вы можете сохранить таблицу клиентов с флагом DidLoggedIn, и ваша служба Windows должна иметь долгосрочную задачу, отслеживающую эти флаги. Идея заключается в том, что всякий раз, когда клиент входит в систему, вы устанавливаете флаг в значение true, а на стороне вашего сервера долгосрочная задача службы Windows обнаружит это и будет делать все, что вы захотите.

Надеюсь, поможет

РЕДАКТИРОВАТЬ >>> У меня есть приложение, которое делает это. Позвольте мне поделиться некоторыми фрагментами.

public virtual async Task InitAsync()
        {
            EdiDataAccess.ResetServiceFlags();
            EdiDataAccess.SetServiceAsWorking();
            var startMonitorTask = new Func<Task>(StartAllWorkersAsync)
                .CyclicalTask(TimeSpan.FromSeconds(MonitorSeconds), MonitorCancellationToken);
            var stopMonitorTask = new Func<Task>(StopRequestsMonitor)
                .CyclicalTask(TimeSpan.FromSeconds(MonitorSeconds), MonitorCancellationToken);
            await TaskEx.WhenAll(startMonitorTask, stopMonitorTask);
        }

startMonitorTask - это долгосрочное задание для отслеживания флагов. CyclicalTask - мой собственный метод расширения:

public static Task CyclicalTask(this Func<Task> task, TimeSpan waitTimeSpan,
            CancellationToken token = default(CancellationToken))
        {
            return TaskEx.Run(async () =>
            {
                while (true)
                {
                    token.ThrowIfCancellationRequested();
                    await task();
                    token.WaitHandle.WaitOne(waitTimeSpan);
                }
            }, token);
        }

StartAllWorkersAsync - это метод, который имеет функцию мониторинга.

protected virtual async Task StartAllWorkersAsync()
        {
            var ediCustomersToStart = EdiDataAccess.GetEdiCostumersToStart();
            var ediTasks = ediCustomersToStart
                .Select(StartWorkerAsync)
                .ToList();
            await TaskEx.WhenAll(ediTasks);
        }

Где EdiDataAccess.GetEdiCostumersToStart(); извлекает всех тех клиентов, которые запросили войти

Эта служба моего окна может определить, когда клиент запросил начать сеанс.

Другие вопросы по тегам