Несколько служб из одного исполняемого файла

StackOverflow https://stackoverflow.com/questions/113288

  •  02-07-2019
  •  | 
  •  

Вопрос

Я написал небольшой сервис (обычный Win32) и хотел бы знать, можно ли запускать несколько его экземпляров, когда в систему вошли несколько пользователей.

По сути, предположим, что у нас есть UserA и UserB: для UserA служба будет входить в систему как «domain\UserA», а для UserB служба будет входить в систему как «domain\UserB» — это, конечно, из одного и того же исполняемого файла.Я могу изменить вход в систему динамически с помощью функции ChangeServiceConfig(), но, похоже, она меняет его в масштабах всей системы, в то время как мне бы хотелось, чтобы у каждого пользователя была своя собственная копия службы, работающая только для него.

Заранее благодарим вас за любые указатели.

Это было полезно?

Решение

Службы Win32 предназначены для общесистемной работы и запускаются до входа в систему любого пользователя.Если вы хотите, чтобы что-то запускалось индивидуально для каждого пользователя, вероятно, лучше спроектировать его как обычное приложение и запускать из группы запуска пользователя.

Другие советы

Возможно ли, чтобы служба создавала дочерние процессы, которые затем принимали учетные данные пользователя (или запускались с ними)?Таким образом, вы по-прежнему ограничены одним экземпляром службы, но она все равно может выполнять свои задания для каждого пользователя.IIRC, служба планировщика задач Windows, делает это.

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


Возможным направлением может быть запуск службы как СИСТЕМА. И каждые несколько минут проверяйте, вошел ли пользователь в систему, если есть - выдавайте себя за этого пользователя и делайте это.

Да, это звучит близко (я отвечаю на комментарий Грега, но комментарии слишком короткие, чтобы соответствовать моему ответу).

Я не знаю заранее список пользователей, но есть приложение для управления графическим интерфейсом, которое будет использоваться для ввода пар имя пользователя/пароль для каждого пользователя.Итак, пользователь А войдет в систему, запустит приложение, введет свои учетные данные, и служба будет их использовать.В то же время (после того, как пользователь А вышел из системы, но служба все еще работает с учетными данными пользователя А) пользователь Б входит в систему, использует приложение, и другая копия службы начинает работать от имени пользователя Б.Таким образом, одновременно работают службы userA и userB.

Это возможно?

Вероятно, вы хотите выдать себя за пользователей.Ознакомьтесь с некоторыми ссылками, которые я нашел с помощью быстрого поиска в Google:

Похоже, что на самом деле у вас есть два разных, противоречивых требования относительно времени и личности.

  1. Запускать от имени каждого вошедшего в систему пользователя
  2. Запускается автоматически, даже если ни один пользователь не вошел в систему.

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

ОДНАКО это может быть не лучшая идея, поскольку пользователь все еще успешно вошел в систему.Это может иметь множество побочных эффектов, включая безопасность, производительность (слишком много пользователей вошли в систему одновременно...) и т. д.

Вы можете создать служебное приложение и неслужебное (обычное) приложение и заставить их взаимодействовать через IPC (сопоставленный файл, каналы, MailSolts...вы называете это).

Таким образом вы решите все проблемы.

ПРИМЕЧАНИЕ:Одно и то же приложение может вести себя по-разному — при запуске как процесса и при запуске пользователем, но в итоге это одно и то же, у вас все равно есть 2 приложения (неважно, если у вас есть только один исполняемый файл).

Возможен запуск с разных учетных записей.На самом деле это обычное дело.См. svchost.exe, который реализует ряд служб ОС.

Я просто не понимаю, как вы определяете, какие аккаунты.В большой компании множество компьютеров настроено так, чтобы ими могли пользоваться все более 100 000 сотрудников.Вы не хотите запускать свою службу от имени вошедших в систему пользователей и не можете запускать ее для всех 100 000 пользователей.Итак, для каких аккаунтов я должен спросить?

Процесс Windows может одновременно выполняться только с привилегиями одного пользователя.Это касается сервисов и других процессов.При наличии достаточных привилегий можно «переключаться» между разными пользователями, используя олицетворение.Наиболее распространенный шаблон того, что вы пытаетесь сделать, — это иметь один экземпляр привилегированной службы, которая регистрируется для событий входа/выхода из системы и соответственно создает дочерние процессы, каждый из которых олицетворяет вошедшего в систему пользователя.Этот шаблон также упростит пользовательский интерфейс, поскольку каждый процесс запускается на рабочем столе каждого отдельного пользователя, как если бы это было обычное приложение.

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

Вы хотите, чтобы это работало постоянно, поэтому вам нужен сервис.

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

Вам не нужно несколько экземпляров вашего сервиса.Судя по описанию вашей проблемы, вам нужна одна служба, которая может выдавать себя за пользователей и выполнять задания от их имени.

Это можно сделать, реализовав COM-объект, размещенный в службе.Ваше клиентское приложение (которое запускает конечный пользователь) вызовет CoCreateInstanceEx по вашему CLSID.Это приведет к созданию нового экземпляра вашего COM-объекта в вашей службе.Затем приложение может использовать метод на одном из ваших интерфейсов для передачи собранных учетных данных пользователя COM-объекту (хотя я бы с осторожностью относился к сбору учетных данных и вместо этого посмотрел бы, смогу ли я вместо этого передать токен пользователя).COM-объект, который работает в контексте службы, может затем вызвать LogonUser() для входа в систему пользователя и олицетворения его, чтобы он мог делать все от его имени (например, находить локальную папку appdata пользователя :-)).В других ответах есть хорошие ссылки на выдачу себя за пользователей с использованием учетных данных или токена.

Если вы чувствуете себя комфортно с COM, я бы посоветовал вам создавать ваши объекты как многопоточные (находящиеся в MTA), чтобы их выполнение не сериализовалось COM.В противном случае вам подойдет однопоточная модель по умолчанию.

Мастер Visual Studio ATL может создать скелет COM-объекта, находящегося в службе.Вы также можете прочитать о реализации службы Windows с ATL здесь: http://msdn.microsoft.com/en-us/library/74y2334x(VS.80).aspx

Если вы вообще не знаете COM, вы можете использовать другие каналы связи для передачи учетных данных в свой сервис.

В любом случае, как только ваша служба получит учетные данные, вся работа от имени пользователя должна будет выполняться в фоновом потоке, чтобы не блокировать приложение, работающее от имени пользователя.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top