31 de jan. de 2005

Como fazer carga e vínculo dinâmico de DLLs?

Do fórum:

Como faço para verificar em qual Windows a aplicação está rodando, para poder chamar esta função

function RegisterServiceProcess(dwProcessID, dwType: integer):integer; stdcall; external 'KERNEL32.DLL';

pois quando utilizo ela no Windows NT ele diz que não existe esta função na biblioteca.

A variável global Win32Platform declarada na unit SysUtils permite determinar qual a versão do Windows. Neste caso, se Win32Platform <> VER_PLATFORM_WIN32_NT, então pode chamar a função RegisterServiceProcess. Um $IFDEF não serve, porque o teste da versão do Windows precisa ser feito em tempo de execução.

Ao executar o programa aparece essa mensagem:

Não foi possivel localizar o ponto de entrada do procedimento RegisterServiceProcess na biblioteca de vinculo dinâmico 'KERNEL32.DLL'

O teste da versão do Windows é parte da solução. A mensagem de erro aparece por causa da declaração

function RegisterServiceProcess(dwProcessID,
  dwType: integer):integer; stdcall;
  external 'KERNEL32.DLL'; 

Essa declaração cria um link estático entre o programa e a rotina RegisterServiceProcess; isso significa que quando programa o programa é iniciado, o código de inicialização (gerado pelo Delphi) do programa irá tentar localizar essa rotina na DLL (no caso, kernel32.dll) e irá falhar se não encontrar. O que resolve é criar um link dinâmico com a rotina RegisterServiceProcess. Um jeito de fazer isso (não testado) seria:

1 type 2 TRegisterServiceProcessProc = function (dwProcessID, 3 dwType: integer):integer; stdcall; 4 5 var 6 RegisterServiceProcess: TRegisterServiceProcessProc; 7 H: THandle; 8 begin 9 H := GetModuleHandle('kernel32'); 10 if H <> 0 then begin 11 12 RegisterServiceProcess := GetProcAddress(H, 'RegisterServiceProcess'); 13 if @RegisterServiceProcess <> nil then begin 14 15 RegisterServiceProcess(GetCurrentProcessID, 1); 16 end; 17 end; 18 end;

No exemplo não usei LoadLibrary e nem FreeLibrary porque sei que kernel32.dll é uma DLL que já está carregada pelo programa, por isso uso GetModuleHandle, mas no caso mais geral deveria usar LoadLibrary/FreeLibrary.

Links relacionados

Nenhum comentário: