尝试在%AppData%中执行.exe时出现访问被拒绝的错误。

7
我正在尝试在我的Java应用程序中使用RemoveDrive.exe,可以在这里找到。我已经将其放在JAR文件中,并使用以下代码将其提取到临时文件中,但是当我尝试运行它时,我会收到一个IOException,其中写着CreateProcess error=5, Access is denied。然而,该程序通常不需要管理员权限。有什么想法可以解决这个问题吗?
            File RDexe = File.createTempFile("rmvd", ".exe");

            InputStream exesrc = (InputStream) GraphicUI.class.getResource("RemoveDrive.exe").openStream();
            FileOutputStream out = new FileOutputStream(RDexe);

            byte[] temp = new byte[1024];
            int rc;

            while((rc = exesrc.read(temp)) > 0)
                out.write(temp, 0, rc);

            exesrc.close();
            out.close();

            RDexe.deleteOnExit();

            // run executable
            Runtime runtime = Runtime.getRuntime();
            System.out.println(RDexe.getPath() + " " + "F:\\" + " -b -s");
            Process proc = runtime.exec(RDexe.getPath() + " " + "F:\\" + " -b");
            InputStream is = proc.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));

            String line; boolean ejected = false;
            while((line = reader.readLine()) != null)
                if(line.equalsIgnoreCase("failed")) ejected = false;
                else if(line.equalsIgnoreCase("success")) ejected = true;

            reader.close();
            is.close();

更新:如果我启用内置的管理员帐户(net user administrator /active:yes),从那里运行一切都很好。但是,如果我在标准帐户中右键单击并以管理员身份运行,则仍会出现错误,并且UAC甚至不会请求权限。

编辑:由于赏金即将结束,请参阅我的SuperUser问题,这已经帮助我解决了这个问题... 我很快就会授予赏金并接受答案。


也许可以查看https://dev59.com/I2w15IYBdhLWcg3wWqV0。 - demongolem
@demongolem 我知道那个问题的信息。但它并不能帮助我解决我的问题。 - Andy
5个回答

4

也许这不是你遇到的问题,但一些反病毒程序会阻止在临时文件夹中运行可执行文件或脚本。尝试将其放在用户目录中,而不是创建临时文件:

File rdExe = new File(System.getProperty("user.home") + "/.yourProgramName/rmvd.exe");
rdExe.getParentFile().mkdirs();

谢谢你的回答。在我的情况下,这不是问题(因为我已经解决了它),但我可以将此位置用作临时文件的故障保护。确实是将其放置的最佳位置吗? - Andy
抱歉,在发布我的答案后才看到你的解决方案。用户应始终可以访问此文件夹。只有在您计划清理自己的代码时才可以这样做 - 而您的代码正在这样做。不过,我可能会将其放入“隐藏”文件夹中(已更新答案)。 - Lunchbox
谢谢更新,这很有道理。那我就把主目录设为安全的临时目录吧。 - Andy

2
  1. 我不是JAVA用户,但这不是32位和64位的问题吗?

    在64位Windows上,错误代码5通常意味着可执行文件不兼容64位。有时即使可执行文件只需要访问一些(旧的win)系统目录,这些目录也不存在了。为了证明这一点,请尝试在命令行中使用您的可执行文件。如果您能够在那里让它工作,那么就是另一个问题了。如果不能,请找到适用于您的操作系统的可执行文件。

  2. 另一个可能性是文件必须实际存在于某个驱动器上。

    您写道,您将其作为临时文件。对于JAVA来说,不确定这意味着什么。如果只是将其复制到某个文件中并在使用后删除,则可以正常使用,但如果它只存在于内存中,则可能会出现问题,如果可执行文件需要访问自身,则可能会出现问题。为了证明这一点,请将文件复制到某个已知位置,然后从那里运行它(在JAVA中)。如果它可以正常工作,那么您需要在执行之前和之后将可执行文件从JAVA复制并删除到物理磁盘介质或其他位置。

  3. 另一个可能性是错误代码5来自JAVA环境而不是操作系统

    在这种情况下,我不知道它的含义(不是JAVA用户)


感谢您的回答。我以为您已经解决了第一个问题,但似乎不是这样。似乎我无法在Temp目录中执行任何内容,包括已经存在的可执行文件,即使我右键单击并按“以管理员身份运行”,所以这更像是一个与操作系统相关的问题。不过,对于深入的回答,还是要点个赞! :) - Andy

2

提醒一下,还有另一种运行文件的方法,您考虑过使用Java Desktop对象吗?:http://docs.oracle.com/javase/6/docs/api/java/awt/Desktop.html

在需要通过Java程序运行程序时,我发现它非常有用。像这样的东西可能适合您:

Desktop.getDesktop().open(new File("enter path and name of the file"));

希望您会发现它有用


谢谢你的答案。我确实知道Desktop,但我从来没有考虑过用它来解决这个问题。不幸的是,这并不能解决任何问题,因为这个问题与Windows有关,而不是Java。 - Andy
啊,好的,我以为这可能会有所帮助,因为我之前尝试了你的方法,也遇到了“访问被拒绝”的错误,但是 Desktop 对象帮助我解决了这个问题。如果你还没有尝试过,我建议你试一下,毕竟没有什么损失,但你永远不知道会发生什么 :) - Ryan Hurling
我会尝试一下,但是撤销我所做的所有权更改有点麻烦,而且我很确定我仍然会得到相同的错误,因为问题与此无关。另外,我不确定是否可以使用 Desktop 对象传递命令行参数。但我肯定以后会使用它的。 - Andy
我认为您不能通过“桌面”对象传递参数,不好意思,我不知道您需要传递参数 :) - Ryan Hurling
没关系,这并不太重要。我没有明确说明需要,但是可以从我的代码中推断出来 :) - Andy

1
既然这里只是稍微提到了一下,那我就说一下,这个问题与Windows权限有关,与Java无关。
如我在原问题中链接的SuperUser问题所述,我发现我的常用账户由于某种未知原因没有拥有该文件夹的所有权 - 所以任何东西都无法执行;不仅仅是我在Java中创建的临时文件。
尽管我是管理员,但为了取得该文件夹的所有权,我必须启用内置管理员账户并授予自己所有权。自从我这样做了,一切都按预期工作了。
感谢大家的努力,我将把赏金颁给最详细并让我找到正确方向的答案。

0
你使用的是哪个版本的Windows操作系统?微软在Windows 7中显著加强了程序执行的限制。我猜测操作系统不允许您分叉(fork)一些在程序启动时未经过身份验证的内容。建议您尝试在Windows 2000或XP上运行该程序,看看是否存在相同的问题。

感谢您的回答,很抱歉回复较慢。我正在运行Windows 7,但受到您的回答启发后,我尝试在另外两台运行Windows 7的电脑上从Temp文件夹中运行可执行文件(我认为这些电脑已经按照相同的方式设置),并且该可执行文件在这些电脑上运行良好。您有什么想法是什么导致我无法在我的笔记本电脑上访问? - Andy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接