2

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

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

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

但是,当该过程使 java 应用程序FileOutputStream在同一文件中创建一些文件(通过 a )时C:\,java 会因“拒绝访问”异常而失败,这可能与用户无法访问驱动器根目录这一事实相一致,但另一个应用程序是虚拟化的。任务管理器确认一个是虚拟化的,而不是另一个。

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

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

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

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

也许这是问题的答案:java不是设计虚拟化的?编辑:我确实明白清单机制会禁用虚拟化。

结语:感谢您的解释,您的论点有助于改变客户的要求。现在人们承认,处理缺少写入某些文件夹的权限比让 Windows 虚拟化以太中某处的文件要好:o)

4

3 回答 3

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 代码中自己实现虚拟化 - 并检测对根驱动器、程序文件等的访问,并将它们替换为 c:\Users\user_name\AppData\Local\VirtualStore\ 路径。

可能有一种方法可以为 UAC 感知应用程序重新打开虚拟化,而无需破解 exe,但我找不到它。

最后的替代方法可能是像 exe4j 那样生成一个新的 java 运行器。我相信 exe4j 可以让您配置生成的可执行文件是否支持 UAC。在您的情况下,您可能希望创建一个不支持 UAC 的 exe(无清单)。然后使用您的新 exe 而不是 java.exe。请参阅http://www.ej-technologies.com/products/exe4j/overview.html

于 2012-09-25T16:29:34.063 回答
2

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

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

于 2012-09-25T15:32:14.383 回答
2

<requestedPrivileges>在 的应用程序清单中找到了元素java.exe。这就是 Java UAC 感知的原因。由于 Java明确要求标准用户的权限,因此关闭了虚拟化。

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

另一个建议是Access Denied在 Java 中处理错误并尝试使用虚拟化位置。但这与其说是真正的解决办法,不如说是一种解决方法:您不应该依赖虚拟化


除非两个部分都在同一侧,否则检查路径是否可访问是很棘手的。如果一个是虚拟化的而另一个不是,您将面临现在看到的相同问题。我的意思是,如果您在PB中执行检查它是否可以在指定的文件夹中创建文件,您将获得成功,因为系统会将调用虚拟化。同时,后端也会失败。

于 2012-09-26T06:50:25.960 回答