Archive for the ‘Delphi 2007’ Category

Delphi, Firebird, IBObjects and Transaction Management

Thursday, November 17th, 2011

I recently had reason to revisit transaction management in our application.  The application makes extensive use of data aware grids (TDBGrid) and, as I am sure everyone is aware, it is impossible to explicitly manage transactions when you are displaying data in a grid.

Fortunately, IBObjects provides the means to automatically clean up transactions left hanging by TDBGrid.  Unfortunately, this isn’t as well documented or as straightforward as I would like.  So, after much research using the programmer’s secret weapon (Google) and a few questions posted to the IBObjects support group (thanks Jason) I think I finally understand how it works. (more…)

The Mystery of the Disappearing Icon

Thursday, November 3rd, 2011

I just finished creating a new custom control for Delphi.  I’ve done this dozens of times in the past and never had a problem until now.  This time the control’s icon simply would not appear in the tool palette.  No matter what I did, all I got was the default icon.

It turns out, that the first time I installed the component I had a problem with the DCR file that held the icon, so Delphi installed the control with the default icon.  Perfectly reasonable.  However, Delphi keeps a cache of custom controls that have been installed and, apparently, no matter how many times you uninstall and reinstall, it remembers certain settings (like the icon) from the cache.  To fix this problem, you need to manually edit the registry and remove the offending cache items.  To do this:

  1. Uninstall your custom control from the Delphi IDE.
  2. Open the registry editor (regedit.exe).
  3. Browse to HKEY_CURRENT_USER\Software\Embarcadero\DBS\9.0\Package Cache.  Where 9.0 is the version number for Delphi XE2.  Your version number may vary.
  4. Delete the key MyCustomControl.bpl where MyCustomControl is the name of your custom control’s package.
  5. Browse to HKEY_CURRENT_USER\Software\Embarcadero\DBS\9.0\Palette\Cache.
  6. Delete the key MyCustomControl.bpl where MyCustomControl is the name of your custom control’s package.
  7. Reinstall your custom control as your normally would.

Hopefully, the proper icon will now appear in the tool palette.

Delphi Compiler Versions

Tuesday, October 25th, 2011

If you ever need it, here is the list of Delphi compiler version numbers:

Compiler CompilerVersion Defined Symbol
Delphi XE5 26 VER260
Delphi XE4 25 VER250
Delphi XE3 24 VER240
Delphi XE2 23 VER230
Delphi XE 22 VER220
Delphi 2010 21 VER210
Delphi 2009 20 VER200
Delphi 2007 18.5 VER185
Delphi 2006 18 VER180
Delphi 2005 17 VER170
Delphi 8 16 VER160
Delphi 7 15 VER150
Delphi 6 14 VER140
Delphi 5 13 VER130
Delphi 4 12 VER120
Delphi 3 10 VER100
Delphi 2 9 VER90
Delphi 1 8 VER80

To make use of this information in a Delphi program you can define conditionally compiled bits, like this:

{$if CompilerVersion >= 20} // Delphi2010 or later

{$ifend}

OR

{$ifdef VER200} // Delphi2010

{$endif}

The Case of the Disappearing Rows

Friday, August 5th, 2011

I just lost a week of my life trying to track down a problem with a program that did a mass insert of records into a SQL Server database.  The program is written in Delphi 2007 and uses dbExpress components for access to SQL Server.

The problem first manifested after an 8 hour run when, lo and behold, the database only had 11K rows rather then the expected 884K.  I knew that the program was sound because I had just run the same program to load the same file into a Firebird database without a problem.  (That only took 3 hours by the way).

Now, the source file had some bogus data in it.  I knew this and the program made allowances for it by trapping the resulting exceptions, writing them to a log file and dropping the offending record.

It turns out that these data conversion errors fall into a class of SQL Server error known as “batch aborting” errors.  Whenever a batch aborting error occurs the current transaction is rolled back without so much as a “by your leave”.  You would think that this would be documented somewhere, in BIG BOLD LETTERS.  If it is, I can’t find it.  If it weren’t for Google I would still be scratching my head.

I found this table in an article on another web site:

Error Aborts
Duplicate primary key. Statement
NOT NULL violation. Statement
Violation of CHECK or FOREIGN KEY constraint. Statement
Most conversion errors, for instance conversion of non-numeric string to a numeric value. BATCH
Attempt to execute non-existing stored procedure. Statement
Missing or superfluous parameter to stored procedure to a procedure with parameters. Statement
Superfluous parameter to a parameterless stored procedure. BATCH
Exceeding the maximum nesting-level of stored procedures, triggers and functions. BATCH
Being selected as a deadlock victim. BATCH
Permission denied to table or stored procedure. Statement
ROLLBACK or COMMIT without any active transaction. Statement
Mismatch in number of columns in INSERT-EXEC. BATCH
Declaration of an existing cursor Statement
Column mismatch between cursor declaration and FETCH statement. Statement.
Running out of space for data file or transaction log. BATCH

The entire article, which is a good review of SQL Server error handling techniques, can be found here.

Imagelib PutTifFile Function Hangs

Monday, April 25th, 2011

I got hung up for a while recently trying to figure out why the Skyline Tools Imagelib puttiffile function was hanging when I tried to use it to create a multi-page TIFF file from a series of bitmaps.  It took me a long time to figure out that appending to an empty (zero byte) file causes puttiffile to enter an endless loop, while appending to a non-existent file does not.

Go figure!

Anyway, I have bundled up a small test application and sent it to Imagelib technical support.  I will post here when I get a response.

Delphi with … do Gotcha

Thursday, February 10th, 2011

I got bitten by something the other day and it had me tearing my hair trying to figure out what was going on.  An application that had been working for years starting throwing access violations.  Stepping through it with the debugger, everything looked good.  No nil pointers, nothing obviously wrong.

Finally, I realized that I was freeing and reallocating the object referenced by a with … do block while I was inside the block.  Very simplified, the code looked something like this:


with myObject do
begin
myObject.Free;
myObject := TmyObject.Create;
end;

Pretty stupid when you think about it, but frustrating all the same.

Forcing a Delphi Program to Run with Administrator Privilege

Monday, June 21st, 2010

No matter how hard you try to eliminate the need for administrator access from your programs, sometimes they just need to run as administrator in order to work.  I came across this requirement while recoding our application’s configuration utility.  I dutifully removed all configuration entries  from the registry and moved them to the “All Users” folder but I needed to be able to configure some of our programs to run as Windows services.  No matter how you look at it, this requires administrator privilege.

I didn’t want to force our users to “run as administrator” on Vista, Windows 7 and Windows 2008.  Can you imagine the number of support calls that would generate? :(  So, I starting looking for a way to force the program to request administrator privilege .

(more…)

Getting the List of Configured DNS Servers

Wednesday, January 13th, 2010

If you ever find yourself in a position where you need to know that IP addresses of the DNS servers configured on a Windows system just use the GetNetworkParams Windows API call.  This is not implemented in the Delphi 2007 component library, but luckily it is implemented in the Jedi Code library.

Custom Variant Wrapper for TDataset - Part 6

Wednesday, January 6th, 2010

In Part 5 we discussed casting our custom variant to and from other data types.  In this part we will discuss implementing dynamic functions and procedures.   Dynamic functions are implemented by overriding TPublishableVariantType.DoFunction and dynamic procedures are implemented by overriding TPublishableVariantType.DoProcedure.

(more…)

Custom Variant Wrapper for TDataset - Part 5

Monday, January 4th, 2010

In Part 4 I showed you how to get and set dynamic properties of our custom variant.  In this part I will show how custom variants can be cast to and from other data types.

(more…)