2012-06-14 46 views
12

我想运行一个外部可执行文件,但显然它需要提升。该代码是这样的,从使用的ProcessBuilder(因此使用一个参数的阵列)的例子修改:通过UAC提升ProcessBuilder进程?

​​

它运行时返回该:

Exception in thread "main" java.io.IOException: Cannot run program "C:\Users\Gilliane\Downloads\bsdiff4.3-win32\bspatch.exe": CreateProcess error=740, The requested operation requires elevation 

我已经做了周围的一些浏览,和知道,在C#中,你可以通过做这个请求海拔,(从this thread看到):

startInfo.Verb = "runas"; 

不过,我不喜欢看与什么的ProcessBuilder。另一种方法是在目标系统上安装Elevation Tools,并用ProcessBuilder调用“提升”提示。但是,我宁愿不强迫使用我的程序的人也安装这些提升工具。

还有别的办法吗?

回答

12

这不能用ProcessBuilder完成,你需要调用Windows API。

我用JNA类似于下面的代码来实现这一目标:

Shell32X.java

import com.sun.jna.Native; 
import com.sun.jna.Pointer; 
import com.sun.jna.Structure; 
import com.sun.jna.WString; 
import com.sun.jna.platform.win32.Shell32; 
import com.sun.jna.platform.win32.WinDef.HINSTANCE; 
import com.sun.jna.platform.win32.WinDef.HWND; 
import com.sun.jna.platform.win32.WinNT.HANDLE; 
import com.sun.jna.platform.win32.WinReg.HKEY; 
import com.sun.jna.win32.W32APIOptions; 

public interface Shell32X extends Shell32 
{ 
    Shell32X INSTANCE = (Shell32X)Native.loadLibrary("shell32", Shell32X.class, W32APIOptions.UNICODE_OPTIONS); 

    int SW_HIDE = 0; 
    int SW_MAXIMIZE = 3; 
    int SW_MINIMIZE = 6; 
    int SW_RESTORE = 9; 
    int SW_SHOW = 5; 
    int SW_SHOWDEFAULT = 10; 
    int SW_SHOWMAXIMIZED = 3; 
    int SW_SHOWMINIMIZED = 2; 
    int SW_SHOWMINNOACTIVE = 7; 
    int SW_SHOWNA = 8; 
    int SW_SHOWNOACTIVATE = 4; 
    int SW_SHOWNORMAL = 1; 

    /** File not found. */ 
    int SE_ERR_FNF = 2; 

    /** Path not found. */ 
    int SE_ERR_PNF = 3; 

    /** Access denied. */ 
    int SE_ERR_ACCESSDENIED = 5; 

    /** Out of memory. */ 
    int SE_ERR_OOM = 8; 

    /** DLL not found. */ 
    int SE_ERR_DLLNOTFOUND = 32; 

    /** Cannot share an open file. */ 
    int SE_ERR_SHARE = 26; 



    int SEE_MASK_NOCLOSEPROCESS = 0x00000040; 


    int ShellExecute(int i, String lpVerb, String lpFile, String lpParameters, String lpDirectory, int nShow); 
    boolean ShellExecuteEx(SHELLEXECUTEINFO lpExecInfo); 



    public static class SHELLEXECUTEINFO extends Structure 
    { 
     /* 
    DWORD  cbSize; 
    ULONG  fMask; 
    HWND  hwnd; 
    LPCTSTR lpVerb; 
    LPCTSTR lpFile; 
    LPCTSTR lpParameters; 
    LPCTSTR lpDirectory; 
    int  nShow; 
    HINSTANCE hInstApp; 
    LPVOID lpIDList; 
    LPCTSTR lpClass; 
    HKEY  hkeyClass; 
    DWORD  dwHotKey; 
    union { 
    HANDLE hIcon; 
    HANDLE hMonitor; 
    } DUMMYUNIONNAME; 
    HANDLE hProcess; 
     */ 

     public int cbSize = size(); 
     public int fMask; 
     public HWND hwnd; 
     public WString lpVerb; 
     public WString lpFile; 
     public WString lpParameters; 
     public WString lpDirectory; 
     public int nShow; 
     public HINSTANCE hInstApp; 
     public Pointer lpIDList; 
     public WString lpClass; 
     public HKEY hKeyClass; 
     public int dwHotKey; 

     /* 
     * Actually: 
     * union { 
     * HANDLE hIcon; 
     * HANDLE hMonitor; 
     * } DUMMYUNIONNAME; 
     */ 
     public HANDLE hMonitor; 
     public HANDLE hProcess; 

     protected List getFieldOrder() { 
      return Arrays.asList(new String[] { 
       "cbSize", "fMask", "hwnd", "lpVerb", "lpFile", "lpParameters", 
       "lpDirectory", "nShow", "hInstApp", "lpIDList", "lpClass", 
       "hKeyClass", "dwHotKey", "hMonitor", "hProcess", 
      }); 
     } 
    } 

} 

Elevator.java

package test; 

import test.Shell32X.SHELLEXECUTEINFO; 

import com.sun.jna.WString; 
import com.sun.jna.platform.win32.Kernel32; 
import com.sun.jna.platform.win32.Kernel32Util; 

public class Elevator 
{ 
    public static void main(String... args) 
    { 
     executeAsAdministrator("c:\\windows\\system32\\notepad.exe", ""); 
    } 

    public static void executeAsAdministrator(String command, String args) 
    { 
     Shell32X.SHELLEXECUTEINFO execInfo = new Shell32X.SHELLEXECUTEINFO(); 
     execInfo.lpFile = new WString(command); 
     if (args != null) 
      execInfo.lpParameters = new WString(args); 
     execInfo.nShow = Shell32X.SW_SHOWDEFAULT; 
     execInfo.fMask = Shell32X.SEE_MASK_NOCLOSEPROCESS; 
     execInfo.lpVerb = new WString("runas"); 
     boolean result = Shell32X.INSTANCE.ShellExecuteEx(execInfo); 

     if (!result) 
     { 
      int lastError = Kernel32.INSTANCE.GetLastError(); 
      String errorMessage = Kernel32Util.formatMessageFromLastErrorCode(lastError); 
      throw new RuntimeException("Error performing elevation: " + lastError + ": " + errorMessage + " (apperror=" + execInfo.hInstApp + ")"); 
     } 
    } 
} 
+0

感谢您的快速回复!我会在我的应用程序范围内测试它,并让你知道它是如何工作的。 –

+0

海拔计划效果很好。非常感谢你! –

+0

有什么办法可以避免使用代码中的某些东西弹出(以管理员身份运行)确认? – Affi

0

Prunge的回答工作正常,我。但经过多一点研究后,我发现了另一种使用vb脚本和批处理文件的方法。我更喜欢th是因为使用VB脚本不会导致黑色cmd窗口每次弹出,当我打开我的应用程序。

  1. 创建一个普通的bat文件来打开外部可执行文件。 我要开一个MySQL服务器可执行文件

    @echo off 
    cd "C:\Program Files (x86)\MySQL\MySQL Server 5.6\bin" 
    :: Title not needed: 
    start /MIN mysqld.exe 
    exit 
    
  2. 保存为mysql.bat

  3. 现在创建具有管理员权限,并在末尾添加脚本打开mysql.bat文件中的VB脚本。

在结束CreateObject(“Wscript.Shell”)。运行运行bat文件mysql.bat。

Set WshShell = WScript.CreateObject("WScript.Shell")' 
If WScript.Arguments.length = 0 Then 
    Set ObjShell = CreateObject("Shell.Application") 
    ObjShell.ShellExecute "wscript.exe", """" & _ 
    WScript.ScriptFullName & """" &_ 
    " RunAsAdministrator", , "runas", 1 
    Wscript.Quit 
    End if 
    CreateObject("Wscript.Shell").Run "C:\Users\Shersha\Documents\NetBeansProjects\Berries\batch\mysql.bat",0,True 
  • 现在保存该文件作为mysql_start.vbs
  • 最后从Java运行VB脚本。
  • 完蛋了

    try { 
        Runtime.getRuntime().exec("wscript C:\\\\Users\\\\Shersha\\\\Documents\\\\NetBeansProjects\\\\Berries\\\\batch\\\\mysql_start.vbs"); 
         } catch (IOException e) { 
              System.out.println(e); 
              System.exit(0); 
         } 
    
    相关问题