how to declare an external function that exist only on windows 8 without making the app crashing on windows 7 and lower?

Viewed 230

Look stupid, but is their a way to declare an external function like :

function EnumDynamicTimeZoneInformation(dwIndex: DWORD; lpTimeZoneInformation: PDynamicTimeZoneInformation): DWORD; stdcall; external advapi32;

because as EnumDynamicTimeZoneInformation is available only still windows 8, this declaration makes the app crash on windows 7 and lower.

The procedure entry point EnumDynamicTimeZoneInformation could not be located in the dynamic link library

Is their anyway to make that this declaration will not make the app crashing, even if we don't use it in the app

2 Answers

In Delphi 2010 and later, you can use the delayed directive on the end of an external declaration, eg:

function EnumDynamicTimeZoneInformation(dwIndex: DWORD; lpTimeZoneInformation: PDynamicTimeZoneInformation): DWORD; stdcall; external advapi32 delayed;

The delayed directive can be used to decorate an external routine to delay the loading of the library containing the routine. The actual loading happens when the routine is called for the first time.

...

The delayed directive is useful in the case where the imported routines do not exist on the target operating system on which the application is run. Statically imported routines require that the operating system find and load the library when the application is started. If the routine is not found in the loaded library, or the library does not exist, the Operating System halts the execution of the application. Using the delayed directive enables you to check, at run time, whether the Operating System supports the required APIs; only then you can call the imported routines.

For example:

if CheckWin32Version(6, 2) then
begin
  EnumDynamicTimeZoneInformation(DesiredIndex);
end;

Load the library dynamically then get the address of the function.

var
  EnumDynamicTimeZoneInformation : function (dwIndex: DWORD; lpTimeZoneInformation: PDynamicTimeZoneInformation): DWORD; stdcall;
  AdvApiHandle: THandle; 

procedure LoadEnumDynamicTimeZoneInformation()
begin
  if EnumDynamicTimeZoneInformation = nil 
  then begin
    AdvApiHandle := LoadLibrary('advapi32.dll');
    if AdvApiHandle <> 0
    then EnumDynamicTimeZoneInformation := GetProcAddress(AdvApiHandle,'EnumDynamicTimeZoneInformation');    
  end;
end;

begin
  LoadEnumDynamicTimeZoneInformation();
  if EnumDynamicTimeZoneInformation <> nil
  then EnumDynamicTimeZoneInformation(...)
  else ShowMessage('No EnumDynamicTimeZoneInformation');
  ....
  if AdvApiHandle <> 0 
  then FreeLibrary(AdvApiHandle);
end.
Related