Я хочу, чтобы моя служба работала без изменений, но как пользователь, являющийся администратором (Windows / UAC) - PullRequest
3 голосов
/ 21 июня 2011

Как видно из названия, я написал программу, запускающуюся «в фоновом режиме», предпочтительно как служба Windows.(Это написано на Java, с сервисной частью, предоставляемой оболочкой tanuki, если это имеет значение. Кроме того, я использую Vista, но предполагаю, что это происходит во всех версиях Windows с UAC.)как «Пользователь X».

У меня также есть сопутствующая программа с графическим интерфейсом, которая обычно запускается из меню «Пуск» (непривилегированный - то есть «asInvoker») - также как «Пользователь Х».

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

Это работает без хлопот, пока «Пользователь Х» не является членомгруппа администраторов.(Конечно, для создания службы требуется логин администратора, но это нормально.)

Это также работает, если я отключаю UAC или запускаю фоновую программу не как службу (например, из командыподскажите).

Но я просто не могу заставить его работать, когда «Пользователь Х» является членом Администраторов, а фоновая программа работает как служба.

Симптомы этогоПроблема в том, что в проводнике процессов мой сервисный процесс отображается как привилегированный (который я выбрал на вкладке «Безопасность» в свойствах процессов и отображал «BUILTIN \ Администраторы - Владелец»).Кроме того, все файлы, созданные службой, принадлежат «Администраторам».

Если я запускаю фоновую программу без привилегий из командной строки, то в проводнике процессов отображается «BUILTIN \ Administrators - Deny», а все файлы, созданныеПрограмма принадлежит «Пользователю X».

Ответы [ 2 ]

1 голос
/ 29 сентября 2011

В конце я реализовал обходной путь, используя запланированные задачи Windows, аналогично тому, что описано выше, но вместо реализации собственного интерфейса «старт / стоп» я написал службу Windows, которая управляет моей программой, выполняемой какзадача.Когда служба запускается, она запускает задачу, а когда служба запрашивается об остановке, она останавливает задачу.Поэтому вместо того, чтобы использовать сокет для родительского элемента для запроса, если дочерний элемент запущен, я использую schtasks / Query и анализирую вывод.Чтобы заставить задачу завершиться, если родительская программа завершается, я использовал метод keepalive RMI в моем приложении, которое уже было там.

Для запланированных задач Windows есть некоторые нежелательные значения по умолчанию для службы, которые можно изменить с помощью графического интерфейса планировщика задач, ноне через параметры командной строки schtasks, а именно: ExecutionTimeLimit, DisallowStartIfOnBatteries, StopIfGoingOnBatteries.) Но эти параметры можно запрашивать и изменять с помощью параметра / XML для schtasks / Query и / Create.Так вот что я сделал.

Мне также нужно было определить, работаю ли я на более новой или более старой версии Windows, потому что если это более старая версия (без UAC), то все это будет ненужным, но, что более важно, определение задачи не будет работатьбез указания пароля, потому что опция / NP для schtasks недоступна.

Единственный недостаток (кроме сложного), о котором я знаю в своей реализации, связан с примечанием schtasks к параметру / NP -«Доступны только местные ресурсы».Оказывается, это означает, что подключенные сетевые диски не будут доступны (и я надеюсь, что это все, что это означает.) У меня поддержка SMB реализована независимо, в Java, в моем приложении, где это необходимо, так что эта слабость не была концоммира.

Это было много работы для того, что, вероятно, можно сделать с помощью одного вызова Win32.Может быть, однажды я пойму, как это сделать.

1 голос
/ 21 июня 2011

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

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

Во-вторых, действительно ли сама служба должна работать как «Пользователь Х»? Если так, то почему? Есть ли способ обойти это ограничение? Если вы можете обойти это требование, то вы можете просто сделать обычного пользователя, чтобы служба работала как.

В-третьих, вы сказали, что желательно как услуга, но не то, что это требование. Позволяет ли среда, в которой это используется, выполнять запланированные задачи? Планировщик задач сам работает как системная служба и порождает другие процессы для выполнения задач, которые вы создали. И, при настройке запланированной задачи, есть опция (флажок, если вы используете графический интерфейс), чтобы запустить задачу с наивысшими привилегиями или нет. Если вы идете по этому пути, вы можете запустить задачу при входе в систему или запустить ее при запуске системы (в этом случае убедитесь, что вы НЕ выбрали «запускать только при входе в систему»). В противном случае это должно быть похоже на настройку вашего сервиса.

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

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

Если вам требуется только состояние «работает / не работает», этого будет достаточно, и ServerSocket может принять () соединение, а затем немедленно завершить работу и закрыть получившийся Socket; вам даже не нужно принимать или отправлять какую-либо информацию, поскольку все, что вам нужно - это начальное соединение.

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

Для запуска, если вы хотите ограничить фоновый процесс одним экземпляром, есть несколько способов сделать это легко. Я думаю, что вы должны быть в состоянии настроить его через планировщик задач, чтобы разрешить только один экземпляр задачи. Даже если это не так, у вас может быть фоновый процесс, запускающий соединение с данным портом, который он в противном случае прослушивал бы, чтобы узнать, получает ли он соединение от чего-то другого, уже существующего там, если да, то это второй случай его отмены. Или, что еще проще, создание ServerSocket должно автоматически завершиться неудачей, если вы используете статический номер порта, поэтому просто позвольте новому ServerSocket (myPort) произойти сбой самостоятельно, перехватите исключение и прервите работу. Таким образом, есть три различных способа убедиться, что ваш процесс работает как правильный сервис.

Прежде всего, чтобы запустить его, вы можете указать планировщику задач, чтобы он запускался при входе пользователя в систему или при загрузке системы, как упоминалось ранее. Вы также можете настроить задачу так, чтобы пользователи могли запускать ее самостоятельно (если по какой-либо причине она еще не запущена), фактически вы могли бы даже настроить клиент, с которым взаимодействует пользователь, проверку состояния процесса и, возможно, запустить его автоматически если он еще не запущен - попробуйте создать новый процесс и выполнить exec () команду, например "schtasks / run / tn" Ваше имя задачи ""

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

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