3

I have an front end application (in PowerBuilder but that is not important) that is calling a helper application developed in Java and packaged with launch4j.

The end user of the application has the possibility to freely configure a path into the front end where some files will be generated by either the front-end or the backend.

I notice that on a Windows Vista or a Windows7 with UAC activated, if the user (that has no administrator privileges) has configured the output to C:\, the generated files are silently virtualized into the c:\Users\user_name\AppData\Local\VirtualStore\ directory.

But when the process makes the java application create some files (via a FileOutputStream) in the same C:\, the java fails on an "Access denied" exception that could be coherent to the fact that the drive root is not accessible to users, but not to the fact that the other application is virtualized. Task manager confirms that one is virtualized and not the other.

I have found that other SO question that provides some clues but not an answser to my case, as both applications are 32 bit on a 32 system and no manifest are involved for both.

Is there a way to let the java behave like the PB application (that is to be virtualized - it a customer request)? Of course a better solution would be to check if the path is accessible and to notify the user if it is not.

EDIT: While looking at the java.exe binary, I noticed that it includes a manifest that states (but I am not familiar with that)

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

Maybe it is the answer of the question : java is not virtualized by design? EDIT: I did understand that the manifest mechanism disables the virtualization.

EPILOGUE: thanks for your explanations and your arguments helped to change the customer request. Now it is acknowledged that handling the lack of privileges to write on some folders is better than letting windows virtualize the files somewhere in the ether :o)

Community
  • 1
  • 1
Seki
  • 11,135
  • 7
  • 46
  • 70

3 Answers3

4

Maybe it is the answer of the question : java is not virtualized by design?

I think a better way to think of it is Java is UAC aware - as you can tell by the manifest you found. Since Java is UAC aware, Windows determines that Java knows what it is doing. Since the manifest does not request admin rights and is being run by a standard user, Windows properly disallows writes to protected directories (C:\) and you get an access denied error.

Note the warning at http://msdn.microsoft.com/en-us/library/windows/desktop/bb756960.aspx

Virtualization is implemented to improve application compatibility problems for applications running as a standard user on Windows Vista. Developers must not rely on virtualization being present in subsequent versions of Windows.

If your customer really thinks virtualization is a good thing, you need to give Java a lobotomy and find some way to remove that manifest. Then Windows will think Java does not know what it is doing and will turn virtualization back on. Or implement virtualization yourself in Java code - and detect accesses to the root drive, Program Files etc. and replace them with the c:\Users\user_name\AppData\Local\VirtualStore\ path.

There may be a way to turn virtualization back on for UAC aware applications, without hacking the exe, but I could not find it.

A final alternative might be something like exe4j to generate a new java runner. I believe exe4j lets you configure whether the resulting executable will be UAC aware. In your case you would want to create an exe that is not UAC aware (no manifest). Then use your new exe instead of java.exe. See http://www.ej-technologies.com/products/exe4j/overview.html

Guido Simone
  • 7,912
  • 2
  • 19
  • 21
2

A better way to handle this is disable virtualization in the power basic app.

You can do this be adding a section to the manifest to say that the process is vista aware. You can find more information in MSDN.

Deanna
  • 23,876
  • 7
  • 71
  • 156
  • That is what has been decided. By disabling virtualization via an internal manifest, we have a consistent behavior of both fornt and back ends. – Seki Oct 02 '12 at 11:22
2

You found <requestedPrivileges> element in the application manifest of java.exe. This is what makes Java UAC-aware. Since Java explicitly requests privileges of standard user, virtualization is turned off.

As already noted, Virtualization is there to make old applications work as seamlessly as possible. So the good solution would be to make Windows turn virtualization off for your PowerBuilder front-end application by adding appropriate manifest to it.

Another suggestion would be to handle Access Denied error in Java and try the Virtualized location instead. But that's rather a workaround than a real fix: you should not rely on virtualization.


To check whether the path is accessible or not is tricky unless both parts are on the same side. If one is virtualized and the other is not, you'll face the same issue you see now. I mean, if you implement a check in PB whether it can create a file in the specified folder, you'll get success because the system would virtualize the call. At the same time, back-end will fail.

Community
  • 1
  • 1
Alexey Ivanov
  • 11,541
  • 4
  • 39
  • 68