Vista User Account Control and Command Line Applications

The last weeks have been quite hectic, I have been face-to-face with over a thousand Delphi developers talking about Delphi 2007 for Win32 in Stockholm, Gothenburg (thanks Karl-Otto for the CodeGeare cap), Budapest, Prauge (see picture), Helsinki, Copenhagen and Oslo.

Jason Vokes tagged me and challenged me to write about five things I like with the new Delphi release:

Like many other already have said, Delphi 2007 launches fast and has a quick and responsive IDE.

Second out are some small debugger features that are really usefull – You can set breakpoints in the call stack and stop execution when it returns to a specific stack frame and you can also select some code and drag and drop it to the watches windows for evaluation.

All RTL and VCL improvements like the MainFormOnTaskbar property on TApplication that solves the long existing problem with the application context menu, Flip3D and Thumbnail support. Improvement of DoubleBuffered rendering. Usage of themed components in IDE. Updated memory manager, etc.

The much improved help system.

And finally another small productivity feature – you can save several diffrent configurations of compiler and linker settings and easily switch between them with the Configuration Manager.

I talked about User Account Control (UAC) during my CodeRage-session last week. I think UAC is one of the most important features of Windows Vista and if you are not in total control of your users’ environment, sooner or later you will run into questions and support issus related to UAC.

UAC Horror StoryI heard a real horror story related to UAC from a developer in Sweden last week during the Delphi User Group meeting in Stockholm. Their application has a local database and the database engine is launched by the application. Since UAC made the application start as Standard User the database enginge also started as Standard User. But a Standard User did not have the rights needed to modify the database files where they got installed. You would assume that this would generate an Access Denied error or some other error message? But no, and now the horror begins…

Since their application did not have required execution level information in the manifest Windows Vista runs the process in compatibility mode. Instead of failing to open the database which the process has no right to modify Windows Vista silently makes a copy of the whole database (to the personal VirtualStore for each user) and saves the changes there instead. The users did not notice anything initally because they work on diffrent projects but after a while they started to wonder why they could not see any changes their colleagues have done.

When they found out what was wrong they had to do a lot of manual work to merge each users’ copy of the database back into one database again…

Conclusion: To get rid of the dangerous compatibility feature called Virtualization or Redirection by adding a manifest with required execution level to all you executables immediately! This can be done easily by just recompiling your application in Delphi 2007 for Win32 and checking use themes in project options or use the xpman unit in D2007. With an earlier Delphi release you can manually create and include the manifest.

Command Line ApplicationsI did not talk so much about command line applications and UAC during my Code-Rage session so I would like to write a little about that.

First, like with all applications targeting Windows Vista, you should have a manifest with required execution level to turn off compatibility mode. But even if you command line tool requires admin privileges you should never set level = “requireAdministrator”. The reason for this is that you do not want a batch script to be interrupted with a modal consent dialog, instead Microsoft recommends you to halt execution with an error message and set the exit code to ERROR_ELEVATION_REQUIRED.

program VistaConsoleApplication;

{$APPTYPE CONSOLE}

//Include Manifest with trustinfo to make executable Vista Logo Compliant and not run in compatibility mode.
//Console Applications should always run as invoker even if they require admin privileges.
{$R ‘ExecutionLevelAsInvokerManifest.res’ ‘ExecutionLevelAsInvokerManifest.rc’}

The RequireAdminConsole function is really simple and it uses a function IsUserAnAdmin in the WinAPI to test. I have written the code so it binds dynamically. The reason is to make it work on operation systems before Windows 2000. You could also use a NT4 compatible apporoach and check if token has SID for admin group but that would be much more code…

Call the function GetTokenElevationType above to test the current state of elevation.

case GetTokenElevationType of
TokenElevationNotAvailable:WriteLn(‘No information about elevation is available. (This is a non-vista machine)’);
TokenElevationTypeDefault:WriteLn(‘TokenElevationTypeDefault – User is not using a split token.’);
TokenElevationTypeFull:WriteLn(‘TokenElevationTypeFull – User has a split token, and the process is running elevated.’);
TokenElevationTypeLimited:WriteLn(‘TokenElevationTypeLimited – User has a split token, but the process is not running elevated.’);end;

When a customer installs my program on a windows vista computer, I have to show them how to;
1. Locate my program (I put it in a new folder on the C:\ drive)
2. Right click my appliaction.exe file
3. Select the Comapibility tab.
4. Check the box “Run as Administrator”
Only then when will my program run correctly.

Obviously, this is a little annoying and puts off some of my customers.
My question is;
Is there a way to Run my application automatically as an administrator or in the alternative, automatically get the users permission to run my appliaction as an Administrator.