5

正如标题所说,我想知道用 Java (并且只有 java)编写的程序是否有可能以管理员权限重新启动自己(最好是 .jar),以本机 Windows UAC 的方式显示(为了使它对用户来说更值得信赖),我做了功课,发现可以使用 c++ 和 java 之间的桥梁来实现这一点,但我真的很想把它作为一个纯 java 项目来做。

PS:在这个结果不可能的远程情况下,有人可以告诉我使用另一种语言的“简单”方法(我的意思是,我找到了教程,但它们对于我认为不应该的东西来说太复杂了这么复杂)。

P.S2:如果可以做到这一点,它是否可以在其他平台(OS X,Linux)上工作

4

5 回答 5

9

它不能在纯java中完成。

最好的办法是将其写入文件:

@echo Set objShell = CreateObject("Shell.Application") > %temp%\sudo.tmp.vbs
@echo args = Right("%*", (Len("%*") - Len("%1"))) >> %temp%\sudo.tmp.vbs
@echo objShell.ShellExecute "%1", args, "", "runas" >> %temp%\sudo.tmp.vbs
@cscript %temp%\sudo.tmp.vbs

并将其保存something.bat在 Windows临时目录中(因为我们可以访问它)。

Runtime然后,您将使用or从您的应用程序中执行此操作,ProcessBuilder然后退出您的应用程序 ( System.exit(0);)。

您应该向您的应用程序添加一个立即启动检查,检查程序是否有提升,如果没有重新运行批处理并退出,它是否已继续。

这是我做的一个例子(这必须在编译为 Jar 时运行,否则它将不起作用):

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JOptionPane;

/**
 *
 * @author David
 */
public class UacTest {

    public static String jarName = "UacTest.jar", batName = "elevate.bat";

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        if (checkForUac()) {//uac is on
            JOptionPane.showMessageDialog(null, "I am not elevated");
            //attempt elevation
            new UacTest().elevate();
            System.exit(0);
        } else {//uac is not on
            //if we get here we are elevated
            JOptionPane.showMessageDialog(null, "I am elevated");
        }

    }

    private static boolean checkForUac() {
        File dummyFile = new File("c:/aaa.txt");
        dummyFile.deleteOnExit();

        try {
            //attempt to craete file in c:/
            try (FileWriter fw = new FileWriter(dummyFile, true)) {
            }
        } catch (IOException ex) {//we cannot UAC muts be on
            //ex.printStackTrace();
            return true;
        }
        return false;
    }

    private void elevate() {
        //create batch file in temporary directory as we have access to it regardless of UAC on or off
        File file = new File(System.getProperty("java.io.tmpdir") + "/" + batName);
        file.deleteOnExit();

        createBatchFile(file);

        runBatchFile();

    }

    private String getJarLocation() {
        return getClass().getProtectionDomain().getCodeSource().getLocation().getPath().substring(1);
    }

    private void runBatchFile() {
        //JOptionPane.showMessageDialog(null, getJarLocation());

        Runtime runtime = Runtime.getRuntime();
        String[] cmd = new String[]{"cmd.exe", "/C",
            System.getProperty("java.io.tmpdir") + "/" + batName + " java -jar " + getJarLocation()};
        try {
            Process proc = runtime.exec(cmd);
            //proc.waitFor();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void createBatchFile(File file) {
        try {
            try (FileWriter fw = new FileWriter(file, true)) {
                fw.write(
                        "@echo Set objShell = CreateObject(\"Shell.Application\") > %temp%\\sudo.tmp.vbs\r\n"
                        + "@echo args = Right(\"%*\", (Len(\"%*\") - Len(\"%1\"))) >> %temp%\\sudo.tmp.vbs\r\n"
                        + "@echo objShell.ShellExecute \"%1\", args, \"\", \"runas\" >> %temp%\\sudo.tmp.vbs\r\n"
                        + "@cscript %temp%\\sudo.tmp.vbs\r\n"
                        + "del /f %temp%\\sudo.tmp.vbs\r\n");
            }
        } catch (IOException ex) {
            //ex.printStackTrace();
        }
    }
}
于 2012-11-08T13:47:54.337 回答
1

使用批处理文件和runas命令。

于 2012-11-08T13:45:06.633 回答
0

我怀疑“只有Java”。充其量你必须有一个围绕 MSFT 模块的 JNI 包装器。除非仅使用“仅 Java”来调用 exe,否则ProcessBuilder您启动用户控制台的代码将只是 Java,而不是它调用的代码。IOW,Win 不附带 Java API

于 2012-11-08T13:48:03.590 回答
0

要重新启动提升的应用程序,您必须从 Windows API调用ShellExecute或运行并使用动词。ShellExecuteExrunas

您可以通过JNA 库在纯 Java 中使用这些 API 。

要重新启动自己,您必须知道java.exeor的完整路径javaw.exe、命令行参数(类路径,如果有的话,以及 jar 的路径)。显然,您可以使用 Windows API 获取此信息。


远程案例是什么意思?
您不能以这种方式启动远程提升进程。

您可以重新启动从网络共享提升的应用程序。但它不适用于映射驱动器:提升后无法访问用户的映射驱动器。


不,这不能在其他平台上运行。UAC 是 Windows 功能。它在某些方面类似于sudoLinux,因此对于 Linux,您可以使用sudo $pathtojava/java.exe <yourparameters>. 但是,如果您的应用程序不是从控制台启动的,这将无法正常工作。窗口管理器通常具有在 GUI 对话框中提示输入密码的包装器。

于 2012-11-11T10:05:57.637 回答
0

只需使用 Hackaprofaw (v29) 即可。它也于 2002 年发布,并于 1997 年开始开发。在 2021 年,它的版本为 29.10.7,但是-

if raw ram = 0
 disable "featureII" program = "JAVA(math = any)"
run on "Hackaprofaw (math = v29(x))
when "featureII" disabled
 end
于 2021-09-01T19:44:48.773 回答