I have a very old application that now needs to be friendly to Windows Server 2008. It is a user application that works as singleton. It uses HKLM part of registry to read and write the configuration, and it creates log files.
Main question: how to make application work with UAC in regards to best current practice?
My initial approach is to run application non-elevated, and if configuration needs to be changed the user manually restarts it elevated, reconfigure, and restarts to non-elevated. The problem is that log file then can be created elevated as well, and then non-elevated application can not write to it. Possible workarounds:
- Don’t do anything in elevated mode that implies writing to log file. But how to detect if application is in elevated mode?
- Create log file with non-elevated privileges even in elevated mode. How?
- If access is denied when opening existing log file then try to create another log file.
- Run elevated all the time.
First option is best looking so far, but how to detect the elevation? Maybe there is some other option? Maybe there is some completely different approach? I’d like not to have to change the code too much if possible.
The best practice is to rewrite the app to use per-user storage unless you really need something saved by one user to affect other users on the box. That is, the answer “there is only one user, so per-user and per-machine are the same” is rejected. In this case the whole app always runs non-elevated, with a manifest to prevent virtualization.
The next best practice is to partition the application. The code that writes to HKLM is in a separate exe, and has a manifest requesting elevation. The UI has some warning (a shield on a button or menu item) where the user makes this code run. The separate process is launched with ShellExecute, which respects manifests. The experience for the user is that most of the time the app runs non elevated, and sometimes parts of it appear to elevate and then come down. That’s what it seems like but that’s actually impossible – an exe is either elevated or not. You achieve the effect with two exes.
The third best thing is to move the log somewhere that is the same whether you are elevated or not, and train your users to hand-elevate when required. I don’t think it’s a good solution at all, but it’s better than training them to hand-elevate and writing the log file in a different place every time. I’m guessing you write under “the current directory”, which is itself under Program Files, and that you have no manifest. Then when not elevated your app will write under the virtual store. If users need to look for log files this is really not good. Write to a different folder – something under AppData would be good. That location will not be virtualized.
The simplest way to detect if you are elevated is to use IsInRole to see if the user is an admin. As a little testing will prove, even admin users get
falsereturned when the app is not elevated, and even non admins who elevated with OTS prompt will gettruereturned.