MSDN Magazine Dezembro/2007
A MSDN Magazine de Dezembro já está disponível no site da Microsoft. Destaque para uso do WCF, WPF e LINQ com o Office e, na coluna Cutting Edge, uma visão geral do Microsoft AJAX.
Polindo bits e bytes todos os dias!
A MSDN Magazine de Dezembro já está disponível no site da Microsoft. Destaque para uso do WCF, WPF e LINQ com o Office e, na coluna Cutting Edge, uma visão geral do Microsoft AJAX.
Postado por Massuda às 14:24 0 comentários
Marcadores: geral
Atualizei hoje meu artigo Como enviar email usando Indy 10. Indy 10 é uma versão que está em desenvolvimento. Entre o dia que escrevi o artigo e hoje, a implementação dos mecanismos de autenticação do servidor SMTP sofreu algumas alterações que simplemente o código exemplo original deixou de funcionar. Pessoalmente, acho problemático adotar o Indy 10 em código de produção, já que é frequente ocorrer esse tipo de problema. A versão que acompanha tanto o BDS2006 como o BDS2007 tem incontáveis bugs (isso não significa que a versão mais recente não tenha bugs). O recomendável é usar a versão snapshot disponível no site indy.fulgan.com (arquivo Indy10.zip). Para atualizar o Indy, primeiro desinstale o Indy que veio com o Delphi, usando para isso o programa de instalação do Delphi. Para instalar a nova versão, siga as instruções disponíveis na página Indy 10 Installation Instructions do site oficial do Indy.
Postado por Massuda às 15:51 0 comentários
Marcadores: delphi
A MSDN Magazine de Novembro já está disponível no site da Microsoft. Destaque para segurança.
Outro destaque é que agora você pode baixar a versão CHM da revista em português.
Postado por Massuda às 09:59 0 comentários
Marcadores: geral
A MSDN Magazine de Outubro está disponível no site da Microsoft. Destaque para otimização de código gerenciado em máquinas com vários núcleos.
Postado por Massuda às 09:44 0 comentários
Marcadores: geral
O Horário Brasileiro de Verão começa à zero hora do dia 14 de outubro, quando os relógios deverão ser adiantados em uma hora, e devem ficar assim, até às 24 horas do dia 16 de fevereiro de 2008, quando os relógios deverão ser atrasados em uma hora.
O horário de verão abrange o Distrito Federal os estados do Rio Grande do Sul, Santa Catarina, Paraná, São Paulo, Rio de Janeiro, Espírito Santo, Minas Gerais, Goiás, Mato Grosso e Mato Grosso do Sul.
Atualizado em 13/10/2007
Para ajustar o horário de verão do Windows, no site da Microsoft tem um aviso informando que os usuários devem solicitar o envio de um hotfix (KB 943000).
Para quem tem pressa, o melhor é dar uma olhada no KB 317211, Como configurar as datas do horário de verão para o Brasil, que explica vários métodos para fazer o ajuste necessário. Note que esse KB refere-se ao horário de verão 2006/2007, portanto as datas que devem ser utilizadas não são as citadas no KB.
Postado por Massuda às 09:05 0 comentários
Marcadores: geral
A MSDN Magazine de Setembro já está disponível no site da Microsoft. Destaque para sockets no framework 3.5 (incluindo P2P) e testes unitários.
Postado por Massuda às 15:10 0 comentários
Marcadores: geral
A MSDN Magazine de Agosto já está disponível no site da Microsoft. Destaque para o novo padrão de empacotamento de dados OPC (Open Packaging Conventions) e um comparativo entre VSTO e VBA na automação do Office.
Postado por Massuda às 15:29 0 comentários
Marcadores: geral
A MSDN Magazine de Julho já está disponível no site da Microsoft. Destaque para compartilhamento de código entre aplicativos desktop e móveis e suporte ao reconhecimento de fala do Windows Vista.
Postado por Massuda às 08:27 0 comentários
Marcadores: geral
A MSDN Magazine de Junho já está disponível no site da Microsoft. Destaque para as novidades nas ferramentas C#, VB e C++ e o novo SilverLight, uma ferramenta para desenvolvimento web/multiplataforma.
Postado por Massuda às 11:29 0 comentários
Marcadores: geral
A MSDN Magazine de Maio já está disponível no site da Microsoft. Destaque para JavaScript e o novo XNA Game Studio Express, a ferramenta de desenvolvimento gratuita para o XBox.
Postado por Massuda às 08:59 0 comentários
Marcadores: geral
Este exemplo mostra como enviar emails usando Indy10.
1 var 2 Email: TIdMessage; 3 begin 4 // SMTP é um TIdSMTP 5 // POP3 é um TIdPOP3 6 // UserPassProvider é um TIdUserPassProvider 7 8 Email := TIdMessage.Create(nil); 9 try 10 11 // ...ajusta remetente, destinatário, etc da mensagem... 12 Email.Subject := '...assunto...'; 13 Email.From.Address := 'remetente@mailinator.com'; 14 Email.Recipients.EMailAddresses := 'destinatario@mailinator.com'; 15 Email.Body.Text := '...texto da mensagem...'; 16 17 // conecta com o servidor POP3 18 // alguns provedores exigem isso 19 POP3.Host := 'seu-servidor-pop3'; 20 POP3.Username := 'seu-username'; 21 POP3.Password := 'sua-senha-secreta'; 22 POP3.Connect; 23 24 try 25 SMTP.Host := 'seu-servidor-smtp'; 26 27 // alguns servidores SMTP exigem login 28 SMTP.AuthType := satSASL; 29 UserPassProvider.Username := 'seu-username'; 30 UserPassProvider.Password := 'sua-senha-secreta'; 31 32 SMTP.Connect; 33 try 34 SMTP.Send(Email); 35 except 36 on E: Exception do begin 37 // o envio falhou, trata o erro 38 end; 39 end; 40 SMTP.Disconnect; 41 finally 42 POP3.Disconnect; 43 end; 44 finally 45 Email.Free; 46 end; 47 end;
Pontos importantes:
Atualizado em 15/11/2007 Indy 10 é uma versão que está em desenvolvimento. Este código funciona usando a versão snapshot (Indy10.zip disponível no site indy.fulgan.com) de 15/11/2007; a versão snapshot é atualizada todos os dias, de modo que não posso garantir que vá funcionar sempre. De qualquer forma, o exemplo foi atualizado e está funcionando novamente.
Postado por Massuda às 10:49 0 comentários
UDP é um protocolo de transporte de dados que se caracteriza por não garantir a entrega dos dados, o que permite entregar rapidamente os dados. Um uso frequente para UDP é transmissão de áudio ou vídeo, que é um caso onde a perda de um pacote de dados não compromete o resultado final.
Uma outra característica do protocolo UDP é a possibilidade de transmitir um mesmo pacote de dados para todas as máquina da rede em uma única operação, o que é conhecido como broadcast. Nesse caso, os dados são enviados por UDP para um endereço especial da rede que replicará o mesmo pacote de dados para todos os endereços da mesma subrede.
Um uso possível seria localizar numa rede local todas as máquinas que estão executando seu programa. Para isso, uma cópia do programa poderia iniciar um broadcast na rede pedindo que todas as outras cópias (em uso) do programa se identifiquem, por exemplo, informando o nome da máquina e o IP.
Usando os componentes TIdUDPClient e TIdUDPServer, o código seria algo assim:
1 type 2 TSeuForm = class(...) 3 // coloque um TIdUDPClient e TIdUDPServer no form 4 // por exemplo... 5 UDPClient: TIdUDPClient; 6 UDPServer: TIdUDPServer; 7 ... 8 procedure FormCreate(Sender: TObject); 9 procedure FormDestroy(Sender: TObject); 10 procedure UDPServerUDPRead(Sender: TObject; AData: TStream; 11 ABinding: TIdSocketHandle); 12 ... 13 private 14 procedure Ping; 15 ... 16 17 const 18 NOSSA_PORTA = 49152; // pode ser qualquer valor entre 49152 e 65535 19 20 // rotina de PING 21 // em algum lugar do programa isso é executado 22 procedure TSeuForm.Ping; 23 var 24 S: string; 25 IP: string; 26 X: Integer; 27 begin 28 // não queremos responder nosso próprio comando 29 UDPServer.Active := False; 30 31 // timeout da resposta, em milissegundos 32 UDPClient.ReceiveTimeout := 5000; 33 34 // manda o comando para todas as máquinas da rede 35 UDPClient.Broadcast('PING', NOSSA_PORTA); 36 37 // espera pela resposta 38 while True do begin 39 40 S := UDPClient.ReceiveString(IP, X); 41 if S = '' then begin 42 // ocorreu timeout 43 Break; 44 end; 45 // faz alguma coisa com os dados... 46 // - S tem o nome da máquina que respondeu 47 // - IP tem o IP da máquina que respondeu 48 end; 49 50 UDPServer.Active := True; 51 end; 52 53 // evento OnUDPRead do UDPServer 54 procedure TSeuForm.UDPServerUDPRead(Sender: TObject; AData: TStream; 55 ABinding: TIdSocketHandle); 56 var 57 Server: TIdUDPServer; 58 S: String; 59 begin 60 Server := Sender as TIdUDPServer; 61 62 // recupera o que recebeu 63 SetLength(S, AData.Size); 64 AData.Read(S[1], AData.Size); 65 66 // é o nosso comando de PING? 67 if S = 'PING' then begin 68 69 // envia a resposta 70 S := Server.LocalName; 71 ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, S[1], Length(S)); 72 end; 73 end; 74 75 // evento OnCreate do form 76 procedure TSeuForm.FormCreate(Sender: TObject); 77 begin 78 UDPServer.DefaultPort := NOSSA_PORTA; 79 UDPServer.Active := True; 80 ... 81 end; 82 83 // evento OnDestroy do form 84 procedure TSeuForm.FormDestroy(Sender: TObject); 85 begin 86 UDPServer.Active := False; 87 ... 88 end;
Para evitar conflitos com outros programas e serviços do Windows, procure escolher uma porta (linha 18) entre 49152 e 65535. Independente da porta escolhida, lembre-se que essa porta precisa estar liberada para UDP no seu firewall.
O valor de timeout usado na rotina de ping (linha 32) precisa ser ajustado de acordo com o tamanho da rede. Um valor muito pequeno pode fazer com que a rotina de ping desista antes que todas as máquinas respondam e um valor muito alto pode congelar momentaneamente o programa. Não tem outra forma de aguardar pela resposta das máquinas já que, a princípio, a rotina não sabe quantas máquinas vão responder.
Broadcast deve ser usado com moderação. O broadcast utiliza um endereço especial da rede para transmitir os dados que faz com que o mesmo pacote de dados seja enviado a todos os endereços possíveis da rede. Como isso consome recursos da rede, não é boa idéia utilizar isso sem que seja absolutamente necessário. É tentador colocar a rotina de ping num timer que executa a cada segundo, mas o administrador da sua rede não vai ficar muito feliz com essa idéia.
Eu não entendo muito de redes, mas é bom saber que alguns roteadores podem impedir o broadcast.
Links relacionados
Postado por Massuda às 23:13 1 comentários
A MSDN Magazine de Abril já está disponível no site da Microsoft. Destaque para efeitos especiais com o novo gerenciador de janelas Aero Glass do Windows Vista e um pequeno analisador/parser XML em C++.
Postado por Massuda às 09:20 0 comentários
Marcadores: geral
Complementando meu post anterior sobre como enviar email usando C#, eis um exemplo interessante que encontrei uns tempos atrás (adaptado para facilitar o entendimento) mostrando como enviar email pelo GMail...
Toda a comunicação com os servidores do GMail (tanto SMTP como POP3) é tunelada através de uma conexão criptografada.1 using System; 2 using System.Net; 3 using System.Net.Mail; 4 5 namespace GMailSample { 6 7 class SimpleSmtpSend { 8 9 static void Main(string[] args) { 10 11 SmtpClient cliente = new SmtpClient("smtp.gmail.com", 587 /* TLS */); 12 cliente.EnableSsl = true; 13 14 MailAddress remetente = new MailAddress( 15 "sua.conta@gmail.com", "Seu Nome"); 16 MailAddress destinatario = new MailAddress( 17 "fulano@mailinator.com", "Fulano"); 18 19 MailMessage mensagem = new MailMessage(remetente, destinatario); 20 21 mensagem.Body = "Exemplo de mensagem via GMail"; 22 mensagem.Subject = "Teste do Gmail com SSL e Credenciais"; 23 24 NetworkCredential credenciais = new NetworkCredential( 25 "sua.conta@gmail.com", /* login */ 26 "sua.senha.secreta", /* senha */ 27 ""); 28 29 cliente.Credentials = credenciais; 30 31 Console.WriteLine("Enviando..."); 32 33 try { 34 cliente.Send(mensagem); 35 Console.WriteLine("OK"); 36 } 37 catch (Exception e) { 38 Console.WriteLine("Exceção:" + e.ToString()); 39 } 40 } 41 } 42 }
Postado por Massuda às 08:57 7 comentários
Marcadores: c#
O exemplo seguinte usa .NET 2.0 e pode ser usado em projetos WinForms ou ASP.NET. Ele mostra o envio de email usando um cliente SMTP.
1 using System; 2 using System.Net; 3 using System.Net.Mail; 4 5 ... 6 // monta a mensagem 7 MailAddress to = new MailAddress("email-do-destinatario"); 8 MailAddress from = new MailAddress("email-do-remetente"); 9 MailMessage mensagem = new MailMessage(from, to); 10 mensagem.Subject = "Teste"; 11 mensagem.Body = "Mensagem de teste"; 12 13 SmtpClient cliente = new SmtpClient("seu-servidor-SMTP"); 14 15 // dados para autenticação 16 cliente.Credentials = 17 new NetworkCredential("seu-username", "sua-senha-secreta"); 18 19 // envia a mensagem 20 try { 21 cliente.Send(mensagem); 22 } 23 catch (Exception ex) { 24 // trata a exceção 25 } 26 ...
Sobre o código:
Pontos importantes:
Tópico atualizado em 09/05/2007: pequena correção na criação da mensagem.
Postado por Massuda às 09:24 0 comentários
Marcadores: c#
Uma das coisas mais desagradáveis é testar um programa, instalar ele no cliente e ele cair com uma exceção no meio da demonstração. Na máquina de desenvolvimento, a IDE gentilmente mostra onde a exceção foi gerada. Mas no cliente, não.
Na JCL (Jedi Code Library) existe uma unit chamada JclDebug que deve ser usada em conjunto com o mecanismo do JCL para tratamento de exceções não tratadas. Esse mecanismo consiste basicamente em determinar onde a exceção foi gerada (em qual linha, função/procedure e unit) bem como gerar um dump da pilha do programa, o que permite ter uma idéia da sequência de processamento que resultou na exceção.
A documentação da JCL não é muito clara sobre como usar esse mecanismo. O problema maior é saber como preparar o executável para poder usar o mecanismo. Esta é a "receita do bolo":
Links relacionados
Postado por Massuda às 00:46 0 comentários
Marcadores: delphi
A MSDN Magazine de Março já está disponível no site da Microsoft. Destaque para o IIS 7.0 e o MS Build.
Postado por Massuda às 22:27 0 comentários
Marcadores: geral
Este exemplo mostra como fazer uma busca incremental num combobox.
1 procedure TSeuForm.SeuComboBoxKeyPress(Sender: TObject; var AKey: Char); 2 var 3 ComboBox: TComboBox; 4 TextoDigitado: string; 5 TextoSelecionado: string; 6 TextoDoItem: string; 7 Texto: string; 8 Achou: Boolean; 9 Inicio: Integer; 10 I: Integer; 11 begin 12 ComboBox := Sender as TComboBox; 13 14 // recupera o que foi digitado 15 16 Inicio := ComboBox.SelStart; 17 18 // trata a tecla 19 TextoDigitado := Copy(ComboBox.Text, 1, ComboBox.SelStart); 20 if AKey = Chr(VK_BACK) then begin 21 22 if ComboBox.SelLength = 0 then begin 23 24 Delete(TextoDigitado, Length(TextoDigitado), 1); 25 end; 26 end 27 else begin 28 TextoDigitado := TextoDigitado + AKey; 29 end; 30 31 TextoSelecionado := Copy(ComboBox.Text, 32 ComboBox.SelLength + ComboBox.SelStart + 1, MaxInt); 33 34 Texto := TextoDigitado + TextoSelecionado; 35 if Texto <> '' then begin 36 37 // atualiza a posição de início da seleção 38 if AKey = Chr(VK_BACK) then begin 39 40 if Inicio > 0 then begin 41 42 Dec(Inicio); 43 end; 44 end 45 else if AKey <> Chr(VK_BACK) then begin 46 47 Inc(Inicio); 48 end; 49 50 // descarta a tecla 51 AKey := #0; 52 53 if Inicio = 0 then begin 54 55 ComboBox.Text := ''; 56 ComboBox.ItemIndex := -1; 57 end 58 else begin 59 60 // busca o texto 61 62 Achou := False; 63 for I := 0 to Pred(ComboBox.Items.Count) do begin 64 65 TextoDoItem := Copy(ComboBox.Items[I], 1, Length(Texto)); 66 Achou := AnsiCompareText(TextoDoItem, Texto) = 0; 67 if Achou then begin 68 69 ComboBox.Text := ComboBox.Items[I]; 70 ComboBox.ItemIndex := I; 71 72 Break; 73 end; 74 end; 75 76 if Achou then begin 77 78 // destaca a parte não digitada da string 79 ComboBox.SelStart := Inicio; 80 ComboBox.SelLength := Length(ComboBox.Text) - Inicio; 81 end 82 else begin 83 84 // beepa para avisar que não encontrou 85 Beep; 86 end; 87 end; 88 end; 89 end;
Postado por Massuda às 22:41 0 comentários
Marcadores: delphi
Com frequência vejo pessoas tentando medir o consumo de memória de um programa feito em Delphi usando o Gerenciador de Tarefas do Windows. Por motivos técnicos, essa não é a melhor forma de medir o consumo de memória do programa.
A grosso modo, o Gerenciador de Tarefas mede o máximo de memória seu programa alocou, não o quanto ele está usando; para piorar a memória que é liberada de volta para o Windows mas que ainda não foi utilizada por outro aplicativo é contabilizada nesse total pois essa memória disponível é considerada pelo Windows como disponível para uso pelo seu programa, embora ela possa ser usada por qualquer programa.
Um dos motivos que a informação do Gerenciador de Tarefas estar errada é que um programa em Delphi aloca indiretamente memória do Windows, através de um gerenciador de memória do runtime do Delphi.
Quando o programa solicita memória para o gerenciador, ele aloca blocos de memória para o programa. Os blocos tem tamanho fixo de modo que para cada pedido de memória o gerenciador aloca a quantidade necessária de blocos contínuos para satisfazer o pedido do programa. Logo, um bloco é a menor quantidade de bytes que o gerenciador aloca. Por exemplo, imagine que cada bloco tem 32 bytes; se o programa pede 4 bytes, o gerenciador irá alocar um bloco; se o programa pedir 40 bytes, o gerenciador irá alocar dois blocos.
Pode parecer desperdício, mas isso é feito para evitar a fragmentação da memória. A fragmentação ocorre quando, apesar de haver memória livre para atender a um pedido de memória, não existem blocos contínuos suficientes para atender à solicitação. Caso o gerenciador fique sem blocos disponíveis para atender uma solicitação do programa, ele irá solicitar mais memória ao Windows.
Quando o programa devolve memória para o gerenciador, ele não devolve totalmente ao Windows a memória que você alocou porque ele imagina que o programa vai requisitar novamente mais memória. Isso é feito para otimizar os tempos de alocação de memória.
Vamos imaginar que inicialmente o programa alocou 100 blocos de memória do gerenciador. O programa cria algum form e precisa de mais 20 blocos de memória; o gerenciador irá providenciar 20 blocos de memória do Windows para poder atender a solicitação; nesse momento, o programa tem alocado 120 blocos de memória.
Quando o form é destruído e a memória devolvida ao gerenciador, ele irá marcar os 20 blocos de memória que foram usados pelo form como sendo disponíveis. O programa continua usando 120 blocos. Imagine que o programa crie outro form que precise de 10 blocos; como tem 20 disponíveis, o gerenciador não pede memória para o Windows, ele usa 10 dos 20 disponíveis.
Um desses gerenciadores de memória alternativos é o FastMM. Esse gerenciador é um dos mais rápidos e baseia-se na idéia de que um programa costuma alocar com mais frequencia pequenas quantidades de memória do que gransdes quantidades. Partindo dessa idéia, o FastMM usa três diferentes estratégias de gerenciamento de memória, dependendo da quantidade de memória que o programa pede. O resultado é que programas que criam/destroem muitos objetos tem desempenho melhor com o FastMM.
A Borland reconheceu a qualidade do FastMM e adotou o FastMM como gerenciador padrão de memória do Delphi 2006. Para quem não tem o Delphi 2006 mas gostaria de experimentar, visite a página do FastMM no SourceForge.net (baixe a versão 4.x mais recente, as versões antigas 2.x e 3.x estão lá apenas para quem mantem programas que usam essas versões)
Para quem usa Delphi 2005 ou anterior é simples saber quantos blocos o gerenciador de memória pegou do Windows e quanto de memória seu programa está consumindo através do gerenciador de memória:
1 var 2 Blocos: Integer; 3 Bytes: Integer; 4 ... 5 Blocos := AllocMemCount; 6 Bytes := AllocMemSize;
Para quem usa Delphi 2006 ou usa o FastMM ao invés do gerenciador de memória padrão, o cálculo é um pouco mais trabalhoso:
1 var 2 Estado: TMemoryManagerState; 3 Blocos: Integer; 4 Bytes: Integer; 5 I: Integer; 6 ... 7 Blocos := 0; 8 Bytes := 0; 9 10 GetMemoryManagerState(Estado); 11 12 for I := 0 to High(Estado.SmallBlockTypeStates) do begin 13 14 Inc(Blocos, Estado.SmallBlockTypeStates[I].AllocatedBlockCount); 15 Inc(Bytes, Estado.SmallBlockTypeStates[I].AllocatedBlockCount 16 * Estado.SmallBlockTypeStates[I].UseableBlockSize); 17 end; 18 19 Inc(Blocos, Estado.AllocatedMediumBlockCount); 20 Inc(Bytes, Estado.TotalAllocatedMediumBlockSize); 21 22 Inc(Blocos, Estado.AllocatedLargeBlockCount); 23 Inc(Bytes, Estado.TotalAllocatedLargeBlockSize); 24 ...
Quem estiver usando o FastMM, deve incluir no uses da unit que contem esse código a unit FastMM4 (ou FastMM3, se for o caso).
Uma diferença do FastMM para o gerenciador de memória usado até o Delphi 2005 é que o FastMM tem diferentes estratégias de gerenciamento da memória conforme o tamanho do bloco de memória a ser alocado. Por isso, o código para calcular o consumo de memória é um pouco mais complicado.
Em ambos os casos, Blocos é o total de blocos de memória alocados pelo gerenciador e Bytes é a quantidade de memória que o programa está usando.
Links relacionados
Postado por Massuda às 22:18 0 comentários
Marcadores: delphi
Desde o Windows 2000 o Windows é capaz de detectar aplicações que estejam congeladas/travadas. Essa detecção se baseia na idéia de que um aplicativo está congelado/travado se...
É graças a essa capacidade que o Windows consegue dar o aviso de que "tal aplicativo não está respondendo".
O Windows XP SP1 adicionou a capacidade de ghosting: ao detectar que um aplicativo não está respondendo (está congelado/travado), o Windows cria uma janela fantasma na mesma posição, com o mesmo tamanho e os mesmos atributos da janela do aplicativo que não está respondendo. Isso permite ao usuário minimizar, maximizar e mover a janela ou até mesmo fechar o aplicativo.
Caso o aplicativo volte a responder, o Windows restaura a janela do aplicativo na mesma posição, com o mesmo tamanho e os mesmos atributos da janela fantasma que foi criada enquanto o aplicativo não respondia.
Sem a janela fantasma, o que o usuário vê na maior parte dos casos é uma janela em branco ou contendo partes de outras janelas que eventualmente tenham sidos postas sobre a janela do aplicativo que não está respondendo. Teoricamente, a janela fantasma dá ao usuário a impressão que o aplicativo está funcionando "normalmente".
Infelizmente, no caso do Delphi, isso causa problemas com forms exibidos usando ShowModal quando o Windows restaura a janela do aplicativo. O form mostrado com ShowModal pode ficar atrás do form principal do aplicativo.
Se estiver tendo esse tipo de problema, inclua a procedure seguinte na unit do seu form principal (nem precisa ser método do form) e execute-a no evento OnCreate do form principal:
1 procedure DesabilitarGhostingDoWindows; 2 var 3 User32: HMODULE; 4 DisableProcessWindowsGhosting: TProcedure; 5 begin 6 User32 := GetModuleHandle('USER32'); 7 if User32 <> 0 then begin 8 DisableProcessWindowsGhosting := 9 GetProcAddress(User32, 'DisableProcessWindowsGhosting'); 10 if Assigned(DisableProcessWindowsGhosting) then begin 11 DisableProcessWindowsGhosting; 12 end; 13 end; 14 end;
Tópicos relacionados no MSDN...
Postado por Massuda às 12:22 0 comentários
Marcadores: delphi
Este exemplo mostra como percorrer as pastas do sistema de arquivos:
1 using System;
2 using System.IO;
3
4 public class Exemplo {
5
6 public static void PercorrerPasta(string oNomeDaPasta) {
7
8 DirectoryInfo dir = new DirectoryInfo(oNomeDaPasta);
9
10 // processa eventuais subdiretórios
11 string[] subdirs = dir.GetDirectories(oNomeDaPasta);
12 foreach (string subdir in subdirs) {
13
14 PercorrerPasta(subdir);
15 }
16
17 FileInfo[] files = dir.GetFiles();
18 foreach (FileInfo file in files) {
19
20 // processa o arquivo encontrado
21 }
22 }
23
24 [STAThread]
25 public static void Main() {
26 PercorrerPasta('c:\');
27 }
28 }
Postado por Massuda às 14:15 0 comentários
Marcadores: c#
Existem relatos frequentes sobre a ocorrência de erros de floating point overflow ao imprimir a partir de programas feitos em Delphi. Algumas pessoas chegam a afirmar que existe incompatibilidade entre Delphi e determinada marca de impressora.
Esse problema resulta de uma "incompatibilidade" no modo como o Delphi trata a FPU e os outros compiladores. O padrão do Delphi gera exceção no caso de problemas em cálculos envolvendo ponto flutuante enquanto os outros compiladores ignoram esses problemas (os cálculos resultam em NaN, INF, etc).
Quando se faz uma impressão, o programa em Delphi precisa usar uma DLL fornecida pelo fabricante da impressora (o driver da impressora). Embora drivers de impressão possam ser feitos em Delphi, é pouco provável que essa DLL tenha sido feita em Delphi. O resultado é que a DLL feita assumindo que erros envolvendo ponto flutuante podem ser ignorados é executada por um programa que assume o oposto. Assim, erros que normalmente a DLL ignoraria passam a não ser mais ignorados.
Se estiver fazendo impressão usando o objeto Printer, a solução seria algo assim...
1 var 2 Sav8087CW: Word; 3 ... 4 Sav8087CW := Default8087CW; 5 Set8087CW(0x133F); 6 try 7 Printer.EndDoc; 8 finally 9 Set8087CW(Sav8087CW); 10 end; 11 ...
Note que o driver da impressora geralmente só é usado quando TPrinter.EndDoc é executado. Não sei dizer se esse comportamento pode ser alterado por alguma configuração do Windows.
Postado por Massuda às 20:34 0 comentários
Marcadores: delphi
Exemplo de envio de email em formato HTML usando Delphi e Indy 9:
1 var 2 Email: TIdMessage; 3 Texto: TIdText; 4 Html: TIdText; 5 Anexo: TIdAttachment; 6 begin 7 Email := TIdMessage.Create(nil); 8 try 9 // ...ajusta remetente, destinatário, etc... 10 11 // define o tipo do conteúdo da mensagem 12 Email.ContentType := 'multipart/mixed'; 13 14 // cria a parte texto - pode estar em branco 15 Texto := TIdText.Create(Email.MessageParts); 16 Texto.Body.Text := 17 'This message contains HTML and images.'; 18 Texto.ContentType := 'text/plain'; 19 20 // cria a parte HTML 21 Html := TIdText.Create(Email.MessageParts); 22 Html.Body.Text := '<html><body>' 23 + 'Mensagem de <b>Teste</b><br />' 24 + '<img src="cid:imagem.jpg" />' 25 + '</body></html>'; 26 Html.ContentType := 'text/html'; 27 28 // inclui no email a imagem usada na parte HTML 29 Anexo := TIdAttachment.Create( 30 Email.MessageParts, 'c:\pasta\imagem.jpg'); 31 Anexo.ContentType := 'image/jpg'; 32 Anexo.Headers.Add('Content-ID: <imagem.jpg>'); 33 34 // ... envia o email... 35 finally 36 Email.Free; 37 end; 38 end;
Postado por Massuda às 00:19 3 comentários
Exemplo básico de envio de email usando Delphi e Indy 9:
1 var 2 Email: TIdMessage; 3 begin 4 // SMTP é um TIdSMTP 5 // POP3 é um TIdPOP3; 6 7 Email := TIdMessage.Create(nil); 8 try 9 10 // ...ajusta remetente, destinatário, etc da mensagem... 11 12 POP3.Host := 'seu-servidor-pop3'; 13 POP3.Username := 'seu-username'; 14 POP3.Password := 'sua-senha-secreta'; 15 16 POP3.Connect; 17 18 try 19 SMTP.Host := 'seu-servidor-smtp'; 20 SMTP.AuthType := atLogin; 21 SMTP.Username := 'seu-username'; 22 SMTP.Password := 'sua-senha-secreta'; 23 24 SMTP.Connect; 25 try 26 SMTP.Send(Email); 27 except 28 on E: Exception do begin 29 // envio falhou 30 end; 31 end; 32 SMTP.Disconnect; 33 finally 34 POP3.Disconnect; 35 end; 36 finally 37 Email.Free; 38 end; 39 end;
Postado por Massuda às 22:25 1 comentários