gpt4 book ai didi

java - JNA Windows 服务启动类型

转载 作者:可可西里 更新时间:2023-11-01 09:56:14 25 4
gpt4 key购买 nike

我一直在玩弄 JNA,并且能够使用下面的代码返回 Windows 服务的状态(即启动或停止)。我不确定如何返回服务的启动类型。我确信 JNA 之外还有其他方法,但如果可能的话,我想继续使用 JNA。

import com.sun.jna.*;
import com.sun.jna.Library.Handler;
import com.sun.jna.platform.win32.*;
import com.sun.jna.platform.win32.Advapi32Util.*;
import com.sun.jna.platform.win32.WinNT.*;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.*;


public class WindowsService {

public static void main(String[] args) {

W32ServiceManager serviceManager = new W32ServiceManager();
serviceManager.open(Winsvc.SC_MANAGER_ALL_ACCESS);
W32Service service = serviceManager.openService("W32Time", Winsvc.SC_MANAGER_ALL_ACCESS);
System.out.println(service.queryStatus().dwCurrentState);
service.close();

}
}

最佳答案

这里的问题是,虽然特定于 JNA 平台的代码提供了查询服务状态的处理,但它不提供查询服务配置的支持。这意味着要这样做,您需要为相关函数提供 JNA 映射。

在这种情况下,您需要的函数是 QueryServiceConfig()在 Advapi32 中定义。这个函数填写一个QUERY_SERVICE_CONFIG结构,它有一个 dwStartType 属性,它对应于各种启动类型值。

幸运的是,使用 JNA 映射 native 函数非常简单:您只需像这样声明一个接口(interface)(我提供的代码示例是用 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
)
}

(我使用 JNA 源代码中的 definition for QueryServiceStatusEx() 得出它,其参数与 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 需要,但尺寸可能不合适。)

有了我们的结构和新接口(interface),我们可以创建一个方法来调用 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)

关于java - JNA Windows 服务启动类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9742639/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com