Wednesday, 11 February 2015

TIniFiles and its alternatives

- or how to make legacy applications survive, with less work.


When applications gets an “End of Life” sentence – it doesn’t mean that they just can be closed down – they might need to wait for their successor to be build – and meanwhile it has to survive in the field of changing infrastructure, OS upgrades and consolidation.

What at the time seemed like a good idea and best practice, would end up as the sins of the past. INI files could be one of these – and here are some minor tips on what can be done to conform to newer or changed environments – without rewriting too much code.


Enter an application build in the Windows 95/2000 time frame – which then needed to be moved into an UAC Windows 7 Citrix centralized environment – also going from a country replicated setup to a single server setup covering several regions.

The setup also allowed to run the application offline – using a local DB identical to the server version – that involved replication and also the need for a local storage of the users preferences via an INI file.

To keep portability the Windows registry had been avoided, and moving the INI files with the users preferences into an UAC “approved” location was not a big issue – when migrating all servers into one Citrix setup, the INI file was moved into an user specific off-line folder structure on a file server – which did do the trick for some years.

But since TIniFile is on a need-basic implementation – every read/write does file I/O – so moving things away from the Application made it slower. When the off-line folder then got discontinued during a Windows 8.1 upgrade – the INI file was moved into My Documents on the users local hard drive – which would seem fine, but upload is normally worse than download speeds – so reading/writing (upload) a 4 kb file to a server was drastically slower than downloading it from one server to another in the same data center – and doing that 200 times within a single application – that hurts.

Tip no. 1: Centralized the reading and writing of the INI file, as much as possible.

Tip no. 2: Do use the TMemIniFile class instead – since the whole file is read into memory so file I/O is reduced. TIniFile and TMemIniFile both descent from TCustomIniFile – so it is just a question about changing the declaration. Do remember when writing data back to call the UpdateFile method (it is implemented on TIniFile also but does nothing)

Tip no. 3: If you want, and can use the registry – which in my opinion would have been an ok alternative, if Microsoft had made it easier to extract, manipulate and backup. TRegistryIniFile to the rescue – this is a wrapper for TRegistry that behaves like a TIniFile, so the constructor only needs to be called with the key instead of the file name. The ROOT is default set to HKCU.

TIniFile

with TIniFile.Create(‘MyProgram.ini’) do
begin
  i := ReadInteger(‘Section’, ‘Key’, 0);
  WriteIntger(‘Section’, ‘Key’, i+42);
  UpdateFile; // Not needed
  Free;
end;

TMemIniFile

with TMemIniFile.Create(‘MyProgram.ini’) do
begin
  i := ReadInteger(‘Section’, ‘Key’, 0);
  WriteIntger(‘Section’, ‘Key’, i+42);
  UpdateFile;
  Free;
end;

TRegistyIniFile

with TRegistryIniFile.Create(‘\Software\MyProgram\’) do
begin
  i := ReadInteger(‘Section’, ‘Key’, 0);
  WriteIntger(‘Section’, ‘Key’, i+42);
  UpdateFile; // Not needed
  Free;
end;

You could also go for something more flexible like a JSON file to replace your INI file – it still leaves some of the other issues open – but check out an older Skill Sprint by Jeff Lefebvre.

As you might have guessed application built during that time frame are not Unicode compliant – well Windows wasn't either – probably being the last OS to comply.

So this raises an issue when things are centralized, and at the same time should cover several regions, locales and character sets. The solution to that issue ended up being SBAppLocale, an alternative command line clone to Microsoft's discontinued AppLocale utility  - and it did also work a lot better than the old official fix. I have mentioned this utility in an earlier post here.

It is still #DelphiWeek 2015 - so go register for some of the sessions - enjoy and tweet #DelphiWeek :-)