7 de jul. de 2015

Debugger Kernel BORDBK100.DLL or BORDBK100N.DLL is missing or could not be loaded

Estava eu, aqui de boas, trabalhando no Delphi 2006 e o debugger parou de funcionar:


Isso acontece porque as duas DLLs citadas na mensagem de erro se des-registraram, quer dizer, é preciso registrá-las novamente para que o debugger do Delphi 2006 volte a funcionar.

Para registrar essas DLLs novamente, é preciso executar os seguintes comandos:

regsvr32.exe "C:\Program Files (x86)\Borland\BDS\4.0\Bin\bordbk100.dll"
regsvr32.exe "C:\Program Files (x86)\Borland\BDS\4.0\Bin\bordbk100n.dll"

Crie um arquivo .bat, adicione esses comandos e execute o arquivo .bat como Administrador, para garantir que o registro das DLLs seja executado.

Após feito isso, feche e abra o Delphi novamente.

Bom proveito.

7 de ago. de 2013

Filtrando dados de acordo com um intervalo de horas

O sistema da empresa na qual trabalho hoje tem uma tela de filtro de logs. Essa tela filtrava os logs apenas por data e tivemos a necessidade de acrescentar filtros para um intervalo de horas específico do dia. Queríamos, por exemplo, visualizar os logs entre 9:30hs e 10:15hs da manhã, de segunda a sexta.

Como a linguagem SQL não tras nenhuma facilidade para esse tipo de filtro, tivemos que colocar a caixola para funcionar. A solução é bem simples.

Meu campo que guarda a informação sobre o inicio do log é o campo INICIO_LOG. O primeiro passo é calcular o valor em minutos desse campo desde a zero-hora e criar um campo virtual na sua tabela resultado contendo esse valor em minutos. Em SQL-Server para calcular o valor em minutos de um campo data, desde a zero-hora, basta fazer:
DatePart(Hour, INICIO_LOG) * 60 + DatePart(Minute, INICIO_LOG) 
A partir daí, basta incluirmos esse campo virtual em nossa tabela resultado, bastando para isso usar um select na cláusula From:
select *
from (select DatePart(Hour, INICIO_LOG) * 60 + DatePart(Minute, INICIO_LOG) MINUTOS, * from LOGS) Logs
Agora temos uma tabela com o novo campo "MINUTOS".

Se eu quero visualizar os Logs entre 9:30hs e 10:15hs da manhã, preciso calcular quantos minutos eu tenho, desde a zero-hora, no 1o. e no 2o. parâmentros. Para 9:00hs temos 9 * 60 + 30 = 570 minutos e para 10:00hs temos 10 * 60 + 15 = 615 minutos. Se um registro de Log foi adicionado as 09:45hs da manhã, temos 9 * 60 + 45 = 585 minutos, cujo valor estará entre nosso 1o. parâmetro (570 minutos) e nosso 2o. parâmetro (615 minutos).

Nossa sentença SQL com os parâmetros fica da seguinte forma:
select *
from (select DatePart(Hour, INICIO_LOG) * 60 + DatePart(Minute, INICIO_LOG) MINUTOS, * from LOGS) Logs
where
  MINUTOS Between :MINUTO_INICIO and :MINUTO_FIM and
  INICIO_LOG Between :DATA_INICIO and :DATA_FIM
No código da aplicação usamos algum componente do tipo TDateTimePicker ou o que você quiser para solicitar os intervalos ao

usuário e calculamos o valor em minutos usando uma função:
function TVisualizaLogs.CalcMinutos(aDate: TDateTime): Integer;
var
  H, M, S, MS: Word;
begin
  DecodeTime(aDate, H, M, S, MS);
  Result := H * 60 + M;
end;
Passamos os parâmetros para nosso componente de acesso a dados da forma usual e o resto você já sabe.
ParamByName('MINUTO_INICIO').AsInteger := CalcMinutos(dtpInicio.Date);
ParamByName('MINUTO_FIM').AsInteger := CalcMinutos(dtpFim.Date);
ParamByName('DATA_INICIO').AsInteger := dtpInicio.Date;
ParamByName('DATA_FIM').AsInteger := dtpFim.Date;

Bom proveito.

19 de out. de 2012

Como remover algumas units de seu processo de Debug

Em um post recente da lista de discussão [lista-delphi] do yahoo, alguém perguntou como é possível remover units do processo de debug, principalmente units de terceiros, como por exemplo IBO e DevExpress.

A razão para isso é que o processo de debugar seu código com essas units fica realmente um porre e a melhor coisa é mesmo não ter que passar por essas units.

Uma das formas de fazer isso é incluir a diretiva de compilação {$-D} na unit que você não quer debugar. Isso vai ser mais ou menos simples de se fazer se forem apenas units do seu projeto. Agora, imagine fazer isso com as units da DevExpress ou IBO ou outra biblioteca qualquer.

Apenas remover as units (.pas) também não adianta, pois o Delphi vai procurar por esses arquivos na hora de debugar, já que o EXE contém essas informações de debug.

Uma solução simples pra isso é compilar tudo sem informação de debuger:
  • Vá em Project Options > Compiling > Debugging e desmarque as opções de debug
  • Dê um build all: nesse momento suas DCUS não terão mais a informação de debug.
  • Retire do Search Path/Lib Path as units (*.pas apenas) que vc não quer mais debugar (IBO, DevExpress, etc) 
  • Vá novamente em Project Options > Compiling > Debugging e marque novamente as opções de debug 
  • Dê um Build all (ou vc pode apenas compilar as units que vc quer debugar) 
A partir de agora você poderá debugar tranquilamente sem ter que se preocupar com as units de terceiros.

Veja que a própria IDE aplica essa técnica (Project Options > Compiling > Debugging > Use Debug Dcus) para as units da VCL: na pasta Lib tem DCUs para Debug e Release e a opção "Use Debug Dcus" indica ao linker qual diretório usar na hora de gerar o Executável de seu projeto.

Bom proveito.

27 de jul. de 2010

Enviando e-mails com Indy através de uma conta do GMail

Além de toda a parafernália que a gente já sabe, para enviar emails pro Gmail, você precisa acrescentar as seguinte linhas:
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
with SSL do begin
  Destination := SMTPHost + ':' + IntToStr(SMTPPort);
  Host := SMTPHost;
  MaxLineAction := maException;
  Port := SMTPPort;
  DefaultPort := 0;
  SSLOptions.Method := sslvTLSv1;
  SSLOptions.Mode := sslmUnassigned;
  SSLOptions.VerifyMode := [];
  SSLOptions.VerifyDepth := 0;
end;
SMTP.IOHandler := SSL;
SMTP.UseTLS := utUseExplicitTLS;
SMTP.UserName := SMTPUser;
SMTP.Password := SMTPPassword;

Porquê? Porque para enviar emails via Gmail, só via conexão segura, SSL (sslvTLSv1) .Nesse caso, as DLLs do OpenSSL tem de estar disponiveis pra sua aplicação.

Pra baixar o OpenSSL que rode com o Indy, vá em http://indy.fulgan.com/SSL/ e baixe de acordo com sua versão do Indy. Eu uso a versão OpenSSL 0.9.8h juntamente com o Indy que vem no Delphi 2007 e funciona bem. A unica limitação que achei foi fazer funcionar numa DLL ISAPI sob o IIS, pelo fato de que o IIS já tem seu próprio SSL.

Bom proveito.

26 de jan. de 2010

Carregando uma imagem no banco de dados

Faz tempo que não tem postagem nova, então vamos lá. Uma dica que resolve uma pergunta recorrente em alguns fórums de Delphi.

Como fazer pra gravar uma imagem num campo Blob? Fiz uma função para isso, a seguir:
procedure LoadPictureToDataset(FileName: TFileName; Dataset: TDataset; PictureFieldName: String);
begin
if StrIsEmpty(FileName) then
raise Exception.Create('Nome de arquivo não pode ser vazio.');
Assert(Dataset <> Nil);
Assert(Dataset.FindField(PictureFieldName) <> Nil, 'Nome de campo inválido: ' + PictureFieldName);
Assert(not (Dataset.FieldByName(PictureFieldName) is TGraphicField), 'Campo ' + PictureFieldName + ' não suporta imagens');
TBlobField(Dataset.FieldByName(PictureFieldName)).LoadFromFile(FileName);
end;

30 de jun. de 2009

Select do Select do Select

Você sabia que pode fazer um select em um resultado de outro select dentro do mesmo SQL? Provavelmente muita gente não conhece esse recurso. Até a um bom tempo atrás eu também não conhecia.

Esse recurso permite fazer coisas interessantes sobre result sets de SQLs complexos. Você pode, por exemplo, agrupar dados, fazer joins com outras tabelas, usar funções aggregates, dentre outras coisas.

Tomemos como exemplo o sequinte SQL hipotético:
select id_cliente, nome,
  case
    when situacao = 'I' then 1
    when situacao = 'X' then 2
    when situacao = 'A' then 3
  end id_situacao
from cliente
Digamos que você queira contar quantos clientes existem para cada nova situação. Fazer isso no SQL acima o tornaria um pouco mais complexo. Usando o recurso do select sobre um result set, torna a tarefa bem mais fácil:
select count(t1.id_situacao), s.ds_situacao from
(
select id_cliente, nome,
  case
    when situacao = 'I' then 1
    when situacao = 'X' then 2
    when situacao = 'A' then 3
  end id_situacao
from cliente
) t1
inner join situacao s on s.id_situacao = t1.id_situacao
Essa sintaxe acima funciona tanto no MS-SQL Server quanto no Oracle e acredito que também funcione no Firebird.

Bom proveito...

24 de nov. de 2008

Debugando projetos Intraweb, a forma fácil

Geralmente, projetos Intraweb vão ser usados em forma de DLL, e a maioria das pessoas começa seu projeto IW escolhendo ISAPI Extension no Application Wizard do IW. O problema com ISAPI é a dificuldade em debugar tais DLLs. Existem alguns truques que envolvem ISS, COM e outras parafernálias que funcionam, mas existe uma forma bem mais simples.

A "técnica" consiste em termos 2 projetos. O primeiro deles é a própria DLL, que vai ser a aplicação a ser distribuida. O segundo projeto é uma versão Stand Alone Server da DLL. O Stand Alone Server é um executável que já tras seu próprio webserver embutido, facilitado o processo de debug, já que não é necessário configurar nada.


Com os dois projetos, à medida que você cria novas units para a DLL, adicione-as ao projeto de teste (o Stand Alone Server). O contrário também é válido, e é o que eu costumo fazer. Crio as novas units no projeto de teste e vou adicionando ao projeto principal.

Para debugar, basta executar o projeto do Stand Alone Server a partir da IDE do Delphi/CBuilder e colocar seus breakpoints normalmente. O resto da história você já sabe.

Uma coisa importante é configurar os Outputs (Output Directory e Unit Output Directory) do projeto de teste para o mesmo diretório da DLL ISAPI, caso você tenha os 2 projetos em diretórios distintos (como é o meu caso). Dessa forma, alguma unit que você esqueça de adicionar ao projeto sempre será linkada com a última compilação, além de não termos DCUs duplicadas. Outra coisa é que você pode compartilhar arquivos entre os dois projeto (imagens, Templates, etc).

Crie também um Project Group e adicione seus dois projetos. Isso facilita na hora de compilar.

É isso aí, apenas uma pequena dica que pode ser útil pra muite gente.

Bom proveito.