Abrir Aplicativo e Aguardar o fechamento..?

Delphi

29/11/2004

Colegas..

Como faço para abrir um aplicativo externo ao delphi, e esperar até que seja encerrado o processo para continuar executando o delphi..?

por exemplo :

Pretendo abrir um arquivo armazenado no firebird com a extensão .doc.

Como faço para chamar o aplicativo responsável pelo processo desta extensão, achá-lo, executá - lo e aguardar que o arquivo seja fechado para continuar a utilizar o sistema?

Agradeço muito a atenção de todos, antecipadamente.


Cabelo

Cabelo

Curtidas 0

Respostas

Aroldo Zanela

Aroldo Zanela

29/11/2004

Colega,

Como eu já te conheço há muito tempo, tenho certeza que você deve ter pesquisado antes de postar. Mas mesmo assim, neste link tem uma resposta que considero suficiente, veja: http://delphiforum.icft.com.br/forum/viewtopic.php?t=21753&highlight=winexec+aguardar


GOSTEI 0
Cabelo

Cabelo

29/11/2004

Cra valeu a dica, mas eu esquecí de mencionar uma informação primordial, eu estou compilando em .CLX, e não posso usar a classe windows, como fazer?


GOSTEI 0
Cabelo

Cabelo

29/11/2004

Alguém??


GOSTEI 0
Dopi

Dopi

29/11/2004

Por incrivel que pareça é bem mais simples que no Windows...

procedure RunCommand(Command: String; Wait : Boolean);
var
  {$ifdef MSWINDOWS}  Show : Integer;{$endif}
  ConnectCommand : PChar;
begin
  {$ifdef LINUX}
     if not Wait then
        Command := Command + ´ &´ ;  { & = Rodar em BackGround}
     ConnectCommand := PChar(Command);
     Libc.system(ConnectCommand);
  {$endif}
  {$ifdef MSWINDOWS}
  { IMPLEMENTAR AQUI O CODIGO  WINDOWS PARA ESPERA }
     ConnectCommand := PChar(Command);
     Show := sw_ShowNormal;
     winexec(ConnectCommand, Show);
  {$endif}
end;


Ou seja, é só dar um System( ´SeuComando´ ) sem o & no final...


GOSTEI 0
Dopi

Dopi

29/11/2004

Esqueci de um detalhe, adcione na Uses da Unit:

 {$ifdef LINUX} Libc, {$endif}
 {$ifdef MSWINDOWS} Windows, {$endif}


Nao há problema uma aplicaçao CLX fazer uso da unit Windows... os proprios fontes da CLX / Delphi 7 fazem isso... No Linux, obviamente essa Unit não existe...

Veja o inicio da Unit QForms.pas do Delphi 7
{ *************************************************************************** }
{                                                                             }
{ Delphi and Kylix Cross-Platform Visual Component Library                    }
{                                                                             }
{ Copyright (c) 2000-2002 Borland Software Corporation                        }
{                                                                             }
{ *************************************************************************** }

unit QForms;

{$P+,S-,W-,R-,T-,H+,X+}

interface

uses
{$IFDEF LINUX}
  Xlib,
{$ENDIF}
{$IFDEF MSWINDOWS}
  Windows, Messages,
{$ENDIF}
  Qt, QTypes, SysUtils, Classes, Types, QGraphics, QControls, QMenus,
  QActnList, QStyle, HelpIntfs;



GOSTEI 0
Cabelo

Cabelo

29/11/2004

Colega Dopi..

Funcionou perfeitamente, tanto no Delphi 7 quanto no Kylyx 3...

Só tem um problema com a função indicada pelo colega Aroldo Zanela, no windows, usando esta função que ele me passou, não consigo fechar o Editor de Text MSWord, ele dá um tempo e manda uma mensagem do Word :

´Esta operação demorou tempo demais, deseja continuar tentando?´..

se eu colocar sim ele dáum novo tempo de depois dá a mesma mensagem novamente, mas se der um não, ele fecha e volta tudo ao normal, vc sabe me dizer o pq?


GOSTEI 0
Dopi

Dopi

29/11/2004

Ola Cabelo....

A funçao citada é bem conhecida na Internet... quase todas as buscas por funçao desse tipo retornam algo semelhante...

Se vc possui a Biblioteca JEDI instalada com a JCL voce pode usar a funçao: ShellExecAndWait

function ShellExecAndWait(const FileName: string; const Parameters: string = ´´; const Verb: string = ´´; CmdShow: Integer = SW_SHOWNORMAL): Boolean;

da Unit: JclShell

é possível ainda abrir a Unit e importar o código da Funçao para o seu aplicativo... Pelo que notei ela tem o código um pouco diferente da funçao citada pelo Aroldo...


GOSTEI 0
Cabelo

Cabelo

29/11/2004

Como faço para abrir esta UNIT, não consegui achá - la?


GOSTEI 0
Dopi

Dopi

29/11/2004

A JclShell faz parta da JCL que pode ser instalada junto com a Jedi.

A JCL não são componentes como a JVCL, mas sim um conjunto de Units com Functions/Procedures muito interessantes...

Se vc instalou a Jedi full ela estará em:
($JEDI)\JCL\source

Onde ($JEDI) é o path onde vc instalou a biblioteca JEDI
Vc pode baixar a Jedi full em:
http://sourceforge.net/project/showfiles.php?group_id=45786

eu uso a versão JVCL 2.10 Stable. Arquivo: JCL+JVCL210FullInstall.zip

O arquivo Help da JCL é bem completo e já é instalado na IDE do Delphi automaticamente.


GOSTEI 0
Cabelo

Cabelo

29/11/2004

Colegas..

Já estou com este problema a muito tempo, e está ficando nsustentável, pois a reclamação dos usuários em relação ao uso do Word, é muito complicado.

Continua dando o erro :


´Esta operação demorou tempo demais, deseja continuar tentando?´..

tenho a UNIT Jedi instalado, e mesmo assim continua dando o erro, mesmo utilizando a função ShellExecuteAndWait como o colega Dopi me passou.

Mas o problema continua, alguém sabe como resolver este problema?


GOSTEI 0
Cabelo

Cabelo

29/11/2004

Colegas.. Já estou com este problema a muito tempo, e está ficando nsustentável, pois a reclamação dos usuários em relação ao uso do Word, é muito complicado. Continua dando o erro : ´Esta operação demorou tempo demais, deseja continuar tentando?´.. tenho a UNIT Jedi instalado, e mesmo assim continua dando o erro, mesmo utilizando a função ShellExecuteAndWait como o colega Dopi me passou. Mas o problema continua, alguém sabe como resolver este problema?


Alguém ????


GOSTEI 0
Marco Salles

Marco Salles

29/11/2004

Cabelo , amigo... So me responda o seguinte

Como faço para abrir um aplicativo externo ao delphi, e esperar até que seja encerrado o processo para continuar executando o delphi..?


Uma vez eu criei uma rotina , que fazia o seguinte...
O Usuário clicava no botão , para chamar por exemplo a calculadora do delphi... Neste ponto o programa era minimizado e so voltava no estado Normal apos o fechamento da Calculadora


Resta saber se isto te enteressa e se te serve.. Porque o codigo que faz uso da Unit Windows :cry: :cry:

mas pelo que falaram:

Nao há problema uma aplicaçao CLX fazer uso da unit Windows...


Se esta idéia te interressar e o fato de se usar a unit Windows não for um incoveniente e so postar..


GOSTEI 0
Marco Salles

Marco Salles

29/11/2004

Uma vez eu criei uma rotina , que fazia o seguinte... O Usuário clicava no botão , para chamar por exemplo a calculadora do delphi... Neste ponto o programa era minimizado e so voltava no estado Normal apos o fechamento da Calculadora


Corrigindo...

[b:422ebe5408]para chamar por exemplo a calculadora do delphi[/b:422ebe5408]... trocar por:

[b:422ebe5408]para chamar por exemplo a Calculadora do Windows[/b:422ebe5408]

p:s .. o fato de ser [b:422ebe5408]minimizado[/b:422ebe5408] , pode ser alterado para[b:422ebe5408] escondido[/b:422ebe5408], :arrow: sem perda de generalidade...


GOSTEI 0
Cabelo

Cabelo

29/11/2004

[quote:e7894a3e8d=´Marco Salles´]Cabelo , amigo... So me responda o seguinte

Resta saber se isto te enteressa e se te serve.. Porque o codigo que faz uso da Unit Windows :cry: :cry:

mas pelo que falaram:

Nao há problema uma aplicaçao CLX fazer uso da unit Windows...


Se esta idéia te interressar e o fato de se usar a unit Windows não for um incoveniente e so postar..[/quote:e7894a3e8d]

Colega..

Interessa sim, já que tenho que usar codificação diferentes tanto pra Windows quanto pra Linux.


GOSTEI 0
Marco Salles

Marco Salles

29/11/2004

com oeu dise é so ara te dar um idéia .. E claro que se pode fazer a mesma coisa com alguma função especifica.. Mas na época eu não obtive sucesso e então eu adaptei com as minhas que eu tinha

Veja se da para entender:

Function VerficarSeAplicaticoEstarRodandoPeloNomeDoExecutavel(Nome:String):Boolean; 
var rId:array[0..999] of DWord; i,NumProc,NumMod:DWord;
    HProc,HMod:THandle; sNome:String; 
    Tamanho, Count:Integer; 
    sNomeTratado:String; 
begin 
  result:=False; 
  SetLength(sNome, 256); 
// Aqui vc pega os IDs dos processos em execução 
  EnumProcesses(@rId[0], 4000, NumProc);

// Aqui vc faz um for p/ pegar cada processo 
  for i := 0 to NumProc div 4 do 
  begin 
// Aqui vc seleciona o processo 
    HProc := OpenProcess(Process_Query_Information or Process_VM_Read, FALSE, rId[i]); 
    if HProc = 0 then 
      Continue; 
// Aqui vc pega os módulos do processo 
// Como vc só quer o nome do programa, então será sempre o primeiro 
    EnumProcessModules(HProc, @HMod, 4, NumMod); 
// Aqui vc pega o nome do módulo; como é o primeiro, é o nome do programa 
    GetModuleBaseName(HProc, HMod, @sNome[1], 256); 
    sNomeTratado := trim(sNome); 
    Tamanho:=Length(SnomeTratado); 
     Count:=1; 
     While Count <= Tamanho do 
       begin 
         if SnomeTratado[Count]= ´´ Then 
           Break; 
        count:=Count+1; 
       end; 
     sNomeTratado:=Copy(SnomeTratado,1,Count-1); 
    if AnsiUpperCase(sNomeTratado)=AnsiUpperCase(Nome) Then 
      Result:=True; 
// Aqui vc libera o handle do processo selecionado 
    CloseHandle(HProc); 
  end; 
end;


Aqui eu chamo o aplicativo externo ao delphi... No meu caso foi a calculadora
procedure TForm1.Button1Click(Sender: TObject);
begin
 WinExec(´C:\Windows\System32\Calc.exe´,SW_ShowNormal);
//Escondo a aplicação
 Form1.Hide;
//Habilito um componente Timer com intervalo a seu gosto..
//Na epoca fiz c0m Intervalo 10 = que é o mesmo que  1s /100
 Timer1.Enabled:=True;
end;


e finalmente no evento ontimer do componente fiz assim

procedure TForm1.Timer1Timer(Sender: TObject);

begin
 if not(VerficarSeAplicaticoEstarRodandoPeloNomeDoExecutavel(´Calc.exe´)) then
   begin
     Timer1.enabled:=False;
     Form1.Show;
     Form1.FormStyle := fsStayOnTop;
   end;
end;


:P :P :P :P :P
Rodou que era uma beleza ..Para mim serviu como uma luva , espero que sirva para voce tb


GOSTEI 0
Cabelo

Cabelo

29/11/2004

Qual a UNIT que devo declara..

Só a Windows..

Se for, não funcionou.. :cry:

Tem mais alguma?


GOSTEI 0
Marco Salles

Marco Salles

29/11/2004

Qual a UNIT que devo declara..


PSApi



GOSTEI 0
Cabelo

Cabelo

29/11/2004

Muito obrigado pela dica..

Está dando um erro assim que eu abro o aplicativo..

Erro : ´ACCESS Violation ......´

nesta linha

HProc := OpenProcess(Process_Query_Information or Process_VM_Read, FALSE, rId[i]);

tem idéia do motivo..?


GOSTEI 0
Marco Salles

Marco Salles

29/11/2004

So uma dica...

Pelo que sei EAccessviolation é um erro gerado quando um programa tenta acessar memória alocada para um objeto que não mais existe , ou mesmo que nunca existiu...

[b:c3f0c20e36]A propriedade Enabled do componente Timer Deve ser cetada inicialmente Como false..[/b:c3f0c20e36]. É Interresante que o evento onTimer so seja disparado quando o aplicativo é chamado..Logo apos o aplicativo ser fechado , o evento Ontimer deve ficar desabilitado...

:idea: :idea:
Isto é so uma dica , talves voce não tenha feito isto , e quando o programa for executado , por alguma razão , o envento timer é disparado antes que o objeto em questão tenha sido criado...

Mesmo que isto , não seje o problema , tb por razoes de otimização, o evento ontimer so deve ser habilitado quando o aplicativo for chamado...
Não ha porque o programa ficar processando ´contas´ qua não serão usadas...

Talvez isto resolva o Problema , talves não... Por se tratar de compiladores diferentes , como voce mencionou no inicio..


GOSTEI 0
Cabelo

Cabelo

29/11/2004

Estou habilitando o evento do timer somente quando eu abro o Word, pois ele precisa ficarverificando se o aplicativo está aberto não?


Portanto logo após a linha do winexec, eu já dou um enable true no timer.

Logo depois de fechar sua função já dá um enable false nele também.

Percebí que enquanto estiver debugando funciona blz.

Já tive problemas assim com timer, mas não me lembro o pq?


GOSTEI 0
Marco Salles

Marco Salles

29/11/2004

Percebí que enquanto estiver debugando funciona blz.


É um bom começo...

Eu tb ja tive um problema com o timer , que é mais ou menos isto...
Parece que , mesmo a que a aplicação , continue rodando em segundo plano, algo ´paralisa´ a contagem do timer...

Tente duas coisas:::

[b:3f1df07571]Tente so trocar a propriedade formSystle do form para fsStayOnTop no objecto inspector[/b:3f1df07571]

[b:3f1df07571]Tente aumentar um pouco o tempo do intervalo
do timer[/b:3f1df07571]


GOSTEI 0
Cabelo

Cabelo

29/11/2004

Não funcionou.. o erro persiste, coloquei 5 segundos.. no timer e nada..

continua dando erro..

Na mesma linha..

Alterei também o form style...

Tem alguma idéia do que pode aestar acontecendo?


GOSTEI 0
Marco Salles

Marco Salles

29/11/2004

Quando eu disse aumentar , na verdade eu pensei que voce estivesse trabalhando com valores bem pequenos no intervalo do Timer... No meu caso eu trabalhava na ordem de 10 ====1/100 segundos

[b:4236086a79]então tente diminuir , o intervalo como uma alternativa desesperada [/b:4236086a79]:lol:

Eu não entendi essas passagens :?: :?:
Logo depois de fechar sua função já dá um enable false nele também

Não é na função , mas sim no próprio evento ontimer do componenteTimer

procedure TForm1.Timer1Timer(Sender: TObject);

begin 
 if not(VerficarSeAplicaticoEstarRodandoPeloNomeDoExecutavel(´Calc.exe´)) then 
   begin 
     Timer1.enabled:=False; 
     Form1.Show; 
     Form1.FormStyle := fsStayOnTop; 
   end; 
end;


[b:4236086a79]e nen essas duas afirmaçoes que parecem contraditórias[/b:4236086a79] :?: :?: :?:

Está dando um erro assim que eu abro o aplicativo..


Percebí que enquanto estiver debugando funciona blz.


[b:4236086a79]Continua isto mesmo[/b:4236086a79] :?: :?:


GOSTEI 0
Cabelo

Cabelo

29/11/2004

Continua o erro, na mesma linha..

Será que é problema com o compilador?


GOSTEI 0
Marco Salles

Marco Salles

29/11/2004

voce ainda não me respondeu a esta pergunta::::

Citação:
Está dando um erro assim que eu abro o aplicativo..


Citação:
Percebí que enquanto estiver debugando funciona blz.

essas duas afirmaçoes que parecem contraditórias , porque se o erro da quando se abre o aplicativo , deveria dar tb quando se debuga.. Logo no inicio :?: :?: :?:


GOSTEI 0
Cabelo

Cabelo

29/11/2004

É exatamente isso...

É contraditório, mas está ocorrendo..

Só dá erro se eu não debugar o programa..

quando eu debugo, passa pela linha e não dá erro..


GOSTEI 0
Marco Salles

Marco Salles

29/11/2004

Deixa eu fazer um teste aqui... Qual é o nome do Word que voce esta usando para testar a função

Function VerficarSeAplicaticoEstarRodandoPeloNomeDoExecutavel(Nome:String):Boolean;


qual o nome :?: :?: :?:

No caso da calculadora é calc.exe e o word como é ::::


GOSTEI 0
Cabelo

Cabelo

29/11/2004

WinWord.Exe


GOSTEI 0
Marco Salles

Marco Salles

29/11/2004

Qual o comando que voce esta usando para abrir este aplicativo via delphi

Não consegui abri-lo via comando:

WinExec(´C:\Windows\System32\WinWord.Exe´,SW_ShowNormal);


:cry: :cry: :cry:

Bem resolvi abri-lo na mão.. Foi um tiro :P :P :P :P :P

Abrir o woed e cliquei no botão para ativar o timer :arrow: .. o aplicativo some

Fechei o word e :::: tiro novamente o aplicativo aparece :P :P :P

coloquei um intervalo de tempo pequeno ..Intervalo=10

mas sabe de uma coisa:

[b:35c5247c6d]Tudo dá certo no final, se não deu certo é porque não chegou o fim ainda.[/b:35c5247c6d]


GOSTEI 0
Cabelo

Cabelo

29/11/2004

Você tem o Office instalado?

Se tiver está assim :

WinExec(C:\Arquivos de programas\Microsoft Office\Office\WinWord.Exe´,SW_ShowNormal);

você usa VCL??


GOSTEI 0
Marco Salles

Marco Salles

29/11/2004

Você tem o Office instalado? Se tiver está assim : WinExec(C:\Arquivos de programas\Microsoft Office\Office\WinWord.Exe´,SW_ShowNormal);


No meu windows xp esta assim:

[b:6fc35146d6]WinExec(´C:\Arquivos de programas\Microsoft Office\Office10\WinWord.Exe´,SW_ShowNormal);[/b:6fc35146d6]

você usa VCL??

Nos testes que estou fazendo sim.. O Uso de pacotes é frequente mas não sempre recomendado... Pelo que ja li em biografias so é mais recomendável quando se tem muitos aplicativos em um do Sistema..
Os aplicativos construidos com pacotes em tempo de execução aparentemente menor somados ao tamanho destas Bibliotecas dinamicas, geralmente sera maior do que o espaço exigido pelo arquivo executável aparentemente maior ... Bem isto é do uma Opinião...


GOSTEI 0
Cabelo

Cabelo

29/11/2004

Ainda não resolvi o meu problema...

Por quê será que dá este erro..?


GOSTEI 0
POSTAR