2012-06-14 37 views
12

Tôi đang cố chạy một tệp thực thi bên ngoài, nhưng dường như nó cần độ cao. Mã này là thế này, biến đổi từ một ví dụ của việc sử dụng ProcessBuilder (do đó mảng với một đối số):Nâng cao quy trình ProcessBuilder qua UAC?

public static void main(String[] args) throws IOException { 
     File demo = new File("C:\\xyzwsdemo"); 
     if(!demo.exists()) demo.mkdirs(); 
     String[] command = {"C:\\fakepath\\bsdiff4.3-win32\\bspatch.exe"}; 
     ProcessBuilder pb = new ProcessBuilder(command); 
     Process process = pb.start(); 
     InputStream is = process.getInputStream(); 
     InputStreamReader isr = new InputStreamReader(is); 
     BufferedReader br = new BufferedReader(isr); 
     String line; 
     System.out.printf("Output of running %s is:\n", Arrays.toString(command)); 
     while ((line = br.readLine()) != null) { 
      System.out.println(line); 
     } 
     try { 
      int exitValue = process.waitFor(); 
      System.out.println("\n\nExit Value is " + exitValue); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

Nó trả về này khi chạy:

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 

tôi đã thực hiện một số trình duyệt xung quanh, và biết rằng trong C#, bạn có thể yêu cầu độ cao bằng cách làm này, (khi nhìn từ this thread):

startInfo.Verb = "runas"; 

Tuy nhiên, tôi không thấy bất cứ điều gì như thế với ProcessBuilder. Một phương pháp khác là cài đặt Elevation Tools trên hệ thống đích và gọi lời nhắc "nâng cao" bằng ProcessBuilder. Tuy nhiên, tôi không muốn ép buộc những người sử dụng chương trình của tôi cũng cài đặt những công cụ nâng cao đó.

Có cách nào khác không?

Trả lời

12

Điều này không thể thực hiện được với ProcessBuilder, bạn sẽ cần gọi Windows API.

Tôi đã sử dụng JNA để đạt được điều này với mã tương tự như sau:

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:

câu trả lời
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

Cảm ơn bạn đã trả lời nhanh chóng! Tôi sẽ kiểm tra điều này trong phạm vi đơn đăng ký của tôi và cho bạn biết cách hoạt động của nó. –

+0

Chương trình nâng cao hoạt động tốt. Cảm ơn nhiều! –

+0

Có cách nào để tránh cửa sổ xác nhận bật lên (chạy dưới dạng quản trị viên) bằng cách sử dụng mã nào đó trong mã không? – Affi

0

Prunge 's hoạt động tốt đối với tôi. Nhưng sau khi nghiên cứu thêm một chút, tôi đã tìm ra cách tiếp cận khác bằng cách sử dụng tập lệnh vb và tệp batch.I thích thứ là cách tiếp cận vì sử dụng vb-script không gây ra cửa sổ cmd đen để bật lên mỗi khi tôi mở ứng dụng của mình.

  1. Tạo tệp dơi thông thường để mở tệp thi hành bên ngoài. Tôi sẽ mở một máy chủ tập tin thực thi MySQL

    @echo off 
    cd "C:\Program Files (x86)\MySQL\MySQL Server 5.6\bin" 
    :: Title not needed: 
    start /MIN mysqld.exe 
    exit 
    
  2. Lưu nó như mysql.bat

  3. Bây giờ tạo ra một kịch bản vb với đặc quyền quản trị và cuối cùng thêm kịch bản để mở file mysql.bat .

Khi kết thúc CreateObject ("Wscript.Shell"). Chạy tệp 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 
  1. Giờ hãy lưu file này như mysql_start.vbs
  2. Cuối cùng Chạy kịch bản vb từ java.

Thats nó

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); 
     } 
Các vấn đề liên quan