quinta-feira, 17 de fevereiro de 2011

Login Integrado ao Active Directory


O Active Directory é um serviço da Microsoft, lançado no Windows 2000, que utiliza o protocolo LDAP para armazenar informações de usuários em uma determinada rede. Com ele, o administrador de redes tem todas as informações necessárias para controlar cada usuário da rede, como: nome, login e senha, bem como a criação de políticas de grupos de usuários.

Atualmente, há uma grande necessidade de se ter um login unificado dentro de uma organização, para que o usuário não tenha que ficar "decorando" login e senha de cada sistema e para que os desenvolvedores e o suporte técnico ganhem tempo, uma vez que não haverá mais tantos cadastros espalhados pela empresa. Sendo assim, vamos demonstrar neste artigo como integrar o login de sua aplicação no Active Directory.


Configure os componentes da seguinte forma:

Componente Nome Valor
TLabel lblLogin LOGIN
TLabel lblUsuario Usuário:
TLabel lblSenha Senha:
TEdit edtUsuario
TEdit edtSenha
TButton btnLogin Entrar

Primeiramente, vamos criar um novo projeto: File/New/VCL Forms Application - Delphi. Neste exemplo, criei uma tela básica de Login, como segue:

Configure os componentes da seguinte forma:

O Active Directory Service Interfaces (ADSI) nos dá uma interface COM para interagirmos com o Active Directory, portanto, vamos adicionar a unit ActiveX na uses list para utilizarmos esta interface.

Para que possamos validar o login e a senha do usuário, necessitamos utilizar uma interface requerida em objetos ADSI para capturar algumas propriedades e um método para comparar estas informações com os objetos do Active Directory. Para tanto, adicionemos em nossa aplicação as units ActiveDs_Tlb e Adshlp, as quais se encontram no final deste artigo, juntamente com o código fonte deste projeto-exemplo, não se esquecendo de adicioná-las também à aplicação.

Configure o evento onClick do btnLogin, como segue:

procedure TfrmLogin.btnLoginClick(Sender: TObject);
var
  adObject: IADs;
begin
  ///Inicialização do COM
  CoInitialize(nil);
  try
    ADsOpenObject('://',
                  LowerCase(edtUsuario.Text),
                  edtSenha.Text,
                  ADS_SECURE_AUTHENTICATION,
                  IADs,
                  adObject);
    ShowMessage('Login válido!');
  except
    on e: EOleException do
    begin
      if Pos('Falha de logon', e.Message) > 0 then
        ShowMessage('Login inválido!')
      else
        ShowMessage(e.Message);
    end;
  end;
  CoUninitialize;
end;
Como podemos ver, inicializamos o COM e depois utilizamos um método para comparação de nosso login e senha com os objetos do Active Directory. Neste método, passamos o provider WinNT ou LDAP, o nome do domínio da rede que estamos conectados, o login e senha que o usuário digitou, a forma de autenticação ao Active Directory, a interface e um objeto IADs que criamos localmente. Se houver erro nesta comparação, significa que o login e senha digitados não foram encontrados em nenhum objeto do Active Directory ou há algum problema na comunicação ou conectividade da rede.



Clique aqui para baixar o código fonte do exemplo (323 KB)

quarta-feira, 16 de fevereiro de 2011

Executar o Windows Explorer em uma pasta específica


Veja nesta dica um código simples, capaz de abrir via programação o Windows Explorer, iniciando-o em uma pasta específica. Para compilar, é necessário acrescentar ao uses a unit ShellApi, e codificar a seguinte função:

function ExecExplorer(OpenAtPath: string; OpenWithExplorer,
  OpenAsRoot: Boolean): Boolean;
var
  s: string;
begin
  if OpenWithExplorer then
  begin
    if OpenAsRoot then
      s := ' /e,/root,"' + OpenAtPath + '"'
    else
      s := ' /e,"' + OpenAtPath + '"';
  end
  else
    s := '"' + OpenAtPath + '"';

  result := ShellExecute(
    Application.Handle,
    PChar('open'),
    PChar('explorer.exe'),
    PChar(s),
    nil,
    SW_NORMAL) > 32;
end;
Para testar, podemos fazer, por exemplo:

  ExecExplorer('C:\Temp', True, True);

terça-feira, 15 de fevereiro de 2011

Executável que se auto-deleta


Veja nessa dica de nosso colunista Handem Vogel como implementar a auto-exclusão do programa em execução. Primeiramente, declare o procedimento
procedure TForm1.DeletaExe;
Var
  Arquivo: TextFile;
begin
  AssignFile(Arquivo, ChangeFileExt(ParamStr(0), '.bat'));
  try
    ReWrite(Arquivo);
    WriteLn(Arquivo, ':1');
    WriteLn(Arquivo, Format('Erase "%s"', [ParamStr(0)]));
    WriteLn(Arquivo, Format('If exist "%s" Goto 1', [ParamStr(0)]));
    WriteLn(Arquivo, Format('Erase "%s"', [ChangeFileExt(ParamStr(0), '.bat')]));
  finally
    CloseFile(Arquivo);
  end;
  WinExec(PChar(ChangeFileExt(ParamStr(0), '.bat')), sw_hide);
  Halt;
end;
Agora, no evento onClose do formulário, basta chamar a procedure acima, com o seguinte código:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  DeletaExe;
end;
Isto fará com que o executável se "auto-exclua" assim que fechado!

segunda-feira, 14 de fevereiro de 2011

Procedimentos com parâmetros opcionais:

Quando você declara o procedimento:

procedure Esperar(Segundos: Byte);
Você está determinando que todas as vezes que o procedimento. Esperar for chamado, deverá ser passado um valor do tipo Byte. No entanto, esse tipo de declaração exige que em todas as chamadas ao procedimento Esperar seja especificado um parâmetro.

Se você fizer uma chamada do tipo:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Esperar()
end;
Será gerado um erro do tipo: Not enough actual parameters. Mas você pode declarar e implementar o procedimento da seguinte forma:

procedure Esperar(Segundos: Byte = 1);
begin
  Sleep(Segundos * 1000);
end;
A declaração acima faz com que o procedimento Esperar assuma o valor 1 caso nenhum parâmetro seja passado. Assim você poderá fazer uma chamada ao procedimento em qualquer das situações abaixo:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Esperar(); // nenhum parâmetro, será assumido o valor 1
  Esperar(1);
  Esperar // nenhum parâmetro, será assumido o valor 1
end;

Cuidados quando criar procedimentos e funções com parametros

Quando criamos procedimentos e funções podemos introduzir parâmetros com
valores defaultdevemos porém respeitar algumas regras:

Esse parâmetros precisam ocorrer no final da lista;

precisam ser constantes

Não pode fazer por referência(var alguma coisa)

Respeitando essas regras o delphi permite criar sem problemas funções ou
procedimentos do tipo:

function Resizer(X: Real; Y: Real = 2.0): Real;
procedimento Multiplicar(var X:Real;X:Real=1;Resposta:Real=0);
etc...

Se vc chamar "resizer" sem os parâmetros o delphi considera que vc quer
usar os valores default da função....

Tenha MUITA ATENÇÃO PORÉM com funções ou procedimentos que forma
declarados em overload ou "sobrecarga" que permite que dois ou mais
procedimentos ou funções tenham nomes iguais desde que tenham parâmetros
diferentes.Isso criaria problemas na lógica do compilador....Pense, O
que difere um procediemnto do tipo:

1)procedure teste(A:integer);overload

2)procedure teste(A:integer=0);overload;

Se vc chamar teste(x) o compilador não sabe se vc está querendo chamar o
procedimento 1 ou 2...

Função de potenciação - Juros

Segue abaixo uma função para efetuar a potenciação. É útil para compor formulas financeiras, como a de VP ("PV" valor presente) VF ("FV" valor futuro).

Exemplo:
Calcular o valor de um produto para o prazo de 30 dias com a taxa de juros de 5% mês.

var

 i: Real; // taxa de juros
 valor: Real; // valor base para calculo do valor futuro.
 pz: Integer // prazo em dias
begin
  i := 5//100;
  valor:= 1000.00
  pz := 30
  Result:= valor*( Pot( (1+i), (pz/30) ) //Resultado 1.050,00
end;
no excel a Pot é substituída pelo sinal ^ Ex. =E18*((1+C19)^(C20/30))

Function Pot( base, expoente: real ):real; // Potenciação
begin
        { utiliza a função de exponencial e de logaritmo }
     Result:= Exp((expoente * Ln( base )));
end;
 
Dicas:
Não amplie o nome da função, pois as funções financeiras costumam ser bem extensas.

domingo, 13 de fevereiro de 2011

Atualizando Dados em Rede com Zeos


Procurei muito na internet sobre como atualizar as informações de minha aplicação nas estações. Tentei todos os tipos de comandos e funções que eu poderia fazer e não funcionou. Os dados só eram visualizados após reiniciar o programa. Foi aí que descobri a solução
Nas propiedades do ZConnection (deve ser a antepenultima opção, 3ª de baixo para cima no Object Inspector), está a TransactIsolationLevel. Mude-a de itNone para tiReadCommited.
Pronto! Faça a alteração de um registro em qualquer estação e ao fazer uma busca novamente em um outro computador / executável, já verá carregado as novas informações.

Curso de Delphi: 7.Consultas SQL