Accessing ExpressScheduler Resource Information from .NET

In a previous blog post I discussed how to access the recurrence information that the VCL ExpressScheduler stores in its DB from a .NET application. Reading and writing the recurrence information is possible from .NET given a knowledge of the struct layout that the Delphi control uses.

However, if you want to read the resource information that ExpressScheduler stores in its DB from .NET, this requires using a Delphi DLL. This is because the Delphi scheduler control stores the resource ID’s for appointments in a single field but in multiple formats depending on the appointment. For instance, if the appointment has only one associated resource, its resource ID will be stored as a Delphi variant. However, the value will be stored as a Delphi variant array of variants if the appointment is associated with multiple resources.

Luckily, both Delphi and .NET make it straight-forward to interoperate between them and DevExpress has a simple utility method we can use to simplify things as well.

Start off with a new Delphi DLL project by clicking File>New>Other in Delphi XE2. On the New Items dialob, select Delphi Projects followed by Dynamic-link Library.

Start by adding both Variants and cxSchedulerStorage to the uses clause of the DPR. Then, add the following exported method to the DPR:

procedure ResourceIDBlobToString(const AResourceID: PByteArray; out AResult: PByteArray); export; stdcall;

  ResourceIDVar: Variant;
  ResourceIDVar := cxFieldValueToVariant(AnsiString(AResourceID));
  if VarIsArray(ResourceIDVar) then
    AResult := PByteArray(VarArrayToArrayStr(ResourceIDVar))
    //the cast to AnsiString below is necessary or a Unicode string will sneak in and gum up the works
    AResult := PByteArray(AnsiString(VarToStr(ResourceIDVar)));

exports ResourceIDBlobToString;

This method uses the cxFieldValueToVariant utility method found in cxSchedulerStorage to translate the string representation of the field value to a Delphi variant. We then use VarIsArray to test if the variant is an array. If it is not, we simply return the variant as a string. If the variant is a variant array, we will use the following method to parse it:

//input is a variant array of strings
//output is a comma delimited string composed of the members of the input array
function VarArrayToArrayStr(const ResourceIDArray: Variant): AnsiString;
  I: Integer;
  Result := '';
  for I := VarArrayLowBound(ResourceIDArray, 1) to VarArrayHighBound(ResourceIDArray, 1) do
    if Result <> '' then
      Result := Result + ',';
    Result := Result + VarToStr(ResourceIDArray[I]);

This simple function iterates through the variant array using VarArrayLowBound and VarArrayHighBound, building up a comma-delimited list of the resource ID’s.

And that’s it for the Delphi DLL.

Next we’ll create a new C# WinForms solution to test out our DLL. Click File>New>Project and select a Windows Forms Application.

I’ll skip the data access code as it’s straight-forward. The interesting bit here is the DllImport attribute we’ll use to call our Delphi DLL:

[DllImport("ExpressSchedulerInterop.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
static extern void ResourceIDBlobToString([MarshalAs(UnmanagedType.AnsiBStr)] string resourceID, [Out, MarshalAs(UnmanagedType.AnsiBStr)] out string result);

With this method defined properly, the following code can be used to read the resource data from the DB in C#:

string result = null;
ResourceIDBlobToString((string)reader["ResourceID"], out result);

You can download a Delphi scheduler app here, the Delphi scheduler interop project here, and the C# example data reader here.

UPDATE: I updated the code in this Blog post, along with the interop Delphi project source, to address a bug when using Unicode versions of Delphi. A cast to AnsiString is necessary or only the first character in the resource ID will be returned.

UPDATE #2: There’s a real-world example of this technique you can find here. It is an open source project for transferring data from ExpressScheduler to XtraScheduler.


1 thought on “Accessing ExpressScheduler Resource Information from .NET

  1. Pingback: Accessing ExpressScheduler Recurrence Information from .NET « Development Technobabble

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s