Thursday, September 25, 2008

Delphi 2009 - COM+ Custom Attributes

The COM+ tab in the Type Library editor of Delphi 2009 and C++Builder 2009 is no longer visible. The only options that did anything where the Transaction Model. If you go into the text tab (I won't suggest this very often but this is one of those times) and add one of the following custom attributes on the COM+ event object then when you register your COM+ event object in the Component Services this Transaction Model will be the default:

Transaction required:

custom('{17093CC5-9BD2-11CF-AA4F-304BF89C0001}', 0)

Requires a new transaction:

custom('{17093CC7-9BD2-11CF-AA4F-304BF89C0001}', 0)

Supports a transaction:

custom('{17093CC8-9BD2-11CF-AA4F-304BF89C0001}', 0)

Does not support a transaction:

custom('{17093CC6-9BD2-11CF-AA4F-304BF89C0001}', 0)

These custom attributes can be found in mtxattr.h. Note that the COM+ tab never worked with these two customer attributes defined in mtxattr.h:

#define TLBATTR_QUEUEABLE E5FC3761-0BBA-11d2-B8FE-00C04FC340EE
#define TLBATTR_COMTI_INTRINSICS 47065EDC-D7FE-4B03-919C-C4A50B749605

For a little history the original COM+ tab looked like this:

Everything on this page was stored by encoding the data as custom attributes in the type library. The Transaction Model used the custom attributes above which is the only useful piece of informationThe rest of the page used the custom attributes described below that only this COM+ page used so they were pointless. Note that no tools other than the this COM+ tab of the Type Library Editor and the menu item in Run | Install COM+ Objects from Delphi 7. All of the Microsoft custom attributes start with a GUID beginning with 17 while the Delphi custom attributes start with the GUID beginning with B0.

This custom attribute tells the IDE that the object is a COM+ event object and allows the COM+ tab and the Run | Install COM+ Objects menu item to be enabled:

custom('{B0FC9341-5F0E-11D3-A3B9-00C04F79AD3A}', True)

Call Synchronization where X is:

X = 0 (Ignored)
X = 1 (None)
X = 2 (Supported)
X = 3 (Required)
X = 4 (Requires New)

custom('{B0FC9344-5F0E-11D3-A3B9-00C04F79AD3A}', Value)

Creation Timeout where X is the timeout value:

custom('{B0FC9340-5F0E-11D3-A3B9-00C04F79AD3A}', X)

Allow inproc subscribers where X is True/False:

custom('{B0FC9345-5F0E-11D3-A3B9-00C04F79AD3A}', "X")

Fire in parallel where X is True/False:

custom('{B0FC9346-5F0E-11D3-A3B9-00C04F79AD3A}', "X")

Transaction Ignored:
custom('{B0FC9368-5F0E-11D3-A3B9-00C04F79AD3A}', 0)

JIT Activation:
custom('{B0FC9342-5F0E-11D3-A3B9-00C04F79AD3A}', True)

Object Pooling:
custom('{B0FC9343-5F0E-11D3-A3B9-00C04F79AD3A}' True)

Delphi 2009 - Exit

Exit is now very similar to the C++ return keyword where you can supply an optional parameter that is assigned to a functions return value. For example:

function DoStuff(Value: Boolean): Integer;
  if Value then

  Result := 0;

Post Ship Bliss...

This means lots of meetings. All day in fact. Nearly all week. Here's a pretty picture I took on my backpacking trip last week:

Brief note about the camera equipment I took on my 10 day 70 mile backpacking trip. I lugged around a Canon 5D, Canon 24-105 F4 IS, remote switch, two batteries and two 8gb Extreme IV memory cards totaling nearly 4lbs. Ouch! Was it worth it? I think so.

Wednesday, September 24, 2008

Delphi 2009 - New Integer Alias Types

Here are some new useful alias types in Delphi 2009:

  Int8   = ShortInt;
  Int16  = SmallInt;
  Int32  = Integer;
  UInt8  = Byte;
  UInt16 = Word;
  UInt32 = Cardinal;

Delphi 2009 - Add a type library to a project

To add a type library to a project add a .ridl file (it should just be a blank file, or can prepopulat it with IDL) with the same filename as the project (Example: Project1.dpr or Project1.cpp then Project1.ridl). Then for Delphi add:

{$R *.TLB}

to the .dpr file or for C++ add a:

#pragma resource "*.tlb"

to the Project1.cpp file.

If you don't want to link the .tlb file into the project simply do remove the $R or the #pragma.

Tuesday, September 23, 2008

Delphi 2009 - Unicode in Type Libraries

If you've opened up the Tools | Options in Delphi 2009 and taken a look at C++ Type Library Options and Delphi Type Library Options you'll notice the options are relatively the same as previous version but there are a few additions that might not be all that easy to understand. Here's a screen capture of the two dialogs:

Notice the two UTF8 options:

- Store Unicode data as UTF8 in type library
- Check for UTF8 data in type library

I'll explain what these do but first I we need a bit of a back story.

Back when the COM team was working on the new COM features for Tiburon (Delphi 2009 and C++ Builder 2009), we found that ICreateTypeLib, ICreateTypeLib2, ICreateTypeInfo and ICreateTypeInfo2 don't actually support BSTRs even thoough all their string paramters are BSTRs. Somewhere in the writing of the .tlb file the data is narrowed down and the unicode data is lost. After some testing using MIDL 5.01.0164 we found that Microsoft had apparently known about this and worked around it by UTF8 encoding the data and then stuffing it into the BSTR. Then we found that the latest version of MIDL 7.00.0500 produced errors when compiling files with unicode data.

So we wanted to support unicode throughout the product so we added support for UTF8 data in type libraries. The two options read UTF8 data and write UTF8 data. This means you can create unicode identifiers (functions and classes) for use between Delphi and C++Builder 2009 (and apparently MIDL 5.01.0164) but that's about it. I would suggest staying away from unicode identifiers in your Type Libraries.

Friday, September 19, 2008

Delphi and C++Builder 2009 - TApplication is Apartment Threaded

In Delphi 2009 and C++Builder 2009 (AKA Tiburon) by default the main thread of a VCL application will be apartment threaded. Take a look at TApplication.Create for the details. This isn't really a change from previous versions of VCL but the location of the call and how to override it is new. And now VCL calls OleInitialize instead of CoInitialize so there is a slight behavior change.

There may be reasons why a developer won't want this default behavior and the best way of doing this is to create this unit:

unit InitCom;




  NeedToUninitialize: Boolean;
  NeedToUninitialize := Succeeded(CoInitializeEx(nil, COINIT_MULTITHREADED));
  if NeedToUninitialize then

And place it in the .dpr as the first unit (it must be before Forms or anything that brings in Controls).

It isn't recommended to run any UI under a multithreaded apartment but this will allow those who need it to change the default threading model.

Here is a blog post by Raymond Chen about why running the UI thread as multithreaded isn't a good idea.

Wednesday, September 17, 2008

September Photo of the Month

Old Army Pass

Copyright © 2008 Chris Bensen. All rights reserved.

I just got back from a 10 day backpacking trip (my daughter calls it pack packing) only to discover that world financial markets had melted down. I went to Sequoia National Park and Inyo National Forest in and around the base of Mt Whitney. We went up through Cottonwood Lakes, over New Army Pass, down Rock Creek, up over Guyot Pass with the craziest little big trees I've ever seen, got stuck in a thunder storm with rain, no wait, hail, no wait, snow, and made it to Crabtree Meadow where you can see Mt Whitney. The next day we heard a dozen helicopters lift people off Mt Whitney because the storm came in unexpected. Then we went down to the Kern river where I got bit up by mosquitoes and almost a rattle snake. On the Kern we soaked in the most disgusting bathtub filled by a hot springs I've ever seen but felt like a million bucks and then hiked out. I started the trip out with a 55lb pack, but ended the trip with a 65lb pack even after eating all my food because we had such a hellacious hike that I took everyone's heavy stuff like water still averaging 2.5mph according to the GPS. Now I have to figure out how to type again.