Java JNA对函数的调用;“启动系统关闭”;在dll Advapi32 don';行不通

Java JNA对函数的调用;“启动系统关闭”;在dll Advapi32 don';行不通,java,dll,jna,Java,Dll,Jna,我使用java jna调用了Advapi32 dll的函数“InitiateSystemShutton”,但它不起作用: public interface JNAApiInterface extends StdCallLibrary { JNAApiInterface INSTANCE = (JNAApiInterface) Native.loadLibrary("Advapi32", JNAApiInterface.class); public boolean Initia

我使用java jna调用了Advapi32 dll的函数“InitiateSystemShutton”,但它不起作用:

public interface JNAApiInterface extends StdCallLibrary {

    JNAApiInterface INSTANCE = (JNAApiInterface) Native.loadLibrary("Advapi32", JNAApiInterface.class);

    public boolean InitiateSystemShutdown(String machine, String message, short timeout, boolean forceAppClose, boolean rebootAfterShutdown);

}



public class JNABucket {
     public static void main(String args[]) {

          System.setProperty("jna.library.path", "C:\\Windows\\System32");
          JNAApiInterface jnaLib = JNAApiInterface.INSTANCE;

          jnaLib.InitiateSystemShutdown(null, null, (short)0, true, true);
     }
}
错误是:

 Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up 
    function 'InitiateSystemShutdown': No se encontró el proceso especificado.
    at com.sun.jna.Function.<init>(Function.java:179)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:430)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:410)
    at com.sun.jna.Library$Handler.invoke(Library.java:205)
    at com.sun.proxy.$Proxy0.InitiateSystemShutdown(Unknown Source)
    at es.tecnocom.pruebas.JNABucket.main(JNABucket.java:9)
线程“main”java.lang.UnsatisfiedLinkError中的异常:查找错误 函数“InitiateSystemShutdown”:没有特殊的进程。 位于com.sun.jna.Function.(Function.java:179) 位于com.sun.jna.nativellibrary.getFunction(nativellibrary.java:430) 位于com.sun.jna.nativellibrary.getFunction(nativellibrary.java:410) 位于com.sun.jna.Library$Handler.invoke(Library.java:205) 位于com.sun.proxy.$Proxy0.InitiateSystemShutdown(未知源) 位于es.tecnocom.pruebas.JNABucket.main(JNABucket.java:9)
有人能帮我吗?

如果你看一下文档页面,你会注意到底部的实际函数名是
InitiateSystemShutdownW
(Unicode)和
InitiateSystemShutdownA
(ANSI)。大多数(全部?)处理字符串的WinAPI函数被定义为预处理器符号,它们解析为*A或*W结束函数,这取决于编译时是否定义了
UNICODE

示例来自:

根据要使用的编码,将函数重命名为
InitiateSystemShutdownA
InitiateSystemShutdownW
。我个人一直使用ANSI变量,因此我不知道如果使用*W变量,是否需要手动指定Unicode编码

public interface JNAApiInterface extends StdCallLibrary {

    JNAApiInterface INSTANCE = (JNAApiInterface) Native.loadLibrary("Advapi32", JNAApiInterface.class);

    public boolean InitiateSystemShutdownA(String machine, String message, short timeout, boolean forceAppClose, boolean rebootAfterShutdown);
}
还请注意,重新启动计算机需要某些特权。摘自:

要关闭本地计算机,调用线程必须具有SE_SHUTDOWN_NAME权限。要关闭远程计算机,调用线程必须在远程计算机上具有SE_remote_SHUTDOWN_NAME权限。默认情况下,用户可以在其登录的计算机上启用SE_SHUTDOWN_NAME权限,管理员可以在远程计算机上启用SE_REMOTE_SHUTDOWN_NAME权限。有关详细信息,请参阅以特殊权限运行

失败的常见原因包括无效或无法访问的计算机名或权限不足。如果指定的计算机上已在进行关机,则返回错误\u SHUTDOWN\u IN\u PROGRESS。如果启用了快速用户切换,但没有用户登录,则会返回错误\u NOT \u READY


如果您查看文档页面的,您会注意到底部的实际函数名是
InitiateSystemShutdownW
(Unicode)和
InitiateSystemShutdownA
(ANSI)。大多数(全部?)处理字符串的WinAPI函数被定义为预处理器符号,它们解析为*A或*W结束函数,这取决于编译时是否定义了
UNICODE

示例来自:

根据要使用的编码,将函数重命名为
InitiateSystemShutdownA
InitiateSystemShutdownW
。我个人一直使用ANSI变量,因此我不知道如果使用*W变量,是否需要手动指定Unicode编码

public interface JNAApiInterface extends StdCallLibrary {

    JNAApiInterface INSTANCE = (JNAApiInterface) Native.loadLibrary("Advapi32", JNAApiInterface.class);

    public boolean InitiateSystemShutdownA(String machine, String message, short timeout, boolean forceAppClose, boolean rebootAfterShutdown);
}
还请注意,重新启动计算机需要某些特权。摘自:

要关闭本地计算机,调用线程必须具有SE_SHUTDOWN_NAME权限。要关闭远程计算机,调用线程必须在远程计算机上具有SE_remote_SHUTDOWN_NAME权限。默认情况下,用户可以在其登录的计算机上启用SE_SHUTDOWN_NAME权限,管理员可以在远程计算机上启用SE_REMOTE_SHUTDOWN_NAME权限。有关详细信息,请参阅以特殊权限运行

失败的常见原因包括无效或无法访问的计算机名或权限不足。如果指定的计算机上已在进行关机,则返回错误\u SHUTDOWN\u IN\u PROGRESS。如果启用了快速用户切换,但没有用户登录,则会返回错误\u NOT \u READY


如果将函数更改为“InitiateSystemShutdownA”或“InitiateSystemShutdownW”后仍然不起作用,则可能是权限问题,正如@cubrr所建议的那样

尝试添加以下内容:

    HANDLEByReference hToken = new HANDLEByReference();
    LUID luid = new LUID();
    Advapi32.INSTANCE.OpenProcessToken(Kernel32.INSTANCE.GetCurrentProcess(), WinNT.TOKEN_ADJUST_PRIVILEGES, hToken);
    Advapi32.INSTANCE.LookupPrivilegeValue("", WinNT.SE_SHUTDOWN_NAME, luid);
    TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES(1);
    tp.Privileges[0] = new LUID_AND_ATTRIBUTES(luid, new DWORD(WinNT.SE_PRIVILEGE_ENABLED));
    Advapi32.INSTANCE.AdjustTokenPrivileges(hToken.getValue(), false, tp, tp.size(), null, new IntByReference());
在调用函数之前:

jnaLib.InitiateSystemShutdown(null, null, (short)0, true, true);

如果将函数更改为“InitiateSystemShutdownA”或“InitiateSystemShutdownW”后仍然不起作用,则可能是权限问题,正如@cubrr所建议的那样

尝试添加以下内容:

    HANDLEByReference hToken = new HANDLEByReference();
    LUID luid = new LUID();
    Advapi32.INSTANCE.OpenProcessToken(Kernel32.INSTANCE.GetCurrentProcess(), WinNT.TOKEN_ADJUST_PRIVILEGES, hToken);
    Advapi32.INSTANCE.LookupPrivilegeValue("", WinNT.SE_SHUTDOWN_NAME, luid);
    TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES(1);
    tp.Privileges[0] = new LUID_AND_ATTRIBUTES(luid, new DWORD(WinNT.SE_PRIVILEGE_ENABLED));
    Advapi32.INSTANCE.AdjustTokenPrivileges(hToken.getValue(), false, tp, tp.size(), null, new IntByReference());
在调用函数之前:

jnaLib.InitiateSystemShutdown(null, null, (short)0, true, true);

将方法调用更改为“InitiateSystemShutdownExW”可以工作,但返回false而不会重新启动系统。将方法调用更改为“InitiateSystemShutdownExW”可以工作,但返回false而不会重新启动系统。谢谢,我已将函数更改为“InitiateSystemShutdownExW”,现在它不会引发异常,但返回“false”不要重启系统。我不知道它为什么不工作。@rjaraba调用后,
Native.getLastError()
的值是多少?请注意我最近添加的内容。@rjaraba请尝试搜索。“Native.getLastError”的结果是5:错误代码5表示“访问被拒绝”。您应该检查用户的访问权限。错误\u访问\u拒绝5(0x5)访问被拒绝。谢谢,我已将我的函数更改为“InitiateSystemShutdownA”,现在它不会引发异常,但返回“false”,并且不会重新启动系统。我不知道它为什么不工作。@rjaraba调用后,
Native.getLastError()
的值是多少?请注意我最近添加的内容。@rjaraba请尝试搜索。“Native.getLastError”的结果是5:错误代码5表示“访问被拒绝”。您应该检查用户的访问权限。错误\u访问\u拒绝5(0x5)访问被拒绝。@rjaraba确保通过单击复选框接受此答案:)@rjaraba确保通过单击复选框接受此答案:)