运行时提升Java应用程序 [英] Elevate Java application while running

查看:134
本文介绍了运行时提升Java应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的软件突然出现了令人讨厌的问题。我正在制作一个与另一个现有软件(游戏)交互的程序。用户报告说他以管理员权限运行游戏,在这种情况下,我的程序停止为他工作。

A nasty problem popped out with my software. I am making a program that interacts with another existing software (a game). User has reported that he runs the game with administrator privileges and under that circumstances, my program stops working for him.

简短的调查显示有些人确实需要运行游戏在管理员帐户下,有些则没有。如果我的程序能够检测到这一点并且警告用户游戏是否在管理员帐户下运行会很棒:

Short investigation revealed that some people really need to run the game under administrator account and some don't. It would be great if my program would be able to detect this and warn user if the game is running under administrator account:

如果用户点击提升,我想要求提升窗口 java.exe 运行我的 jar 文件并调用典型的UAC对话框。

If the user clicks "Elevate", I'd like to ask windows to elevate the java.exe running my jar file and invoke the typical UAC dialog.



显然,这一次是问题不会是关于java更新程序但是JRE

我的问题是:这可能吗? Windows可以提升我的 java.exe 实例的权限吗? java有办法吗?或者我可以使用命令行命令吗?

My question is: Is this possible? Can windows elevate my java.exe instance's privilege? Does java have a way to do it? Or can I use command line command?

我想避免重新启动程序(虽然它可能不会那么大)。

I want to avoid restarting the program (though it wouldn't probably be such a big deal).

编辑:
如果您查看评论,您会发现无法避免重启应用程序 - 进程只能启动提升,而不是升高。不幸的是,这有点改变了这个问题。基本上,现在听起来更像是:如何使用管理员权限重启我的应用程序?。当然,除非有两个 java.exe 共享一个jar ... ...

If you look in the comments, you'll see that there's no avoiding the restart of an application - process can only start elevated, not become elevated. This kinda shifts the question, unfortunately. Basically, it now sounds more like: "How to restart my application with admin rights?". Unless, of course, there's a trick like two java.exe sharing one jar...

推荐答案

正如评论中所指出的那样,遗憾的是Java(或任何其他进程)在运行时无法提升。虽然在JWM的情况下,理论上可以将整个程序上下文从普通用户java.exe移动到提升的一个,我认为这是不可能的。我希望有一天会有人来告诉我我错了。

As has been pointed in comments, sadly the Java (or any other process) cannot be elevated while running. While in the case of JWM, it could be theoretically possible to move whole program context from normal user java.exe to elevated one, I don't think it's possible. I hope some day someone will come and tell me I'm wrong.

令人惊讶的是,即使重新启动,这也是一个棘手的任务我花了一段时间才弄清楚。

Surprisingly, even with restart in place, this was a tricky task that took me a while to figure out.

首先,我们如何完全运行从命令行升级的程序? 有答案,你可以看到它并不简单。但是我们可以将它分解为这个VBS脚本:

First, how do we exactly run a program elevated from command line? There's an answer and you can see it's not simple. But we can break it to this VBS script:

Set UAC = CreateObject("Shell.Application") 
UAC.ShellExecute "program name", "command line parameters", "working directory", "runas", 1 



<很快,事实证明我们从VBS脚本运行java.exe没有任何成功。最后,我决定运行一个帮助程序批处理文件。最后,这里(在上一个链接中回答问题)我们有一套完整的两个脚本,它们真正运行给定的 .jar 文件已提升。这是改进版本,允许通过拖放Jar文件进行快速测试:

Soon, it also turns out that we won't have any success running java.exe from VBS script. In the end, I decided to run a helper batch file. Finally, here (answer to question in the last link) we have a complete set of two scripts which really run the given .jar file elevated. Here's improved version that allows quick testing by drag'n'dropping the Jar file on it:

' Require first command line parameter
if WScript.Arguments.Count = 0 then
  MsgBox("Jar file name required.")
  WScript.Quit 1
end if

' Get the script location, the directorry where it's running
Set objShell = CreateObject("Wscript.Shell")

strPath = Wscript.ScriptFullName

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objFile = objFSO.GetFile(strPath)
strFolder = objFSO.GetParentFolderName(objFile) 
'MsgBox(strFolder)

' Create the object that serves as runnable something
Set UAC = CreateObject("Shell.Application") 
' Args:
'   path to executable to run
'   command line parameters - first parameter of this file, which is the jar file name
'   working directory (this doesn't work but I use it nevertheless)
'   runas command which invokes elevation
'   0 means do not show the window. Normally, you show the window, but not this console window
'     which just blinks and disappears anyway
UAC.ShellExecute "run-normally.bat", WScript.Arguments(0), strFolder, "runas", 0 

WScript.Quit 0



Java部分



Java部分更直接。我们需要做的是打开新进程并在其中执行准备好的脚本。

The Java part

Java part is more straightforward. What we need to do is to open new process and execute the prepared scripts in it.

   /**
    * Start this very jar file elevated on Windows. It is strongly recommended to close any existing IO
    * before calling this method and avoid writing anything more to files. The new instance of this same
    * program will be started and simultaneous write/write or read/write would cause errors.
    * @throws FileNotFoundException if the helper vbs script was not found
    * @throws IOException if there was another failure inboking VBS script
    */
   public void StartWithAdminRights() throws FileNotFoundException, IOException {
     //The path to the helper script. This scripts takes 1 argument which is a Jar file full path
     File runAsAdmin = new File("run-as-admin.vbs");;
     //Our 
     String jarPath;

     //System.out.println("Current relative path is: " + s);

     try {
       jarPath = "\""+new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getAbsolutePath()+"\"";
     } catch (URISyntaxException ex) {
       throw new FileNotFoundException("Could not fetch the path to the current jar file. Got this URISyntax exception:"+ex);
     }
     //If the jar path was created but doesn't contain .jar, we're (most likely) not running from jar
     //typically this happens when running the program from IDE
     //These 4 lines just serve as a fallback in testing, should be deleted in production
     //code and replaced with another FileNotFoundException
     if(!jarPath.contains(".jar")) {
       Path currentRelativePath = Paths.get("");
       jarPath = "\""+currentRelativePath.toAbsolutePath().toString()+"\\AutoClient.jar\"";
     }
     //Now we check if the path to vbs script exists, if it does we execute it
     if(runAsAdmin.exists()) {
       String command = "cscript \""+runAsAdmin.getAbsolutePath()+"\" "+jarPath;
       System.out.println("Executing '"+command+"'");
       //Note that .exec is asynchronous
       //After it starts, you must terminate your program ASAP, or you'll have 2 instances running
       Runtime.getRuntime().exec(command);

     }
     else
       throw new FileNotFoundException("The VBSScript used for elevation not found at "+runAsAdmin.getAbsolutePath());
   }

这篇关于运行时提升Java应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆