У меня есть Java-приложение. В любом случае я могу сказать, был ли процесс запущен с правами администратора в Windows 7.
Определить, запускалось ли приложение Java от имени администратора Windows
Ответы (8)
Я нашел этот фрагмент кода в Интернете, который, я думаю, сделает эту работу за вас.
public static boolean isAdmin() {
String groups[] = (new com.sun.security.auth.module.NTSystem()).getGroupIDs();
for (String group : groups) {
if (group.equals("S-1-5-32-544"))
return true;
}
return false;
}
Он работает ТОЛЬКО в Windows и встроен в основной пакет Java. Я только что проверил этот код, и он работает. Меня это удивило, но это так.
SID S-1-5-32-544 — это идентификатор группы администраторов в операционной системе Windows.
Вот ссылка для получения более подробной информации о том, как это работает.
Я нашел другое решение, которое кажется независимым от платформы. Он пытается записать системные настройки. Если это не удается, пользователь может не быть администратором.
Как предложил Tomáš Zato, вы можете захотеть подавить сообщения об ошибках, вызванных этим методом. Вы можете сделать это, установив System.err
:
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.prefs.Preferences;
import static java.lang.System.setErr;
import static java.util.prefs.Preferences.systemRoot;
public class AdministratorChecker
{
public static final boolean IS_RUNNING_AS_ADMINISTRATOR;
static
{
IS_RUNNING_AS_ADMINISTRATOR = isRunningAsAdministrator();
}
private static boolean isRunningAsAdministrator()
{
Preferences preferences = systemRoot();
synchronized (System.err)
{
setErr(new PrintStream(new OutputStream()
{
@Override
public void write(int b)
{
}
}));
try
{
preferences.put("foo", "bar"); // SecurityException on Windows
preferences.remove("foo");
preferences.flush(); // BackingStoreException on Linux
return true;
} catch (Exception exception)
{
return false;
} finally
{
setErr(System.err);
}
}
}
}
Kvě 07, 2015 1:49:14 ODP. java.util.prefs.WindowsPreferences <init> WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.
Можно ли их подавить?
- person Tomáš Zato - Reinstate Monica; 07.05.2015
NullPointerException
из-за System.setErr(null)
. Чтобы исправить это, используйте вместо этого фиктивный поток вывода: System.setErr(new PrintStream(new OutputStream() { @Override public void write(int i) throws IOException { } }));
- person MC Emperor; 15.09.2015
synchronized(systemErr)
не действует, если другие потоки также не синхронизируются с System.err
.
- person Beto Neto; 19.09.2017
Run as Administrator
, что отличается от простого запуска программы от имени пользователя, входящего в группу администраторов.
- person Jonathan; 03.11.2017
В Java Runtime Environment нет такой возможности, но она может быть в собственной подпрограмме, зависящей от платформы. Обратите внимание, что обычно лучший способ убедиться в этом — это попытаться сделать это на самом деле и посмотреть, не получится ли.
Только при попытке выполнить операцию, требующую такого доступа (например, привязать порт с низким номером или открыть заведомо защищенный файл).
Метод из ответа, отмеченного как лучший, отлично работал для меня до того момента, когда мне пришлось создавать код в Jenkins на машине с Linux. com.sun.security.auth.module.NTSystem() там недоступен, и использование пакетов sun обычно считается плохой практикой: ссылка
Или вы можете сделать это:
System.getenv().get("USER")
И посмотреть, какой пользователь запустил процесс.
Когда я запускаю его как я, я получаю «goran», когда я запускаю его с помощью sudo, я получаю «root». Работает на Линукс. Наверное то, что нужно.
System.out.println(System.getenv());
Возможно, есть что-то еще.
- person Goran Jovic; 04.12.2010
System.out.println(System.getProperties());
- person Goran Jovic; 04.12.2010
Вот решение для Windows 10, я думаю, что оно работает правильно и в других ОС Windows.
public static boolean isAdmin() {
try {
ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe");
Process process = processBuilder.start();
PrintStream printStream = new PrintStream(process.getOutputStream(), true);
Scanner scanner = new Scanner(process.getInputStream());
printStream.println("@echo off");
printStream.println(">nul 2>&1 \"%SYSTEMROOT%\\system32\\cacls.exe\" \"%SYSTEMROOT%\\system32\\config\\system\"");
printStream.println("echo %errorlevel%");
boolean printedErrorlevel = false;
while (true) {
String nextLine = scanner.nextLine();
if (printedErrorlevel) {
int errorlevel = Integer.parseInt(nextLine);
return errorlevel == 0;
} else if (nextLine.equals("echo %errorlevel%")) {
printedErrorlevel = true;
}
}
} catch (IOException e) {
return false;
}
}
Приведенный ниже код сработал для меня
Команда командной строки
net user
Java-код
public static boolean isAdmin() {
StringBuilder outputbuilder = new StringBuilder();
try {
ProcessBuilder builder = new ProcessBuilder(
"cmd.exe","/c" ,"net user");
builder.redirectErrorStream(true);
Process p = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while (true) {
line = r.readLine();
if (line == null) { break; }
outputbuilder.append(line);
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
System.out.println(outputbuilder.toString());
return outputbuilder.toString().contains("Administrator");
}