quarta-feira, 13 de junho de 2007

Compilação Condicional - Modo Debug e Modo Release.

Quando você compila sua aplicação tem duas opções, compilar em modo debug ou modo release (Caso não saiba, essa opção fica ao lado do botão Start Debuggin, o "play").

A idéia é compilar em modo debug enquanto estiver desenvolvendo e depurando a aplicação, e em modo release quando for colocar o aplicativo em produção , pois para depurar o executável, o compilador precisa embutir nele algumas informações extras, como nome do arquivo fonte e número da linha. Como você dificilmente irá depurar diretamente o aplicativo em produção, essas informações podem ser removidas para otimizar o aplicativo.

Além dessa otimização que o próprio compilador faz, o próprio programador pode especificar uma determinada parte do código que só será executada em um modo específico. Por exemplo, você quer escrever uma rotina de tratamento de erros que não mostre a mensagem de erro original para o usuário, pode fazer algo do tipo:

try
{
// Código
}
catch(Exception ex)
{
#if DEBUG
MessageBox.Show(ex.Message);
#else
MessageBox.Show("Ocorreu um erro no sistema!");
#endif
}

No código acima , o primeiro comando MessageBox será executado se o programa for compilado em modo DEBUG, e o segundo se a aplicação for compilada em modo Release.

Além disse, você pode usar o Atributo Conditional para excluir uma determinada função do modo release. Se você declarar uma função dessa forma :


[System.Diagnostics.Conditional("DEBUG")]
private void Funcao()

Essa função só será considerada se estiver em modo DEBUG, caso contrário , será ignorada. A vantagem nesse caso, é que você não precisa alterar os pontos do códigos que chamam a função, somente a própria função.

terça-feira, 12 de junho de 2007

Stopwatch

Existe uma classe simples mas útil no namespace System.Diagnostics chamada Stopwatch. Essa classe simula um cronômetro e pode ser usada, por exemplo, para medir o tempo gasto por determinada operação. Por exemplo, você quer saber quanto tempo determinada função está demorando para executar, pode fazer isso:

Stopwatch sw = new Stopwatch();
sw.Start();
OperacaoDemorada();
sw.Stop();
Debug.WriteLine("Tempo gasto : " + sw.ElapsedMilliseconds.ToString() + " ms");


O código acima irá mostrar o tempo gasto em milisegundos, mas a classe também possui a propriedade Elapsed, que retorna um TimeSpan, permitindo a obtenção do tempo na unidade que você quiser.

domingo, 3 de junho de 2007

Acessando uma classe .Net via COM

A frequência de atualização desse blog tem sido baixa, mas ele ainda vive...rs. Vou tentar atualizá-lo com mais frequência. Dica: Para você saber quando há uma atualização, utilize um leitor RSS, como o FeedReader: http://www.feedreader.com/

Agora ao artigo.

Quem já trabalhou com ASP ou VB (os antigos, não-.Net), provavelmente já usou um comando como esse:
set obj = CreateObject("Dundas.Upload")
Deixando erros de sintaxe de lado (Escrevi só como exemplo, vai), esse comando permite criar objetos COM para acessar em sua aplicação. Você sabia que é possível chamar uma classe .NET dessa forma?

A vantagem é que com isso é possível acessar uma dll em .Net de uma aplicação ASP tradicional, VB 6 ou qualquer outra plataforma que suporte COM. Isso pode facilitar a transição parcial de um sistema para a plataforma .Net.

Passarei aqui as instruções para o Visual Studio 2005, mas isso também é possível no 2003. Em primeiro lugar é necessário adicionar uma strong name key ao seu projeto. Caso não saiba como fazer isso, procure por Strong Name Key no google que deve achar bastante coisa sobre o assunto. Também é necessário que todas as DLLs às quais a sua faça referência tenham um strong name key. Agora é só compilar e registrar a DLL.

Para registrá-la, use o utilitário de linha de comando Regasm.exe , com a seguinte sintaxe :
RegAsm.exe NomeDoArquivo.dll /tlb /codebase
Não sei te dizer exatamente o que fazem os parâmetro /tlb e /codebase, mas sei que sem eles não funciona :P (Quem souber e quiser explicar, fique a vontade e poste um comentário. ;) ). Como qualquer outro utilitário do .Net, o RegAsm.exe está na pasta do framework (e pode ser acessado diretamente se utilizado o atalho para o prompt de comando criado pelo visual studio no menu iniciar).

Após registrada a DLL, é só acessá-la do ASP ou VB como se fosse um objeto COM. Na string de identificação da classe, use o namespace seguido do nome da classe. No exemplo abaixo , está sendo chamada a classe TesteCOM do namespace Br1.Library.Teste:
set obj = CreateObject("Br1.Library.Teste.TesteCOM").

Algumas observações importantes:
  • Isso obviamente não elimina a necessidade do Framework, ele deve estar instalado na máquina onde o objeto COM for executado.
  • A DLL chamará as outras como qualquer objeto .Net, então as dlls às quais ela faz referência devem estar ou no mesmo diretório ou no GAC.
  • Só consegui fazer funcionar a DLL com tipos primitivos nos parâmetros e retorno. Internamente podem ser usadas classes e structs sem problema, mas a função que será chamada externamente só poder receber e retornar tipos primitivos, como string ou int.
  • Como qualquer objeto COM, depois da primeira chamada, a DLL vai estar carregada na memória. Portanto, para substituir a DLL pode ser necessário reiniciar o ISS. Sugiro registrar a DLL de outro local, para não dar erro quando o VS não conseguir compilá-la devido à dll em bin\debug estar em uso. Sugiro criar um .BAT para a atualização, com os seguintes passos:
  1. Reiniciar o iis (use o iisreset.exe)
  2. Desregistrar a DLL com o comando : Regasm.exe NomeDoArquivo.dll /unregister
  3. Excluir os arquivos .DLL e .PDB do diretório de registro.
  4. Copiar os arquivos .DLL e .PDB do diretório bin\debug (ou bin\release, se preferir)
  5. Registrar a DLL novamente com o comando que já passei.

Essa abordagem pode ser bem interessante para ir convertendo aos poucos um sistema para .Net, ou então para incrementar um sistema já existente.