Executando uma aplicação externa

 

Olá, hoje veremos como executar uma aplicação externa, chamando-a de dentro de nossa aplicação. Veremos como passar parâmetros, esperar pelo seu término e mudar o estado da janela, tudo isso em .net.

Classes do .NET

Como todos sabemos, a class library do .NET encapsulou as APIs  do sistema operacional deixando-as organizadas, fáceis de encontrar. Tudo isso de forma lógica.

Antes do .NET tínhamos as funções do sistema operacional  todas “espalhadas”, e encontrar algo que precisássemos era como procurar uma agulha em um palheiro, isso sem mencionar a ajuda do SDK do Windows que era muito vaga.

Quem encontrava alguma função interessante da API, logo a publicava como uma “dica” para facilitar a vida de outros.

O .NET encapsulou as rotinas gerenciamento de processos  na classe System.Diagnostics.Process, que permite literalmente criar um gerenciador de tarefas como o existente no windows, e é ela que usaremos.

Exemplo

Crie no Delphi 2005 uma nova aplicação Windows Forms, e em seu formulário principal adicione três botões conforme Figura 1.

AppExterna.gif 

Figura 1. Formulário Principal

Adicione System.Diagnostics ao Uses da interface, e adicione um campo privado, de nome FBlocoNotas do tipo Process, à classe do formulário. No evento onClick do primeiro botão adicione o código conforme Listagem 1.

 

Listagem 1.  Chamando o bloco de notas

  FBlocoNotas := Process.Create;

  with FBlocoNotas do

  begin

    StartInfo.FileName := 'notepad.exe';

    StartInfo.Arguments := '.\teste.txt';

    try

      Start;

      Free;

    except

      Free;

    end;

  end;

 

Você se lembra que sem o .NET chamaríamos o bloco de notas assim ?

 

WinExec('notepad.exe teste.txt',SW_SHOW)

 

Você pode pensar agora que foi escrito muito menos, até concordo, mas você também se lembra de quanto tempo você levou para descobrir a existência dessa API ? Veja, WinExec não é uma função do Delphi, e sim uma função do sistema operacional. No evento onClick do segundo botão adicione o código da listagem 2.

 

Listagem 2. Executando o  bloco de notas e esperando pelo seu término

  FBlocoNotas := Process.Create;

  with FBlocoNotas do

  begin

    StartInfo.FileName := 'notepad.exe';

    StartInfo.Arguments := '.\teste.txt';

    try

      Start;

      WaitForExit;

      Free;

    except

      Free;

    end;

  end;

 

Em relação ao código da Listagem 1 temos de diferente apenas o método WaitForExit, é ele quem pára o processo atual (nosso sistema), até o processo iniciado terminar. Todo o processo do “como parar e esperar” está encapsulado dentro do método WaitForExit. Simples e fácil não é ?  Agora para matar saudades... vou mostrar como faríamos isso sem o .Net, implementando uma rotina genérica que é conhecida por muitos a ExecAndWait, veja listagem 3.

 

Listagem 3. Implementação do ExecAndWait

function ExecAndWait(const FileName, Params: string;

  const WindowState: Word): boolean;

var

  SUInfo: TStartupInfo;

  ProcInfo: TProcessInformation;

  CmdLine: string;

begin

  { Coloca o nome do arquivo entre aspas. Isto é necessário devido aos espaços contidos em nomes longos }

  CmdLine := '"' + Filename + '"' + Params;

  FillChar(SUInfo, SizeOf(SUInfo), #0);

  with SUInfo do begin

  cb := SizeOf(SUInfo);

  dwFlags := STARTF_USESHOWWINDOW;

  wShowWindow := WindowState;

  end;

  Result := CreateProcess(nil, PChar(CmdLine), nil, nil, false,

  CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,

  PChar(ExtractFilePath(Filename)), SUInfo, ProcInfo);

  { Aguarda até ser finalizado }

  if Result then begin

  WaitForSingleObject(ProcInfo.hProcess, INFINITE);

  { Libera os Handles }

  CloseHandle(ProcInfo.hProcess);

  CloseHandle(ProcInfo.hThread);

  end;

end;

 

Quantos de nós simplesmente não copiamos essa função para dentro de nossos sistemas?  Agora quem realmente sabe explicar em detalhes cada linha que está sendo executada? Ou conhece cada tipo utilizado? Tudo isso em .NET resume-se ao WaitForExit. E para terminar, coloque no evento onClick do terceiro botão o código da Listagem 4

 

Listagem 4. Executando o Bloco de notas, com sua janela minimizada

  FBlocoNotas := Process.Create;

  with FBlocoNotas do

  begin

    StartInfo.FileName := 'notepad.exe';

    StartInfo.Arguments := '.\teste.txt';

    StartInfo.WindowStyle := ProcessWindowStyle.Minimized;

    try

      Start;

      Free;

    except

      Free;

    end;

end;

 

A diferença agora está por conta da classe StartInfo. Ela expõe de forma lógica parâmetros para a execução do processo a ser executado. Em nosso exemplo estamos mudando o estilo da janela para  minizado, poderíamos ter maximizado. O que quero mostrar com isso é que o estilo da janela é um tipo enumerado de ProcessWindowStyle.  Tudo foi encapsulado e organizado de forma lógica para que fosse facilmente utilizado por nós programadores.

Não importa qual a linguagem a utilizar, essas são classes do framework, o que vai mudar é apenas sintaxe. Fica aqui meu abraço a todos, e mais uma dica: estudem o framework, leiam o SDK do .NET de vez em quando, não esperem a necessidade bater.

Até a próxima !

 

 

Paulo Roberto Quicoli (pauloquicoli@gmail.com) é analista e programador da Control-M Informática. Trabalha com Delphi, desde sua primeira versão, e Firebird desenvolvendo aplicações cliente-servidor. Formado em Tecnologia de Processamento de dados pela FATEC, na cidade de Taquaritinga/SP.