Как запустить службу в учетной записи сетевой службы на сервере, когда клиент входит в систему?
У нас есть существующая система, в которой служба 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(); извлекает всех тех клиентов, которые запросили войти
Эта служба моего окна может определить, когда клиент запросил начать сеанс.