Java JNA调用dll Advapi32中的函数“InitiateSystemShutdown”不起作用

时间:2017-05-03 09:56:51

标签: java dll jna

我用java jna调用了Advapi32 dll的函数“InitiateSystemShutdown”,但它没有用:

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)

有人可以帮助我吗?

2 个答案:

答案 0 :(得分:1)

如果将功能更改为“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);

答案 1 :(得分:0)

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

来自Working with Strings的示例:

#ifdef UNICODE
#define SetWindowText  SetWindowTextW
#else
#define SetWindowText  SetWindowTextA
#endif 

将您的功能重命名为InitiateSystemShutdownAInitiateSystemShutdownW,具体取决于您要使用的编码。我个人总是使用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);
}

另请注意,您需要某些权限才能重新启动计算机。摘录自documentation

  

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

     

失败的常见原因包括无效或无法访问的计算机名称或权限不足。如果指定计算机上的关闭已在进行中,则会返回错误ERROR_SHUTDOWN_IN_PROGRESS。如果启用了快速用户切换但没有用户登录,则可以返回错误ERROR_NOT_READY。