Jan 16 2007
Delphi: Como detectar se a sua aplicação está rodando sobre WTS e saber qual é a ID da sessão
Parece ridículo, mas quem poderia imaginar que o controle de licenças de um software furaria quando os clientes fizessem o acesso via WTS (Windows Terminal Server)?
Imagine a seguinte situação: um controlador de licenças baseado no IP dos clientes e que bloqueia a execução da mesma aplicação duas vezes simultaneamente na mesma máquina. Se o acesso ao controlador for via TCP/IP “diretamente”, da forma mais comum possível (um servidor + um cliente), essa validação funcionará perfeitamente.
Agora pense no mesmo cenário acima, porém com o acesso de dois clientes usando WTS. O que acontece? O primeiro cliente acessa, o controlador faz o registro do IP. Quando o segundo cliente for acessar (lembre-se, é WTS), adivinha? O controlador bloqueia! Por que? Pois o segundo cliente possui o mesmo IP do primeiro, que por sua vez possui o mesmo IP do servidor, pois está tudo sobre WTS.
Solução? Eu vejo duas:
- Controlar o acesso pelo IP do cliente. Para isso, é preciso identificar qual a sessão que está acessando o WTS e através do seu ID buscar as informações (IP e outras) de quem a originou;
- Fazer com que o controlador de licenças conheça se o cliente está sobre WTS e considerar o ID da sessão no controle de acesso.
Para ambas as soluções duas rotinas são fundamentais:
- Identificar se a aplicação está sendo executada via WTS:
function IsRemoteSession: boolean; const SM_REMOTESESSION = $1000; begin Result := GetSystemMetrics(SM_REMOTESESSION) <> 0; end;
Adicione o uses Windows à unit.
- Pegar o ID da sessão que vai executar o aplicativo:
1 function GetCurrentSessionID: Integer; 2 type 3 TProcessIdToSessionId = 4 function(dwProcessId: DWORD; 5 pSessionId: DWORD): 6 BOOL; stdcall; 7 var 8 ProcessIdToSessionId: TProcessIdToSessionId; 9 hWTSapi32dll: THandle; 10 Lib : THandle; 11 pSessionId : DWord; 12 begin 13 Result := 0; 14 Lib := GetModuleHandle('kernel32'); 15 if Lib <> 0 then 16 begin 17 ProcessIdToSessionId := 18 GetProcAddress(Lib, 'ProcessIdToSessionId'); 19 20 if Assigned(ProcessIdToSessionId) then 21 begin 22 ProcessIdToSessionId(GetCurrentProcessId(), 23 DWORD(@pSessionId)); 24 Result:= pSessionId; 25 end; 26 end; 27 end;
As units Windows e Winsock são necessárias.
Com essas duas rotinas é possível controlar se aplicação cliente está sobre WTS ou não. O resto fica por conta da sua imaginação.
Fonte: Torry’s Delphi Pages (cuidado com a rotina que está lá, ela tem um errinho no parâmetro da GetProcAddress - o número 1 está sobrando)
Até +!







