Проблема здесь в том, что, хотя специфичный для платформы JNA код обеспечивает обработку запросов о состоянии службы, он не обеспечивает поддержку запросов о конфигурации службы.Это означает, что для этого вам необходимо предоставить сопоставление JNA для рассматриваемой функции.
Функция, которую вы хотели бы в этом случае определить QueryServiceConfig()
в Advapi32.Эта функция заполняет структуру QUERY_SERVICE_CONFIG
, которая обладает свойством dwStartType
, которое соответствует различным значениям типа запуска.
К счастью, отображение нативной функции действительно прямолинейно.Вперед с JNA: вы просто объявляете интерфейс следующим образом (примеры кода, которые я предоставляю, написаны на Groovy; преобразование в Java должно быть довольно простым):
interface MyAdvapi32 extends StdCallLibrary {
MyAdvapi32 INSTANCE = (Advapi32) Native.loadLibrary("Advapi32", MyAdvapi32.class, W32APIOptions.UNICODE_OPTIONS);
boolean QueryServiceConfig(
SC_HANDLE hService,
QUERY_SERVICE_CONFIG lpServiceConfig,
int cbBufSize,
IntByReference pcbBytesNeeded
)
}
(я получил это, используяопределение для QueryServiceStatusEx()
в источнике JNA, параметры которого близко соответствуют параметрам для QueryServiceConfig()
. Обратите внимание, что QueryServiceStatusEx()
в конечном счете является функцией, вызываемой W32Service#queryStatus()
).
Однако нашей функции требуется структура QUERY_SERVICE_CONFIG
, которая не определена нигде в JNA.Работая на основе модели определения JNA SERVICE_STATUS_PROCESS
, мы получаем что-то вроде:
class QUERY_SERVICE_CONFIG extends Structure {
public DWORD dwServiceType
public DWORD dwStartType
public DWORD dwErrorControl
public char[] lpBinaryPathName
public char[] lpLoadOrderGroup
public DWORD dwTagId
public char[] lpDependencies
public char[] lpServiceStartName
public char[] lpDisplayName
QUERY_SERVICE_CONFIG() {}
QUERY_SERVICE_CONFIG(int size) {
lpBinaryPathName = new char[256]
lpLoadOrderGroup = new char[256]
lpDependencies = new char[256]
lpServiceStartName = new char[256]
lpDisplayName = new char[256]
allocateMemory(size)
}
}
(Обратите внимание, что эта структура несколько сложнее, чем SERVICE_STATUS_PROCESS
, поскольку SERVICE_STATUS_PROCESS
имеет только параметры DWORD
. Размеры размещения, которые я предоставил во втором конструкторе, хотя и требуются для JNA, вероятно, имеют неправильный размер.)
Вооружены нашей структурой иНовый интерфейс, мы можем создать метод для вызова QueryServiceConfig:
QUERY_SERVICE_CONFIG queryServiceConfig(W32Service service) {
IntByReference size = new IntByReference()
MyAdvapi32.INSTANCE.QueryServiceConfig(
service.handle,
null,
0,
size
)
QUERY_SERVICE_CONFIG config = new QUERY_SERVICE_CONFIG(size.value)
if (!MyAdvapi32.INSTANCE.QueryServiceConfig(
service.handle,
config,
config.size(),
size
)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
return config
}
Как только мы получим все это, использовать его довольно просто:
QUERY_SERVICE_CONFIG config = queryServiceConfig(service)
System.out.println(config.dwStartType)