UAC和java创建的文件的文件虚拟化



我有一个前端应用程序(在PowerBuilder中,但这并不重要),它正在调用用Java开发并与launch4j打包的助手应用程序。

应用程序的最终用户可以自由配置进入前端的路径,其中一些文件将由前端或后端生成。

我注意到,在激活了UAC的Windows Vista或Windows7上,如果用户(没有管理员权限)已将输出配置为C:,则生成的文件将以静默方式虚拟化到c:Usersuser_nameAppDataLocalVirtualStore目录中。

但是,当该过程使java应用程序在同一个C:中创建一些文件(通过FileOutputStream)时,java会出现"拒绝访问"异常,这可能与用户无法访问驱动器根目录这一事实有关,但与其他应用程序已虚拟化这一事实无关。任务管理器确认其中一个是虚拟化的,而不是另一个。

我发现了另一个SO问题,它为我的案例提供了一些线索,但不是答案,因为这两个应用程序都是32位系统上的32位应用程序,并且两者都不涉及清单。

有没有一种方法可以让java表现得像PB应用程序(要虚拟化——这是客户的请求)?当然,更好的解决方案是检查路径是否可访问,如果不可访问,则通知用户。

EDIT:在查看java.exe二进制文件时,我注意到它包含一个声明(但我不熟悉)的清单

<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="asInvoker"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>

也许这就是问题的答案:java不是通过设计虚拟化的编辑:我确实知道清单机制会禁用虚拟化。

EPILOGUE:感谢您的解释和您的论点帮助更改了客户的请求。现在,人们承认,处理某些文件夹上缺乏写入权限的问题比让windows虚拟化以太中的某个文件要好:o)

也许这就是问题的答案:java不是通过设计虚拟化的?

我认为一种更好的方式是Java是UAC感知的——正如你从你发现的清单中可以看出的那样。由于Java具有UAC意识,Windows确定Java知道自己在做什么。由于清单不请求管理权限,并且由标准用户运行,因此Windows正确地禁止写入受保护的目录(C:\),并且会出现拒绝访问错误。

注意上的警告http://msdn.microsoft.com/en-us/library/windows/desktop/bb756960.aspx

实施虚拟化是为了提高应用程序兼容性在Windows Vista上作为标准用户运行的应用程序的问题。开发人员决不能依赖于虚拟化Windows版本。

如果您的客户真的认为虚拟化是一件好事,那么您需要对Java进行脑叶切除术,并找到一些方法来删除该清单。然后,Windows会认为Java不知道自己在做什么,并将重新启用虚拟化。或者,在Java代码中自己实现虚拟化,并检测对根驱动器、程序文件等的访问,并将其替换为c:\Users\user_name\AppData\Local\VirtualStore\路径。

可能有一种方法可以在不破解exe的情况下为支持UAC的应用程序重新打开虚拟化,但我找不到它

最后一种选择可能是类似于exe4j的东西来生成一个新的java运行程序。我相信exe4j可以让您配置生成的可执行文件是否具有UAC意识。在您的情况下,您可能希望创建一个不支持UAC的exe(没有清单)。然后使用新的exe而不是java.exe。请参阅http://www.ej-technologies.com/products/exe4j/overview.html

处理此问题的更好方法是在power-based应用程序中禁用虚拟化。

您可以通过在清单中添加一个部分来说明该过程是可预见的。您可以在MSDN中找到更多信息。

您在java.exe的应用程序清单中找到了<requestedPrivileges>元素。这就是Java UAC所意识到的。由于Java显式地请求标准用户的权限,因此虚拟化被关闭

如前所述,虚拟化旨在使旧应用程序尽可能无缝地工作。因此,好的解决方案是通过向PowerBuilder前端应用程序添加适当的清单来关闭Windows的虚拟化

另一个建议是在Java中处理Access Denied错误,并尝试虚拟化位置。但这是一种变通方法,而不是真正的解决方案:您不应该依赖虚拟化


检查路径是否可访问是很棘手的,除非两个部分都在同一侧。如果一个是虚拟化的,而另一个不是,那么您将面临与现在相同的问题。我的意思是,如果你在PB中实现一个检查,它是否可以在指定的文件夹中创建一个文件,你就会成功,因为系统会虚拟化调用。同时,后端将出现故障。

最新更新