2012-06-14 77 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); 
         } 
    
    相關問題