我有一个前端应用程序(在PowerBuilder中,但这并不重要),它调用了一个用Java开发并与launch4j打包在一起的帮助应用程序。
应用程序的最终用户可以自由配置进入前端的路径,其中某些文件将由前端或后端生成。
我注意到在启动了UAC的Windows Vista或Windows7上,如果用户(没有管理员权限)已将输出配置为C:\
,则生成的文件将以静默方式虚拟化为{{1} }目录。
但是当进程使java应用程序在同一c:\Users\user_name\AppData\Local\VirtualStore\
中创建一些文件(通过FileOutputStream
)时,java会因“拒绝访问”异常而失败,这可能与以下事实相符用户无法访问驱动器根目录,但不能访问其他应用程序已虚拟化的事实。任务管理器确认一个是虚拟化而不是另一个。
我发现that other SO question提供了一些线索但不是我的情况的答案,因为两个应用程序在32系统上都是32位,并且两者都没有涉及清单。
有没有办法让java的行为像PB应用程序(即虚拟化 - 客户请求)?当然,更好的解决方案是检查路径是否可访问,并通知用户是否存在。
修改 在查看java.exe二进制文件时,我注意到它包含一个表明的清单(但我不熟悉)
C:\
也许这就是问题的答案:java不是按设计虚拟化的? 编辑:我确实明白清单机制会禁用虚拟化。
EPILOGUE:感谢您的解释,您的论据有助于改变客户的要求。现在我们承认,处理缺少在某些文件夹上写入的权限比让windows在以太网中某处虚拟化文件更好:o)
答案 0 :(得分:3)
也许这就是问题的答案: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代码中自己实现虚拟化 - 并检测对根驱动器,Program Files等的访问,并用c:\ Users \ user_name \ AppData \ Local \ VirtualStore \ path替换它们。
可能有一种方法可以为UAC感知应用程序重新启用虚拟化,而不会破解exe,但我找不到它。
最终替代方案可能类似于exe4j来生成新的java运行器。我相信exe4j允许您配置生成的可执行文件是否可以识别UAC。在您的情况下,您可能希望创建一个不支持UAC的exe(没有清单)。然后使用新的exe而不是java.exe。见http://www.ej-technologies.com/products/exe4j/overview.html
答案 1 :(得分:2)
更好的方法是在power basic app中禁用虚拟化。
您可以这样做,即在清单中添加一个部分,以表明该过程具有vista意识。 您可以在MSDN中找到更多信息。
答案 2 :(得分:2)
您在<requestedPrivileges>
的应用程序清单中找到了java.exe
元素。这是使Java UAC意识到的原因。由于Java 显式请求标准用户的权限,因此虚拟化已关闭。
作为already noted,虚拟化可以使旧应用程序尽可能无缝地工作。因此,良好的解决方案是通过向其添加适当的清单,使Windows为您的PowerBuilder前端应用程序关闭虚拟化。
另一个建议是在Java中处理Access Denied
错误并尝试使用虚拟化位置。但这是一个解决方法,而不是一个真正的解决方案:你不应该依赖虚拟化。
要检查路径是否可访问,除非两个部件位于同一侧,否则很棘手。如果一个是虚拟化而另一个没有,你将面临你现在看到的同样问题。我的意思是,如果你在PB中实现检查是否可以在指定的文件夹中创建文件,那么你将获得成功,因为系统会虚拟化调用。与此同时,后端将失败。