the club - megazine · android studio novas técnicas para manipulações de exceções. junho 04...

32
junho 2014

Upload: vanthien

Post on 28-Sep-2018

226 views

Category:

Documents


1 download

TRANSCRIPT

junho2014

junho2014

junho2014 03

18

Índice

Desafio The Club

30

Editorial

04

14

Autor: Jeferson Silva de Lima.

05

Autor: Hamden Vogel

25Criando um serviço no Microsoft Visual Studio 2013Autor: Thiago C. Montebugnoli

Autor: Luciano Pimenta

Delphi

Delphi XE5 – Trabalhando com Intents

Android Studio

Novas técnicas para manipulações de Exceções

junho201404

Delphi é marca registrada da Borland International, as demais marcas citadas são registradas

pelos seus respectivos proprietários.

Thiago Montebugnoli - Editor [email protected]

Caro Leitor,

Não foi desta vez que conquistamos o Hexa em casa, mas como brasileiros não podemos desistir nunca, pois afinal de contas não podemos esquecer que as Olimpíadas estão por vir e teremos outras chances nas próximas Copas. Com nossa equipe não existe tempo ruim, pois a cada mês estamos proporcionando ótimos artigos para os ajudar. Neste mês, nosso colunista Luciano Pimenta, irá nos mostrar uma ferramenta gratuita do Google para criar aplicações mobile, o “Android Studio”. Neste artigo ele irá criar um aplicativo que abordará as principais funcionalidades desta IDE de desen-volvimento. Já nosso colaborador Handem Vogel, trabalhando com o Delphi, nos escreve o artigo “Novas técnicas para manipulações de Exceções”, uma nova alternativa para capturar as exceções relevantes para o contexto de uma aplicação, explorando a técnica de “Hooking” na DLL “Kernel32.dll”. Eu utilizo a última versão do Microsoft Visual Studio para tratar de um assunto bem usual no dia a dia, a Criação de um serviço no S.O. Windows. Esta dica se torma indispensável para quem deseja rodar alguma tarefa em segundo plano. Para finalizar a revista com estilo, nosso consultor técnico Jeferson Silva de Lima escreve o artigo “Delphi XE5 – Trabalhando com Intents”. Os denominados Intents são ações que permitem iniciar uma atividade em um aplicativo externo. Um recurso muito utilizado quando desejamos executar uma calculadora ou até mesmo o navegador.

Não podemos esquecer de nossa seção de Dicas e Truques, sendo que neste mês abordará diversos assuntos importantes.

Vou ficando por aqui, desejando uma ótima leitura e um Abraço.

Vejo vocês o mês que vem!

Av. Profº Celso Ferreira da Silva, 190 Jd. Europa - Avaré - SP - CEP 18.707-150

Informações e Suporte: (14) 3732-1529

Internethttp://www.theclub.com.br

Cadastro: [email protected]: [email protected] Informações: [email protected] Cadastro: theclub_cadastro

Skype Suporte: theclub_linha1 theclub_linha2 theclub_linha3

www.twitter.com/theclubbr

Copyright The Club 2013

Diretor TécnicoMarcos César Silva

DiagramaçãoVitor M. Rodrigues

DesignVitor M. Rodrigues

RevisãoDenise Blair

ColunistasHamden Vogel

Jeferson Silva de LimaLuciano Pimenta

Lucas Vieira de OliveiraThiago Cavalheiro Montebugnoli

Impressão e acabamento:GRIL - Gráfica e Editora

Taquarituba-SP - Tel. (14) 3762-1345

ReproduçãoA utilização, reprodução, apropriação, armazenamento em banco de dados, sob qualquer forma ou meio, de textos, fotos e outras criações intelectuais em cada publicação da revista “The Club Megazine” são terminantemente proibidos sem autorização escrita dos titulares dos direitos autorais.

Editorial

junho2014 05

O emprego de exceções para o controle e manipulação de erros em uma aplicação sempre se mostrou importante e profissional para o desenvolvedor, no que diz respeito principalmente aos custos/benefícios e eficiência para recuperações de tratamentos não-previstos ou até mesmo

esquecidos: o que seria de um cálculo de divisão cujo dividendo permite a entrada do zero? Ou chamadas a variáveis não instanciadas? O alcance da empregabilidade desta poderosa ferramenta é infinita – e poupa e muito o trabalho do programador em procurar a linha do fonte do erro – imagina em um programa antigo e com incalculáveis unit´s onde muitas delas chamam-se entre si: onde realmente estará o erro e porque aconteceu e porque não foi tratado? É fácil de perguntar. Mas muito esquecido, pois nem sempre é em-pregado quando deveria; muitas vezes sua importância não foi considerada e muito subestimada.

Vamos ao que interessa: uma unit para manipular serviços de exceções antes de serem disparados – como assim?

Rastreamento, Identificação e Correção: Aqui vamos nós !

A nossa unit tem como objetivo implementar a técnica de Hooking para capturar as chamadas da Kernel32.dll, desviando sua execução normal para este aplicativo, onde possamos manipular “com antecedência” todas as ocorrências registradas de exceções levantadas nele. A boa notícia é que agora saberemos de antemão quando uma exceção vai disparar antes que o sistema operacional dispare primeiro – teremos esta “novidade” para registro – no nosso caso um eficiente arquivo de log – porque não?

O que é hooking, então? É a forma que escolhemos neste projeto – é uma função para monitorar uma DLL, a grosso modo falando. Assim, podemos interceptar suas chamadas, debugando (a ideia primordial da Microsoft) ou desenvolvendo alternativas à implementação inicial de uma DLL de um Sistema Operacional. Podemos, claro, utilizar este conceito para o bem ou para o mal – um aplicativo para monitorar tudo que o usuário digita, por exemplo, como um “espião” – mas não é isso o tema proposto neste escopo deste artigo – a

Novas técn icas para manipulações de Exceções

intenção é explicar e exemplificar de forma útil, simples, honesta e sincera como as exceções do sistema operacional possam ser capturadas e com esta informação possam ser utilizadas eficientemente e de grande valor para o tratamento de erros obtidos – através da captura de Kernel32.RaiseException (Kernel32.dll) chamada a partir de System.RaiseExcept.

Este artigo tem como foco principal explorar a excelente ideia de um desenvolvedor norueguês chamado Hallvard Vassbotn, onde esmiúça em detalhes toda a implementação da técnica de hooking particularmente no contexto de captura de exceções em um programa escrito em Delphi – com isso todas as aplicações baseadas nesta linguagem poderão usufruir destas funções de hooking de exceções fornecidas e explicadas vasta e detalhadamente no escopo deste projeto.

Em prática: botando o quebra-cabeça pra funcionar:

Segue abaixo o roteiro das partes deste quebra-cabeça, juntando as peças para nosso entendimento, para clarear tudo o que foi dito antes de forma mais rápida.

1 – Testando o nosso aplicativo de exemplo:

Figura 01 – Tela do nosso programa em modo de execução, contendo testes para disparar exceções propositadamente;

2 – Disparando uma exceção – chamamos antes do Delphi chamar elas primeiro:

junho201406

Figura 02 – Tela mostrando as notificações de exceções geradas pelo sistema operacional – note que a nossa função de hooking “pegou” ela primeiro – depois que o usuário

clicar neste botão de “OK” aí sim, que o Delphi vai chamar ela normalmente, como ela já faz de costume;

3 – O Delphi “por debaixo dos panos”:

Figura 03 - Nesta parte, na altura do campeonato, o Delphi já manipula o nosso hooking, embora ainda não chegou a chamar a exceção disparada ainda – quem está fazendo

isso ainda somos nós (na nossa procedure NotifyException passamos um objeto do tipo compatível com uma procedure - type TExceptNotify = procedure (ExceptObj: TObject; ExceptAddr: pointer; OSException: boolean); esta variável que é a responsável por tudo isso que está acontecendo neste processo de hooking;

4 – O Delphi encontrou a exceção! Mas já chegou tarde: em segundo lugar, porque nós descobrimos ela primeiro.

Figura 04 – Entregamos a exceção que nós capturamos primeiro, para o Delphi manipular ela depois, como já faz tradicionalmente.

Portanto, estes são os passos básicos que são percorridos, até que o Delphi encerre este processo por padrão. Apenas criamos uma entrada de hooking no meio deste processo, para manusearmos primeiramente as exceções. E é assim que as coisas funcionam. Temos de antemão toda a recuperação de erros gerados para nós lidarmos conforme nosso desejo de implementação destes dados. O bom é que temos uma ferramenta poderosa de geração e

fornecimento de hooking e dados capturados deste hooking, respectivamente.

Abaixo segue a unit contendo a manipulação de capturas de exceções levantadas na kernel32.dll, utilizando hooking para esta finalidade de “espioná--la” – note que somente exceções que dizem respeito ao nosso aplicativo serão tratadas – demais exceções do sistema operacional, hardware, etc, não serão

junho2014 07

Listagem 01

abordadas na nossa funcionalidade.

unit HVExceptNotify;// Unit that provides a notification service when exceptions are being raised//// Written by Hallvard Vassbotn, [email protected], September 1999interface

type TExceptNotify = procedure (ExceptObj: TObject; ExceptAddr: pointer; OSException: boolean);var ExceptNotify: TExceptNotify;

implementation

uses Windows, SysUtils, HVHookDLL;

var Kernel32_RaiseException : procedure (dwExceptionCode, dwExceptionFlags, nNumberOfArguments: DWORD; lpArguments: PDWORD); stdcall;

type PExceptionArguments = ^TExceptionArguments; TExceptionArguments = record ExceptAddr: pointer; ExceptObj : TObject; end;

procedure HookedRaiseException(ExceptionCode, ExceptionFlags, NumberOfArguments: DWORD; Arguments: PExceptionArguments); stdcall;// All calls to Kernel32.RaiseException ends up hereconst // D2 has a different signature for Delphi exceptions cDelphiException = {$IFDEF VER90}$0EEDFACE{$ELSE}$0EEDFADE{$ENDIF}; cNonContinuable = 1;

begin // We’re only interested in Delphi exceptions raised from System’s // internal _RaiseExcept routine if (ExceptionFlags = cNonContinuable) and (ExceptionCode = cDelphiException) and (NumberOfArguments = 7) and (DWORD(Arguments) = DWORD(@Arguments) + 4) then begin // Run the event if it has been assigned if Assigned(ExceptNotify) then ExceptNotify(Arguments.ExceptObj, Arguments.ExceptAddr, false); end; // Call the original routine in Kernel32.DLL Kernel32_RaiseException(ExceptionCode, ExceptionFlags, NumberOfArguments, PDWORD(Arguments));end;

var SysUtils_ExceptObjProc: function (P: PExceptionRecord): Exception;

function HookedExceptObjProc(P: PExceptionRecord): Exception;begin // Non-Delphi exceptions such as AVs, OS and hardware exceptions // end up here. This routine is normally resposible for creating // a Delphi Exception object corresponding to the OS-level exception // described in the TExceptionRecord structure. // // We leave the mapping to the standard SysUtils routine, // but hook this to know about the exception and call our

junho201408

Listagem 2

Listagem 3

// event.

// First call the original mapping function in SysUtils Result := SysUtils_ExceptObjProc(P);

// Run the event if it has been assigned if Assigned(ExceptNotify) then ExceptNotify(Result, P^.ExceptionAddress, true);end;

initialization SysUtils_ExceptObjProc := System.ExceptObjProc; System.ExceptObjProc := @HookedExceptObjProc; HookImport(‘Kernel32.dll’, ‘RaiseException’, @HookedRaiseException, @Kernel32_RaiseException)

finalization UnHookImport(‘Kernel32.dll’, ‘RaiseException’, @HookedRaiseException, @Kernel32_RaiseException); System.ExceptObjProc := @SysUtils_ExceptObjProc; SysUtils_ExceptObjProc := nil;

end.

Outro exemplo de hooking de exceção – para erros do tipo EConvertError:

Figura 05 – Tela do hooking para exceções geradas do tipo de conversão de tipos, no caso a EConvertError. Para todos os tipos de exceções o processo de hooking sempre será o mesmo.

Em outras palavras, a variável ExceptObjProc do tipo ponteiro (Pointer) declarada em system.pas é a responsável por receber a nossa função (que re-

torna um Exception) que fará o nosso papel de “espião” (hooking) – recebendo primeiramente as chamadas das exceções geradas pelo sistema operacional e consequentemente podendo manipulá-las livremente, da forma como queremos que sejam tratadas. A procedure HookedRaiseException e a função HookedExceptObjProc serão utilizadas para o hooking da Kernel32.dll, de onde as exceções do sistema operacional são geradas. Abaixo segue o código impor-tante deste processo – note que estas funções são passadas como ponteiros.

initialization SysUtils_ExceptObjProc := System.ExceptObjProc; System.ExceptObjProc := @HookedExceptObjProc; HookImport(‘Kernel32.dll’, ‘RaiseException’, @HookedRaiseException, @Kernel32_RaiseException)

finalization UnHookImport(‘Kernel32.dll’, ‘RaiseException’, @HookedRaiseException, @Kernel32_RaiseException); System.ExceptObjProc := @SysUtils_ExceptObjProc; SysUtils_ExceptObjProc := nil;

Segue abaixo a descrição de uma importante unit contendo funções gerais (podendo ser utilizadas para qualquer DLL) para a manipulação de hooking:

unit HVHookDLL;{ General DLL hooking utility

Hook any implicitly imported DLL routine used by a loaded module.

Written by Hallvard Vassbotn, [email protected], September 1999

Inspired by Matt Pietrek’s article “Peering inside the PE: A Tour of the Win32 Portable Executable File Format”, available at:

http://msdn.microsoft.com/library/techart/msdn_peeringpe.htm

junho2014 09

Quote: “Since the import address table is in a writeable section, it’s relatively easy to intercept calls that an EXE or DLL makes to another DLL. Simply patch the appropriate import address table entry to point at the desired interception function. There’s no need to modify any code in either the caller or callee images. What could be easier?”}interface

function ReplaceImport(Base: Pointer; ModuleName: PChar; FromProc, ToProc: pointer): boolean;function HookImport(ModuleName, ImportName: PChar; HookProc: pointer; var DLLProc: pointer): boolean;function UnhookImport(ModuleName, ImportName: PChar; HookProc: pointer; var DLLProc: pointer): boolean;

implementation

uses Windows, SysUtils, HVPEUtils;

type PWin95CallThunk = ^TWin95CallThunk; TWin95CallThunk = packed record PUSH: byte; // PUSH instruction opcode (=$68) Addr: pointer; // The actual address of the DLL routine JMP : byte; // JMP instruction opcode (=$E9) Rel : Integer; // Relative displacement (a Kernel32 address) end;

function IsWin95CallThunk(Thunk: PWin95CallThunk): boolean;

begin Result := (Thunk^.PUSH = $68) and (Thunk^.JMP = $E9);end;

function ReplaceImport(Base: Pointer; ModuleName: PChar; FromProc, ToProc: pointer): boolean;var NtHeader : PImageNtHeaders; ImportDescriptor : PImageImportDescriptor; ImportEntry : PImageThunkData; CurrModuleName : PChar; IsThunked : Boolean; FromProcThunk : PWin95CallThunk; ImportThunk : PWin95CallThunk; FoundProc : boolean;begin // Assume failure Result := false;

// Cache some Win95-specific knowledge about the FromProc // On Win95/98, the import entries and GetProcAddress of some system // module routines point to PUSH [ActualAdress]/JMP [Rel] thunks, // so we have to look into the code to see if the final target matches // Convert the FromProc into the thunk code it /might/ point to FromProcThunk := PWin95CallThunk(FromProc); // Is it a valid Win95 thunk? IsThunked := (Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and IsWin95CallThunk(FromProcThunk);

// Get a pointer to the PE-header NtHeader := GetImageNtHeader(Base); // Get a pointer to the import descriptor table ImportDescriptor := PImageImportDescriptor(DWORD(Base)+

junho201410

NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

// The table of import descriptors is marked with a null name offset while ImportDescriptor^.NameOffset <> 0 do begin // Calculate a pointer to this module name CurrModuleName := PChar(Base) + ImportDescriptor^.NameOffset; // Only search matching modules if StrIComp(CurrModuleName, ModuleName) = 0 then begin

// Calculate a pointer to the first import entry for this module ImportEntry := PImageThunkData(DWORD(Base) + ImportDescriptor^.IATOffset);

// Loop until we have reached the end of the list while ImportEntry^.FunctionPtr <> nil do begin // Now we must determine if this import entry pointer // is equivalent to the FromProc address

if IsThunked then begin // Convert the ImportEntry into the thunk code it /might/ point to ImportThunk := PWin95CallThunk(ImportEntry^.FunctionPtr);

// If the routine we’re hooking points to a Win95 thunk, // see if the final

target matches FoundProc := IsWin95CallThunk(ImportThunk) and (ImportThunk^.Addr = FromProcThunk^.Addr) end else // otherwise, only check for clean matches FoundProc := (ImportEntry^.FunctionPtr = FromProc);

// If we found the correct import entry, patch it! if FoundProc then begin // Note that all import sections have Read/Write access by default, // so there is no need to play around with WriteProcessMemory or // VirtualProtect ImportEntry^.FunctionPtr := ToProc;

// There could be more imports of the same routine, so just flag // success and keep looking for more matches Result := true; end;

// Look at the next Import Entry for this module Inc(ImportEntry); end; end; // Look at the next Import Descriptor Inc(ImportDescriptor); end;end;

function HookImport(ModuleName, ImportName: PChar; HookProc: pointer; var DLLProc: pointer): boolean;

junho2014 11

Listagem 4

begin Result := not Assigned(DLLProc); if Result then begin DllProc := Windows.GetProcAddress(Windows.GetModuleHandle(ModuleName), ImportName); Result := Assigned(DllProc) and ReplaceImport(Pointer(HInstance), ModuleName, DllProc, HookProc); if not Result then DLLProc := nil; end;end;

function UnhookImport(ModuleName, ImportName: PChar; HookProc: pointer; var DLLProc: pointer): boolean;begin Result := Assigned(DllProc) and ReplaceImport(Pointer(HInstance), ModuleName, HookProc, DllProc); if Result then DLLProc := nil;end;

end.

Um log para registrar as ocorrências de Exceções

Criei uma classe para ilustrar a técnica de hooking explicado no escopo deste artigo, exemplificando em um contexto do mundo real, onde as aplicações de hoje em dia possuem log´s e auditoria – no nosso exemplo particular vamos utilizar o registro de log para armazenar em um arquivo txt qualquer todas as incidências de erros. O universo desta implementação é vasto – poderíamos futuramente migrar para outras soluções, como enviar um email ao fabricante do software contendo os erros gerados (algo como enviar relatórios, que o Windows já faz) ou registrar em um banco de dados os erros para uma tabela de auditoria, ou criar um indicador de desempenho, etc; enfim as alternativas podem ser muitas conforme a criatividade do desenvolvedor para o manuseio destes dados.

No nosso exemplo a classe foi criada batizada de TLogException – utili-zando uma variável do tipo TStringList que fará o papel de registrar os dados de exceções em um arquivo txt. Claro que poderíamos utilizar outras soluções

como um objeto TextFile, TFileStream, etc; e que todas estas atendem ao propósito desejado. Segue abaixo a implementação desta classe TLogExcep-tion, podendo ser customizada e readaptada à qualquer projeto já existente. É claro que alguns pré-requisitos devem ser atendidos, como a permissão de gravação deste arquivo txt bem como a quantidade de espaço disponível no disco, o nome do diretório ou do disco-rígido (no caso de redirecionar para uma outra partição ou endereço de rede), etc;

type TLogException = class private fPathFileLog: string; FileLogException: String; FileLog: TStringList; procedure SetFileLogException(const Value: String); public property MyFileLogException: String read FileLogException write SetFileLogException; procedure RegisterExceptionInLogFile(const ExceptionText: string = ‘’); constructor Create(const myFileLogException: String = ‘’); destructor Destroy; override;end;

{ TLogException }

constructor TLogException.Create(const myFileLogException: String);begin fPathFileLog := ‘c:\’; if (myFileLogException = ‘’) then Exit; FileLogException := fPathFileLog + myFileLogException; FileLog := TStringList.Create; end;

destructor TLogException.Destroy;begin if (FileLogException <> ‘’) then if Assigned(FileLog) then FreeAndNil(FileLog);

inherited;

junho201412

Listagem 5 Listagem 6

end;

procedure TLogException.RegisterExceptionInLogFile(const ExceptionText: string);begin if (FileLogException = ‘’) then Exit; if (ExceptionText = ‘’) then Exit; //if not FileExists(FileLogException) then Exit; if not Assigned(FileLog) then FileLog := TStringList.Create;

with FileLog do begin Add(‘’); Add(‘-------- Log gerado às ‘ + FormatDateTime(‘c’, Now)+ ‘------’); Add(‘Segue informações detalhadas do erro abaixo:’); Add(ExceptionText); Add(‘’); Add(‘-------- Fim da ocorrência ----------------------------------’); SaveToFile(FileLogException); end;

Application.ProcessMessages;end;

procedure TLogException.SetFileLogException(const Value: String);begin FileLogException := fPathFileLog + Value;end;

A função NotifyException modificada para atender a nossa nova classe TLogException:

procedure NotifyException(ExceptObj: TObject; ExceptAddr: pointer; OSException: boolean);

const Recursive: boolean = false;var msgException: string;begin // We have to be careful what we are doing in here - // if an exception is raised, we could get endless recursive behaviour if not Recursive then begin Recursive := true; if ExceptObj is Exception then begin msgException := Format(‘Notified of exception %s at %p’#13#10’”%s”’, [ExceptObj.ClassName, ExceptAddr, Exception(ExceptObj).Message]); ShowMessage(msgException); myFileLogException.RegisterExceptionInLogFile(msgException); end else begin msgException := Format(‘Notified of exception %s at %p’, [ExceptObj.ClassName, ExceptAddr]); ShowMessage(msgException); myFileLogException.RegisterExceptionInLogFile(msgException); end;

Recursive := false; end;end;

onde myFileLogException é um objeto do tipo TLogException, definido como global em:

var Form1: TForm1; myFileLogException: TLogException;

junho2014 13

Listagem 7

e chamado na criação e destruição do formulário principal, respectiva-mente em:

procedure TForm1.FormCreate(Sender: TObject);begin HVExceptNotify.ExceptNotify := NotifyException; myFileLogException := TLogException.Create(‘myLog.txt’);end;

procedure TForm1.FormDestroy(Sender: TObject);begin HVExceptNotify.ExceptNotify := nil; FreeAndNil(myFileLogException);end;

Veja a figura 6.

Conclusão:

Hoje é indispensável a utilização de técnicas avançadas de manipulação de exceções; sabemos que existem softwares de risco que operam o dia in-teiro que não podem nem devem apresentar erros, e se no caso isso ocorrer

toda exceção (senão quase todas) é recomendável tratá-las da melhor forma para não ter que encerrar a aplicação imprevisivelmente, perdendo dados não salvos, por exemplo, ou evitando novos erros que poderiam surgir em decorrência de outros (como um arquivo danificado, falha na transmissão de dados, objetos instanciados sem serem destruídos, etc);

Apresentei uma forma alternativa para a manipulação de exceções, através da técnica de hooking na DLL Kernel32.dll para capturar as exceções relevan-tes para o contexto da nossa aplicação, sem se importar com demais erros ocasionados fora do ciclo de vida do mesmo (erros de hardware, de arquivos danificados do sistema operacional, por exemplo) que na verdade não dizem respeito à relevância negocial de uma aplicação;

Portanto, o desenvolvedor terá em suas mãos o emprego de mais uma técnica importante para o debug de suas aplicações, podendo ser aplicada tanto em um projeto velho quanto em um novo sem muitas alterações; é fácil de implementar e utilizar da melhor forma que seja tanto prática quanto também eficiente. Uma boa leitura e até a próxima revista !

Figura 06 – O processo de log em ação – registrado pela nossa classe TLogException em modo de execução, chamadas no contexto do hooking para armaze-namento destes dados em modo txt.

[email protected]

Hamden VogelAnalista de Sistemas pós-graduado em Engenharia de Software pela

UPIS e Programador Delphi com larga experiência desde 2000, tem de-senvolvido e vendido softwares em Delphi para a África e Estados Unidos, além do mercado nacional. Colaborou com dicas e componentes para sites especializados em Delphi. Também desenvolve em outras linguagens como C/C++, ASP, PHP e .NET.

Sobre o autor

junho201414

Nos últimos anos, tivemos uma grande evolução de dispo-sitivos móveis, os chamados smartphones. Em seguida, tivemos os tablets, com funcionalidades semelhantes aos telefones, mas com telas maiores, mais processamento etc.

Um dos grandes responsáveis pela popularidade desses equipamentos se deve ao sistema que controla esses devices. Um dos mais usados é o Android. Cada dia mais aplicativos Android são lançados no mercado. Neste artigo, que-ro mostrar uma ferramenta gratuita do Google para criar aplicações mobile. Vamos conhecer o Android Studio.

Existem outras IDEs para criar aplicações Android, como Eclipse e Xamarin, que podemos ver em outra oportunidade.

Dowload e instalação

Para baixar a ferramenta, acesse: http://developer.android.com/sdk/installing/studio.html. Baixe a última versão. Nesse artigo vamos usar a versão 0.5.2 (no update da ferramenta, já estamos na versão 0.6). Como podemos ver, a ferramenta é beta, mas suas qualidades saltam aos olhos.

A instalação é simples, sem muitas configurações. Precisamos também baixar e instalar o SDK do Android. São as ferramentas necessárias para que possamos criar projetos Android. Acesse: http://developer.android.com/sdk/index.html e baixa a última versão.

Versões do Android

O Android esta em constante atualização. Sua versão mais recente é a 4.4 (chamada KitKat). Cada versão possui caracteristicas distintas, desenvolvendo novos tipos de aplicativos, assim como novas funcionalidades.

Você pode criar um aplicativo com a versão 1.0, que a mesma irá rodar no Android 4.4. Isso não quer dizer que funcionalidades, e controles de tela

Android Studiopresentes no 4.4 estarão disponiveis para equipamentos com a versão 1.0. Um aplicativo pode ser criado para várias versões, como veremos adiante.

Precisamos instalar as versões que desejamos trabalhar, e para isso usamos o SDK Manager. Ele pode ser acessado através do menu do Windows. Ao abrir o SDK, ele mapeia todas as versões do Android, ferramentas e extras, indicando se os mesmos estão instalados em sua máquina (Figura 1).

Figura 1. SDK Manager com as versões, extras e tools instaladas

No SDK Manager podemos baixar as versões que vamos trabalhar, como também ferramentas e outros aplicativos necessários para o desenvolvimento Android.

junho2014 15

Criando um emulador

Caso você não possua um device (celular) para testar sua aplicação, temos como criar um emulador, que fará o papel do device para visualizarmos o projeto. No SDK Manager, acesse o menu Tools>Manage AVDs.

Nessa tela (Figura 2) podemos criar novos emuladores.

Figura 2. AVD Manager para criar um emulador

Agora, basta clicar em New. Na nova tela, vamos configurar o emulador, primeiramente, dando um nome (AVD Name). Em Device, vamos escolher o tipo de equipamento que o emulador terá de layout. Escolha um meio termo para que sua aplicação não seja mostrada em uma resolução muito grande ou muito pequena. Em Target, indicamos qual a API do Android que será usada.

Veja como fica as outras configurações na Figura 3.

Figura 3. Criando um emulador

Clique em OK. Agora o emulador esta presente na lista de emuladores do AVD Manager. Lembrando apenas que criar o emulador é necessário apenas se você não tem um device.

Criando o primeiro projeto

Ao abrir o Android Studio, temos a Figura 4 com suas funcionalidades.

Figura 4. Tela do Android Studio

Na tela, temos o histórico dos projetos recentes, assim como podemos criar, importar ou abrir um projeto.

Nota: depois da primeira vez, o Android Studio abre sempre o último projeto.

No item Configure, somos direcionados para outra tela, onde podemos abrir o SDK Manager. Para criar um novo projeto, acesse New Project. A tela da Figura 5 será mostrada.

Figura 5. Criando um projeto no Android Studio

Na tela inicial do wizard, vamos configurar o nome da aplicação no item Application name. Module e Package são oriundos do Java para criarmos um nome único para a aplicação quando distribuirmos a mesma no Play Store (loja do Android).

junho201416

Minimum e Target SDK refere-se, respectivamente, a versão do Android mínima para utilização do aplicativo e qual a versão é nosso alvo/foco. Isso é importante, pois características e funcionalidades de aplicativos podem não estar disponíveis de acordo com a versão.

Por exemplo, mapas esta disponível a partir da versão 2.2 (API 8). Criando um aplicativo nessa versão mínima, consideramos que irá rodar em todas as versões posteriores do Android. Mas se quisermos utilizar funcionalidades presentes em versões mais recentes. Indicamos a versão no Target SDK.

Podemos escolher um tema para o aplicativo: Dark ou Light. Marque a opção que indica que vamos customizar o ícone do aplicativo. Os modos de suportem indicam que tipo de layout será suportado: barra de ações, grids, fragmentos, itens de navegação etc.

Clique em Next para na próxima tela configurar um ícone. No Android, temos quatro tamanhos de imagens. Pequena, média, grande e extra grande. É interessante, que quando adicionarmos imagens, tenhamos um arquivo para cada resolução. Veremos adiante, que existe uma pasta para cada tamanho de imagem.

Após escolher a imagem, no próximo passo, vamos escolher o layout do nosso aplicativo. O Android da a opção de criar aplicativo vazio, bem como uma aplicação com uma base pronta para apenas codificarmos o que precisamos. Veja abaixo os tipos de templates:

- Blank Activity: cria um aplicativo vazio com uma Action Bar;

- Blank Activity with Fragment: é um aplicativo vazio, com uma Action Bar e apenas com um fragmento.

- Empty Activity: aplicativo totalmente vazio (somente a estrutura é criada,

sem nenhum arquivo de layout);

- Fullscreen Activity: aplicativo de tela cheia. Fica sobre barra de ações, de navegações etc.

- Google Maps Activity: cria um aplicativo para o Google Maps.

- Google Play Services Activity: aplicativo para conectar aos serviços do Google.

junho2014 17

- Master Detail Flow: possui uma lista de itens, que ao clicar, abrem acti-vitys. Um exemplo desse tipo de template é o WhatssApp.

- Navigation Drawer Activity: outro template muito usado atualmente

(GMail, Foursquare etc), possui um “menu” lateral na esquerda com opções e a activity é mostrada na parte direita da tela.

- Tabbed Activity: aplicativo em branco, com action bar e navegação de elementos. Semelhante a uma lista de fotos onde podemos “passar” de uma foto para outra, correndo de um lado para o outro. A foto nesse exemplo, é um elemento.

Após escolher o template (vamos usar o Navigation Drawer Activity), clique em Next. A próxima e última aba vai ser diferente, de acordo com o template escolhido. Nela daremos os nomes para a Activity, layout e elements do projeto. Na Figura 6, temos o passo final do wizard.

Figura 6. Finalizando o projeto

Nota: neste artigo foi usado a versão 0.6.0 do Android Studio. Na versão 0.6.1 algumas modificações profundas foram adicionadas ao wizard, mas nada que mude a essência final do projeto. No primeiro passo, você escolhe o nome e local do projeto. No segundo, não temos mais Target SDK, agora apenas Minimum. O passo seguinte é onde escolhemos os templates e temos mais dois tipos: Settings Activity (para configurações) e Login Activity (para autenticação de usuário). Mudanças essas que não afetam o desenvolvimento final de um aplicativo.

Conclusões

Vimos neste artigo uma introdução sobre uma ferramenta gratuita para desenvolvimento de aplicativos para Android. Conhecemos como criar um aplicativo e quais as funcionalidades dessa ferramenta. No próximo artigo vamos dar continuidade no projeto e veremos algumas dicas para codificação e criação de layouts.

Um grande abraço a todos e até a próxima!

www.lucianopimenta.net

Luciano PimentaLuciano Pimenta (NOVO DOMINIO: www.lucianopimenta.com) é desenvolvedor Delphi/C#

para aplicações Web com ASP.NET, Windows com Win32 e Windows Forms com .NET. Palestrante da 4ª edição da Borland Conference (BorCon) e da 1ª Delphi Conference.

É MVP Embarcadero, grupo de profissionais que ajudam a divulgar o Delphi no mundo. Atualmente é desenvolvedor da SoftDesign fábrica de softwares em Porto Alegre-RS.

Autor de mais de 90 artigos e de mais de 600 vídeos aulas publicadas em revistas e sites especializados, além de treinamentos presenciais e multimídias. É consultor da FP2 Tecnologia (www.fp2.com.br) onde ministra cursos de programação e banco de dados.

Sobre o autor

junho201418

Listagem 1 – Uses.

Listagem 2 – Intent Telefone.

Introdução

Nos artigos anteriores demonstramos desde a criação até a comunicação dos dados entre aplicações Mobile e DataSnap (Desktop) utilizando os bancos de dados SQLite e Firebird.

Neste artigo vamos demonstrar a utilização do recurso Intents no Android... Mas o que são Intents?

Intents de forma bem simples são ações que permitem iniciar uma ati-vidade em um aplicativo externo, por exemplo, executar uma calculadora, navegador etc. Para exemplificar este recurso criaremos um exemplo utilizando alguns aplicativos comuns no Android.

Aplicação

Comece criando um novo projeto ‘ File/New/Firemonkey Mobile Applica-tion ‘ e insira 5 Buttons no formulário cada um deles irá chamar um aplicativo diferente.

No site Developer Android podemos encontrar o guia de APIs para adap-tarmos em nossos códigos. Segue Link abaixo para consulta.

http://developer.android.com/guide/components/intents-common.html

Inicialmente declare na Uses as seguintes Units:

IdURI,Androidapi.JNI.JavaTypes,Androidapi.JNIBridge,Androidapi.JNI.GraphicsContentViewText,Androidapi.JNI.Net,

Delphi XE5 – Trabalhando com Intents

Androidapi.JNI.Os,Androidapi.IOUtils,Androidapi.Jni.App,FMX.Helpers.Android,FMX.Platform;

Com as Units declaradas podemos acessar a API do Android. Crie as se-guintes variáveis globais em seus fontes:

Imagem 1 – Variáveis Globais.

A variável ‘Comando’ irá representar o URI dentro de cada ação, ou seja, as ações armazenadas em cada Intent podem ser acessadas através de esquemas de dados, por exemplo:

Ação -> ACTION_DIAL

Esquema URI de Dados -> tel: <Número de Telefone>

Exemplo de Intent:

“Public void dialPhoneNumber(String

junho2014 19

Listagem 3 – Botão Telefone.

Listagem 4 – Intent Contatos.

phoneNumber) { Intent Intent = new Intent(Intent.ACTION_DIAL); Intent.setData(Uri.parse( “tel:” + phoneNumber )); If (intent.resolveActivity(getPackageManager())!= null) { StartActivity(Intent); } }”

No exemplo acima a ação ‘ACTION_DIAL’ irá chamar o discador do apa-relho já com o número identificado no URI, mas como podemos adaptar isto para o Delphi?

Primeiro vamos analisar o código para identificar o que será necessário para acessar as mesmas propriedades. Veja que é realizada a criação do intent e passado a ação logo em seguida através do ‘Intent.setData’ já para executar a ação o comando ‘StartActivity’ é iniciado. Portanto vamos reproduzir o comando no Delphi conforme Listagem abaixo:

procedure TFrmxIntents.btnTelefoneClick(Sender: TObject);Begin Comando:= ‘tel://(099)91234-5678’; Try Intent:= TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_CALL); //ACTION_DIAL Irá chamar o Discador já com o Número Intent.setData(TJnet_Uri.JavaClass.parse(StringToJString(TIdURI.URLEncode(Comando)))); SharedActivity.startActivity(Intent); Except on E: Exception do ShowMessage(E.Message); End;end;

Optamos por ‘ACTION_CALL’, pois, com isso o número será chamado ao clicar no botão. Caso utilize ‘ACTION_DIAL’ será direcionado para a tela do discador de números.

Imagem 2 – Ligação.

Agora que entendemos a sintaxe dos comandos vamos reproduzi-lo em outros exemplos, veja abaixo:

Ação -> ACTION_PICK

Esquema URI de Dados -> Nenhum

Porém, podemos utilizar o seguinte URI:‘content://com.android.contacts/contacts/’;

O URI < content: > permitirá visualizar os contatos, neste caso todos eles.

Exemplo de Intent:

“static final int REQUEST_SELECT_CONTACT = 1;public void selectContact() { Intent intent = new Intent(Intent.ACTION_PICK); intent.setType(ContactsContract.Contacts.CONTENT_TYPE); if (intent.resolveActivity(getPackageManager()) != null) { startActivityForResult(intent,

junho201420

Listagem 5 – Botão Contatos.

Listagem 6 – Intent Web Browser.

Listagem 7 – Botão Navegador.

REQUEST_SELECT_CONTACT); }}”

A sintaxe mudou um pouco em relação a anterior, porém, em nosso exem-plo Delphi vamos seguir a mesma linha de raciocínio. Veja Listagem abaixo:

procedure TFrmxIntents.btnContatosClick(Sender: TObject);begin Comando:= ‘content://com.android.contacts/contacts/’; Try Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_PICK); Intent.setData(TJnet_Uri.JavaClass.parse(StringToJString(TIdURI.URLEncode(Comando)))); SharedActivity.startActivityForResult(Intent, 0); Except on E: Exception do ShowMessage(E.Message); end;end;

Imagem 3 – Contatos.

Ação -> ACTION_VIEW

Esquema URI de Dados -> http: <URL>

Exemplo de Intent:

“Public void openWebPage(String Url) { Uri webpage = Uri.parse(Url); Intent intent = new Intent (Intent.ACTION_VIEW, webpage); If (intent.resolveActivity (getPackageManager ()) != null) { StartActivity(Intent); } }”

procedure TFrmxIntents.btnBrowserClick(Sender: TObject);Begin Comando:= ‘http://theclub.com.br’; Try Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW); Intent.setData(TJnet_Uri.JavaClass.parse(StringToJString(TIdURI.URLEncode(Comando)))); SharedActivity.startActivity(Intent); Except on E: Exception do ShowMessage(E.Message); end;end;

Veja a imagem 4

junho2014 21

Listagem 8 – Intent E-mail.

Listagem 9 – Procedimento Email.

Imagem 4 – Navegador.

Ação -> ACTION_SEND; (Um Anexo). ACTION_SENDTO; (Sem Anexo). ACTION_SEND_MULTIPLE; (Vários Anexos).

Esquema URI de Dados -> Nenhum.

Exemplo de Intent:

“public void composeEmail(String [] addresses, String subject, Uri attachment) { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType(“*/*”); intent.putExtra(Intent.EXTRA_EMAIL, addresses ); intent.putExtra(Intent.EXTRA_SUBJECT, subject ); intent.putExtra(Intent.EXTRA_STREAM, attachment ); if (Intent.resolveActivity ( getPackageManager ()) != null ) {

StartActivity(Intent); } }”

Neste caso podemos criar um procedimento para indicarmos o destino, assunto e a mensagem do e-mail. Segue abaixo:

procedure TFrmxIntents.Email(const Destinatario, Assunto, Conteudo: string);Var Recipients: TJavaObjectArray<JString>;begin Try Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_SEND); Recipients:= TJavaObjectArray<JString>.Create(1); Recipients.Items[0] := StringToJString(Destinatario);

Intent.putExtra(TJIntent.JavaClass.EXTRA_EMAIL, Recipients); Intent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(Assunto)); Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(Conteudo));

Intent.setType(StringToJString(‘plain/text’)); SharedActivity.startActivity(TJIntent.JavaClass.createChooser(Intent,StrToJCharSequence(‘Selecione um App. de E-mail.’))); Except on E: Exception do ShowMessage(E.Message); End;end;

Veja que foi necessário a utilização de um vetor ‘ JString ’ para o arma-zenamento dos destinatários do e-mail. Também é possível notar a utilização

junho201422

Listagem 10 – Intent Map.

Listagem 11 – Botão Mapas.

da função ‘putExtra’ que nos permite acessar funções extras deste Intent:

EXTRA_EMAIL Uma Matriz de String que indica os destinatários.EXTRA_SUBJECT Uma String com o Assunto do E-mail.EXTRA_TEXT Uma String com o corpo do E-mail.MIME TYPEPLAIN_TEXT_TYPE (“text / plain”) (“* / *”);

Se utilizarmos conforme apresentado no ‘ MIME Type’ as mensagens serão enviadas através de ‘mensagens de texto’ do Android conforme ilustrado na Imagem 5:

Imagem 5 – Mensagem de texto.

Este não é o objetivo, portanto, para enviarmos e-mail através dos apli-cativos comuns indique o Type como:

(“plain / Text”) ou (‘mailto:’)

Ao utilizar ‘mailto:’ deve indicar qual o aplicativo que irá utilizar, caso contrário uma tela com as opções de aplicativos será apresentada, conforme vemos na imagem abaixo:

Imagem 6 – E-mail.

Ação -> ACTION_VIEW

Esquema URI de Dados -> geo: latitude, longitude; geo: 0,0 q = meu + endereço.

Exemplo de Intent:

“public void showMap(Uri geoLocation) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(geoLocation); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); }}”

procedure TFrmxIntents.btnMapasClick(Sender: TObject);

junho2014 23

begin Comando:= ‘geo://0,0?q=Avare, Sao Paulo’; Try Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW); Intent.setData(TJnet_Uri.JavaClass.parse(StringToJString(TIdURI.URLEncode(Comando)))); SharedActivity.startActivity(Intent); Except on E: Exception do ShowMessage(E.Message); end;end;

Imagem 7 – Mapa.

Conclusão

Observamos um recurso muito útil para facilitar em nosso desenvolvimento a utilização de Intents. Este artigo mostrou alguns dos aplicativos que podem ser acessados, existem outros que podemos utilizar, portanto, com base nesta dica sintam-se livres para implementar e melhorar da forma que for necessário.

Espero que tenham gostado desta dica! Até a Próxima!

Referências

http://developer.android.com/index.html

[email protected]

Jeferson Silva de LimaConsultor The Club.

Sobre o autor

junho201424

junho2014 25

Olá amigos do The Club, neste artigo vou procurar dar algumas di-cas de como devemos criar um serviço do Windows junto com a classe “EventLog”(responsável por registrar tarefas). Usaremos como ferramenta base a última versão do Microsoft Visual Studio, a 2013. Os serviços do Sis-tema Operacional Windows nada mais é que uma aplicação que se inicializa quando o mesmo é carregado rodando em “BackGround”. Aplicações deste tipo é muito útil quando desejamos monitorar de uma forma constante al-guma tarefa, ou seja, efetuar qualquer tarefa em segundo plano enquanto o sistema está ocupado efetuando seu trabalho. Outra característica primordial deste tipo de aplicação é que não devemos possuir componentes visuais, pois como foi dito anteriormente sua característica principal é rodar em segundo plano. Um bom exemplo de utilização de serviços é a atualização constante de Banco de Dados, Monitoração de diretórios ou arquivos, criação de arquivos de logs entre outras. Quando exibimos os serviços instalados por padrão no Windows podemos obter algumas informações como Nome, Descrição, Status e Tipo de Inicialização.

Criando o Projeto de Exemplo

Para isto abra o MVS2013 e navegue até a opção “File/New Project...” e em “Templates/Visual C#/Windows” escolheremos “Windows Service”. Definimos o Nome para “WindowsServiceTheClub”. Ver Imagem 01.

Figura 01: Criando um Novo Projeto.

Criando um serviço no Microsoft Visual Studio 2013

Para registrar os eventos salvaremos nos denominados Logs de Serviços no Windows. Temos um componente que realiza exatamente esta tarefa, clicando na “ToolBox” e na região “Components” podemos localizar o “Even-tLog”. Ver Imagem 02.

Clique e arraste para a nosso Serviço. Lembrando que todos os compo-nentes para se trabalhar com serviços não deverão ser Visuais.

Figura 02: Componente EventLog.

junho201426

Listagem 1

Listagem 2

Teremos no “Service1.cs” o componente como ilustra abaixo (Ver Imagem 03)

Figura 03: Componente Utilizado.

Codificando o Exemplo

Clique com o botão direito escolhendo “View Code”. Abaixo detalharei mais a codificação.

Por padrão temos algumas bibliotecas utilizadas.

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Diagnostics;using System.Linq;using System.ServiceProcess;using System.Text;using System.Threading.Tasks;

namespace WindowsServiceTheClub{

public partial class Service1 : ServiceBase { public Service1() { InitializeComponent(); if (!System.Diagnostics.EventLog.SourceExists(“MySource”))

{ System.Diagnostics.EventLog.CreateEventSource( “MySource”, “MyNewLog”); }

eventLog1.Source = “MySource”; eventLog1.Log = “MyNewLog”;

}

No Construtor da classe “Service” encontramos o método “InitializeCom-ponent”, é este método que executa o início do contrutor da classe abordada em questão. Após esta declaração faremos um “If” para identificar se o arquivo de Log foi criado ou não, utilizando os eventos “Source” e “Log”. O evento “Log” será a identificação do Log, ou seja, “MyNewLog”.

protected override void OnStart(string[] args) { eventLog1.WriteEntry(“Iniciar...”); }

protected override void OnStop() { eventLog1.WriteEntry(“Parar...”); }

protected override void OnContinue() { eventLog1.WriteEntry(“Continuar...”); }

Temos três eventos do tipo“Override” (sobrescritos) para classes deste tipo, sendo: “Onstart” (Iniciar o serviço), “OnStop” (Parar o serviço) e “OnContinue” (Continuar o serviço). Como se trata de um exemplo para aprendizado iremos apenas identificar o tipo de tarefa utilizando o Método “eventLog1.WriteEntry”.

junho2014 27

Listagem 3

}

Criando os Instaladores para o Serviço

Podemos criar estes instaladores para o Windows Services com o auxílio do Visual Studio. Para isto clique com o botão direito sobre o arquivo “Service.cs” e selecione “View Designer”. No plano de fundo clique para selecionar o próprio serviço e com o botão direito escolha “Add Installer”.

Ver Figura 04.

Figura 04: Adicionando o Instalador.

Abaixo o código que foi gerado automaticamente pelo Visual Studio.

using System;using System.Collections;using System.Collections.Generic;using System.ComponentModel;using System.Configuration.Install;using System.Linq;using System.Threading.Tasks;

namespace WindowsServiceTheClub{ [RunInstaller(true)] public partial class ProjectInstaller : System.Configuration.Install.Installer { public ProjectInstaller() {

InitializeComponent(); } }}

Por padrão, uma classe de componente que contém dois instaladores é adicionada ao projeto. O componente é denominado “ProjectInstaller” e os instaladores que ele contém são: o instalador para o seu serviço e o instala-dor para o processo associado do serviço. No modo de exibição Design de “ProjectInstaller”, clique em “ServiceInstaller1” para um projeto do Visual C#.

Na janela Propriedades, defina a propriedade ServiceName como Ser-vicoTheCLub (Este é o nome que irá apresentar nos serviços instalados). Em StartType deixe como Automatic (Desta forma o serviço irá iniciar automati-camente quando o computadorfor reiniciado)

Ver Imagem 05.

Figura 05: ServiceInstaller.

Já no designer, do “ServiceProcessInstaller1” defina a propriedade Account como LocalSystem. Isso fará com que o serviço seja instalado e executado em uma conta de serviço local. Ver Imagem 06.

Observação Importante:

A conta LocalSystem tem amplas permissões, incluindo a capacidade de gravar no log de eventos. Use essa conta com cuidado, pois ela pode aumentar o risco de ataques de software mal-intencionado. Para outras tarefas, pense

junho201428

em usar a conta LocalService, que atua como um usuário não privilegiado no computador local e apresenta credenciais anônimas a qualquer servidor remoto. Esse exemplo falhará se você tentar usar a conta LocalService, uma vez que ela não tem permissões para gravar no log de eventos. (Fonte: http://msdn.microsoft.com/pt-br/library/zt39148a(v=vs.110).aspx)

Figura 06:ServiceProcessInstaller.

Após realizar estas etapas devemos compilar o projeto.

Instalação e desinstalação

A instalação dos serviços deverão ser realizadas via prompt de comando. Para isto clique no menu iniciar digitando “CMD” para abrir a janela responsável por esta tarefa. No meu caso o exemplo de Windows Service foi salvo na pasta

“C:\TheClub\Revista\2014\Revista_07_2014\VisualStudio_Serviços\Win-dowsServiceTheClub\WindowsServiceTheClub\bin\Debug”

O aplicativo “InstallUtil” será o responsável pela instalação e desinstalação do mesmo. Este aplicativo normalmente se encontra na pasta do Framework, veja abaixo:

“C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe”

Para Instalar:

“C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe” “C:\TheClub\Revista\2014\Revista_07_2014\VisualStudio_Serviços\WindowsSer-viceTheClub\WindowsServiceTheClub\bin\Debug”

Para desinstalar:

“C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe” /u “C:\TheClub\Revista\2014\Revista_07_2014\VisualStudio_Serviços\Windo-wsServiceTheClub\WindowsServiceTheClub\bin\Debug”

Receberemos uma mensagem identica à Imagem 07.

Para iniciar o serviço abra o painel de controle e em ferramentas adminis-trativas localize ‘Serviços”. Ver Imagem 08.

Figura 07: Instalação Concluída com sucesso.

junho2014 29

[email protected]

Thiago Cavalheiro Montebugnoliadora aprender novas tecnologias. Formado pela Faculdade de Tecnologia de Botucatu

– SP (FATEC), já desenvolveu softwares utilizando a plataforma .NET, Delphi junto com Banco de Dados SQL Server e Firebird. Atualmente trabalha no Centro de Processamento de Dados da Prefeitura Municipal de Itaí-SP é colunista mensal da Revista The Club Megazine e é consultor Técnico do The Club. Possui as seguintes certificações: MCP - Microsoft Certified Professional, MCTS - Microsoft Certified Technology Specialist, MCAD - Microsoft Certified Application Developer e MCSD - Microsoft Certified Solution Developer.

Sobre o autor

Figura 08: ServicoTheClub.

Por padrão o serviço é instalado com o tipo de inicialização automático e parado. Para isto Selecione seu serviço na lista, clique nele com o botão direito do mouse e clique em Iniciar.

Podemos verificar o Log de eventos clicando com o botão direito sobre no ícone “Meu Computador” escolhendo “Gerenciar”. Teremos uma janela igual ilustra a Imagem 09.

Figura 09: Gerenciamento do Computador.

Navegue até “Ferramentas do Sistema/Visualizador de Eventos/Logs de Aplicativos e Serviços” ali encontramos o Log gerado pelo nosso serviço, no caso, se tudo tiver ocorrido de acordo teremos na aba Geral algumas infor-mações, sendo: “Iniciar...”, “Parar...”, “Continuar...” entre outras informações irrelevantes para este exemplo.

Conclusões

Podemos aprender neste artigo todos os passos necessários para se criar um serviço do Windows utilizando o Microsoft Visual Studio 2013. Apesar do exemplo ser muito simples, pudemos explorar todas as funcionalidades com o mínimo de código possível. Fica aí a dica,

Espero que tenham gostado, um abraço e até a próxima.

junho201430

Listagem 1

dicas the club

Delphi – Deixando a Máscara

igual ao do caixa eletrônico

Muitas vezes precisamos de diversos tipos de diferentes recursos em nos-sos sistemas, nesta dica em especial, iremos deixar a máscara do componente “Tedit” funcionando igual ao Caixa Eletrônico. Para isto coloque no form 1 Tedit e 1 Tlabel. Ver a Imagem 01.

Figura 01: Layout proposto.

Utilizaremos dois eventos do Tedit, sendo o KeyPress e o Click, Ver código abaixo:

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);var Texto, Texto2: string; i: byte; begin if (Key in [‘0’..’9’,chr(vk_back)]) then begin if (key in [‘0’..’9’]) and (Length(Trim(TEdit(Sender).Text))>23) then key := ‘0’; Texto2 := ‘0’; Texto := Trim(TEdit(Sender).Text)+Key; for i := 1 to Length(Texto) do if Texto[i] in

[‘0’..’9’] then Texto2 := Texto2 + Texto[i]; if key = chr(vk_back) then Delete(Texto2,Length(Texto2),1); Texto2 := FormatFloat(‘#,0.00’,StrToInt64(Texto2)/100);

repeat Texto2 := ‘ ‘+Texto2until Canvas.TextWidth(Texto2) >= TEdit(Sender).Width;TEdit(Sender).Text := Texto2;TEdit(Sender).SelStart := Length(Texto2);endelse if ord(key) <> VK_RETURN then Key := ‘0’; abort;end;

procedure TForm1.Edit1Click(Sender: TObject);begin TEdit(Sender).SelStart := Length(TEdit(Sender).Text);end;

Teremos um resultado parecido a Figura 02.

Figura 02: Exemplo em Run-Time.

junho2014 05

junho2014