通过UAC提升ProcessBuilder流程?

我正在尝试运行外部可执行文件,但显然它需要提升。 代码是这样的,从使用ProcessBuilder的示例修改(因此带有一个参数的数组):

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(); } } 

它在运行时返回:

 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#中,你可以通过这样做来请求提升,(从这个线程可以看出):

 startInfo.Verb = "runas"; 

但是,我没有看到与ProcessBuilder类似的东西。 另一种方法是在目标系统上安装Elevation Tools ,并使用ProcessBuilder调用“elevate”提示符。 但是,我宁愿不强迫使用我的程序的人也安装这些高程工具。

还有另一种方式吗?

使用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 + ")"); } } } 

Prunge的回答对我来说很好。但在做了一些研究之后,我发现了另一种使用vb脚本和批处理文件的方法。我更喜欢这种方法,因为使用vb-script不会导致每次都出现黑色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. 现在创建一个具有管理员权限的vb脚本,最后添加脚本以打开mysql.bat文件。

最后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 
  1. 现在将此文件另存为mysql_start.vbs
  2. 最后从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); }