Fechar sistema ao rodar aplicativo externo
Dai pessoal 8)
Estou terminando a parte de atualização automática do meu sistema, e um probleminha que eu enfrentei sempre foi com o WinExec.
Não com ele, mas vamos supor que o Principal.exe chama o Update.exe via WinExec, e logo após faça um Application.Terminate:
Teoricamente deveria funcionar, até funciona. O problema é que o [b:333459da78]Terminate[/b:333459da78] só é executado junto (ou praticamente junto) com o fim da execução do Update.exe, e dessa forma, o Update.exe não consegue sobreeescrever o Principal.exe
Alguém aí tem uma idéia??
Valeu!! :wink:
Estou terminando a parte de atualização automática do meu sistema, e um probleminha que eu enfrentei sempre foi com o WinExec.
Não com ele, mas vamos supor que o Principal.exe chama o Update.exe via WinExec, e logo após faça um Application.Terminate:
WinExec(PChar(ExtractFilePath(ParamStr(0)) + ´update.exe´), SW_HIDE); Application.Terminate;
Teoricamente deveria funcionar, até funciona. O problema é que o [b:333459da78]Terminate[/b:333459da78] só é executado junto (ou praticamente junto) com o fim da execução do Update.exe, e dessa forma, o Update.exe não consegue sobreeescrever o Principal.exe
Alguém aí tem uma idéia??
Valeu!! :wink:
Felipeaj
Curtidas 0
Respostas
Felipeaj
09/04/2007
Completando o post, já que não tem como editar:
Acho que deveria haver alguma modificação no Update.exe, já que se por exemplo eu colocar um ShowMessage(´Oi´); no início do código do Update.exe (antes das cópias dos arquivos), antes de o usuário poder clicar no OK, o Principal.exe fecha e a cópia ocorre com sucesso.
Sem uma ´pausa´, o Principal.exe não fecha até o fim da execução do Update.exe.
E não adianta colocar Sleep(), nem Application.ProcessMessages...
Valeu 8)
Acho que deveria haver alguma modificação no Update.exe, já que se por exemplo eu colocar um ShowMessage(´Oi´); no início do código do Update.exe (antes das cópias dos arquivos), antes de o usuário poder clicar no OK, o Principal.exe fecha e a cópia ocorre com sucesso.
Sem uma ´pausa´, o Principal.exe não fecha até o fim da execução do Update.exe.
E não adianta colocar Sleep(), nem Application.ProcessMessages...
Valeu 8)
GOSTEI 0
Marco Salles
09/04/2007
não lhe o seu tópico , mas acho que voce quer fechar o aplicativo e executar via winexec um outro programa ???
voce pode usar um delay para isto , mandando e preocsessando uma mensagem do windows ou mais simples aplicar um retardo na suia aplicação
voce pode usar um delay para isto , mandando e preocsessando uma mensagem do windows ou mais simples aplicar um retardo na suia aplicação
WinExec(PChar(ExtractFilePath(ParamStr(0)) + ´update.exe´), SW_HIDE);
sleep(50)
Close; ;// se estiver no form principal
GOSTEI 0
Felipeaj
09/04/2007
Sim, é isso que eu quero, e está funcionando
Só que o Principal.exe demora pra fechar, fecha junto com o término da execução do Update.exe
Gostaria de saber como fazer p/ que o Update.exe só continuasse a execução dos comandos, quando o principal.exe estivesse fechado (colocar um sleep no update.exe não adianta).
Só que o Principal.exe demora pra fechar, fecha junto com o término da execução do Update.exe
Gostaria de saber como fazer p/ que o Update.exe só continuasse a execução dos comandos, quando o principal.exe estivesse fechado (colocar um sleep no update.exe não adianta).
GOSTEI 0
Djjunior
09/04/2007
crie essa função :
a chamada fica algo do tipo
tipo ele vai abrir uma janela do DOS ( O ShowCmd) executa teu aplicativo e retorna o código de erro do programa (se for o caso tipo o errorlevel do chose do DOS)
function ExecuteFileWait(const FileName, Params, StartDir: PAnsiChar;
ShowCmd: Integer): Integer;
var
Info: TShellExecuteInfo;
ExitCode: DWORD;
begin
Screen.Cursor:= crHourGlass;
FillChar(Info, SizeOf(Info), 0);
Info.cbSize:= SizeOf(TShellExecuteInfo);
with Info do begin
fMask:= SEE_MASK_NOCLOSEPROCESS;
Wnd:= Application.Handle;
lpFile:= FileName;
lpParameters:= Params;
lpDirectory:= StartDir;
nShow:= ShowCmd;
end;
if ShellExecuteEx(@Info) then begin
repeat
Application.ProcessMessages;
GetExitCodeProcess(Info.hProcess, ExitCode);
until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
Result:= ExitCode;
end
else Result:= -1;
Screen.Cursor:= crDefault;
end;
a chamada fica algo do tipo
ExecuteFileWait(´SeuPrograma´, Parametros, ´´, 1 );
tipo ele vai abrir uma janela do DOS ( O ShowCmd) executa teu aplicativo e retorna o código de erro do programa (se for o caso tipo o errorlevel do chose do DOS)
GOSTEI 0
Djjunior
09/04/2007
crie essa função :
a chamada fica algo do tipo
tipo ele vai abrir uma janela do DOS ( O ShowCmd) executa teu aplicativo e retorna o código de result do programa (se for o caso tipo o errorlevel do chose do DOS)
function ExecuteFileWait(const FileName, Params, StartDir: PAnsiChar;
ShowCmd: Integer): Integer;
var
Info: TShellExecuteInfo;
ExitCode: DWORD;
begin
Screen.Cursor:= crHourGlass;
FillChar(Info, SizeOf(Info), 0);
Info.cbSize:= SizeOf(TShellExecuteInfo);
with Info do begin
fMask:= SEE_MASK_NOCLOSEPROCESS;
Wnd:= Application.Handle;
lpFile:= FileName;
lpParameters:= Params;
lpDirectory:= StartDir;
nShow:= ShowCmd;
end;
if ShellExecuteEx(@Info) then begin
repeat
Application.ProcessMessages;
GetExitCodeProcess(Info.hProcess, ExitCode);
until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
Result:= ExitCode;
end
else Result:= -1;
Screen.Cursor:= crDefault;
end;
a chamada fica algo do tipo
ExecuteFileWait(´SeuPrograma´, Parametros, ´´, 1 );
tipo ele vai abrir uma janela do DOS ( O ShowCmd) executa teu aplicativo e retorna o código de result do programa (se for o caso tipo o errorlevel do chose do DOS)
GOSTEI 0
Felipeaj
09/04/2007
[b:31b7b5ce51]djjunior[/b:31b7b5ce51], valeu pela ajuda!
Mas o problema é o oposto...
O principal.exe chama a aplicação externa update.exe e se fecha (application.terminate)
O problema é justamente que o principal.exe demora p/ se fechar. Os dois aplicativos NAO PODEM estar rodando junto! Por que? Porque dai o update.exe nao consegue atualizar o principal.exe!
o que eu preciso é de alguma forma que o update.exe fique parado, esperando o principal.exe ser finalizado efetivamente...
Mas o problema é o oposto...
O principal.exe chama a aplicação externa update.exe e se fecha (application.terminate)
O problema é justamente que o principal.exe demora p/ se fechar. Os dois aplicativos NAO PODEM estar rodando junto! Por que? Porque dai o update.exe nao consegue atualizar o principal.exe!
o que eu preciso é de alguma forma que o update.exe fique parado, esperando o principal.exe ser finalizado efetivamente...
GOSTEI 0
Briciosm
09/04/2007
Simples!
Faz assim...
Dentro do teu sistema update.exe coloca um componente timer. E deixa configurado para 5 segundos, por exemplo.
O teu sistema principal irá fechar e chamar o update.exe.
E só após 5 segundos, por exemplo, ele irá atualizar o sistema.
Outra solução seria:
Em vez de tu chamar o sistema principal, tu chama outro aplicativo que verifica se tem alguma atualização.
Se tiver tu atualiza.
E depois chama o sistema. (Derrepente terá que colocar um timer pois a atualização poderá demorar alguns segundos)
E depois tu fecha este aplicativo que faz a atualização.
Seria isso!
Faz assim...
Dentro do teu sistema update.exe coloca um componente timer. E deixa configurado para 5 segundos, por exemplo.
O teu sistema principal irá fechar e chamar o update.exe.
E só após 5 segundos, por exemplo, ele irá atualizar o sistema.
Outra solução seria:
Em vez de tu chamar o sistema principal, tu chama outro aplicativo que verifica se tem alguma atualização.
Se tiver tu atualiza.
E depois chama o sistema. (Derrepente terá que colocar um timer pois a atualização poderá demorar alguns segundos)
E depois tu fecha este aplicativo que faz a atualização.
Seria isso!
GOSTEI 0
Felipeaj
09/04/2007
Realmente, não sei porque não usei o timer
Achei que não iria funcionar
Mas fiz diferente. Pus um timer, que a cada 0,2 segundos verifica se a aplicação principal está rodando. Se NÃO, pára o timer e roda atualização!
Funcionou perfeito!
Valeu pela ajuda!
Achei que não iria funcionar
Mas fiz diferente. Pus um timer, que a cada 0,2 segundos verifica se a aplicação principal está rodando. Se NÃO, pára o timer e roda atualização!
Funcionou perfeito!
Valeu pela ajuda!
GOSTEI 0
Adriano Santos
09/04/2007
Aqui eu fiz o contrário camarada. O meu executável Atualizador.exe fecha o Principal.exe, se liga:
[list:de244f7994]
[*:de244f7994] 1. Eu mostro para o usuário todos os módulos que necessitam de atualizações.
[*:de244f7994] 2. Quando o cara clica em ´Atualizar agora´ ai sim eu verifico se existe algum módulo (executável aberto):
[quote:de244f7994=´Funções PreencherModulosAbertos´]
[/quote:de244f7994]
[quote:de244f7994=´Funções FecharModulosAbertos´]
[/quote:de244f7994]
[/list:u:de244f7994]
Como que eu sei o módulo que está aberto?
Bem, fiz um esquema simples, mas eficiente hehehe...se liga, eu tenho no meu arquivo Atualizacoes.amk que fica no meu servidor a seguinte estrutura:
[quote:de244f7994=´EStrutura do arquivo´]
...
Modulo1=Operacao.exe
Versao1=vF6.1.02
Titulo1=Operacional
Modulo2=Cobranca.exe
Versao2=vF6.1.02
Titulo2=Faturamento/Cobrança
...
[/quote:de244f7994]
Onde o Titulo? contém o ´titulo´ do meu programa gravado no Project >> Options do projeto, que consequentemente, é o titulo dele no Windows.
Neste caso o meu usuário abre o Atualizador.exe por fora do meu sistema pq ainda não criei o link pra abrir por dentro. Porém mesmo colocando o link dentro do sistema vai funcionar tranquilamente.
Qq coisa eu mando o fonte do projeto Atualizador.exe, sem problemas.
[list:de244f7994]
[*:de244f7994] 1. Eu mostro para o usuário todos os módulos que necessitam de atualizações.
[*:de244f7994] 2. Quando o cara clica em ´Atualizar agora´ ai sim eu verifico se existe algum módulo (executável aberto):
{Aqui verifica se existem módulos abertos. Caso haja o usuário será alertado e os mesmos fechados na confirmação dele}
PreencherModulosAbertos;
if ModulosAbertos.Count > 0 then
begin
if MessageBox(Handle, ´Um ou mais módulos do sistema América encontram-se em execução.´ + #13 +
´Deseja fechá-los e continuar a atualização do sistema?´, ´Alerta´, MB_ICONQUESTION + MB_YESNO) = ID_YES then
FecharModulosAbertos
else
begin
btnAtualizar.Enabled := True;
btnFechar.Enabled := True;
Tamanho_Arquivo := 1;
Exit;
end;
end;
[quote:de244f7994=´Funções PreencherModulosAbertos´]
procedure TfAtualiza.PreencherModulosAbertos;
var
I: Integer;
begin
IniRemota := TIniFile.Create(ExtractFilePath(Application.ExeName) + gsArqRemoto);
ModulosAbertos.Clear;
for I := 1 to 20 do
begin
{Verifica se a chave existe, ou seja, se o "I" atual corresponde à algum módulo no arquivo. local.ini}
if not IniRemota.ValueExists(´Atualizacoes´, ´Modulo´ + IntToStr(I)) then
Break;
{Nome e tamanho do Módulo}
Titulo := IniRemota.ReadString(´Atualizacoes´, ´Titulo´ + IntToStr(I), Titulo);
if FindWindow(nil, PChar(Titulo)) > 0 then
ModulosAbertos.Add(Titulo);
end;
IniRemota.Free;
end;
[/quote:de244f7994]
[quote:de244f7994=´Funções FecharModulosAbertos´]
procedure TfAtualiza.FecharModulosAbertos; var I: Integer; begin IniRemota := TIniFile.Create(ExtractFilePath(Application.ExeName) + gsArqRemoto); for I := 0 to ModulosAbertos.Count - 1 do if FindWindow(nil, PChar(ModulosAbertos[I])) > 0 then PostMessage(FindWindow(nil, PChar(ModulosAbertos[I])), WM_CLOSE, 0, 0); IniRemota.Free; end;
[/quote:de244f7994]
[/list:u:de244f7994]
Como que eu sei o módulo que está aberto?
Bem, fiz um esquema simples, mas eficiente hehehe...se liga, eu tenho no meu arquivo Atualizacoes.amk que fica no meu servidor a seguinte estrutura:
[quote:de244f7994=´EStrutura do arquivo´]
...
Modulo1=Operacao.exe
Versao1=vF6.1.02
Titulo1=Operacional
Modulo2=Cobranca.exe
Versao2=vF6.1.02
Titulo2=Faturamento/Cobrança
...
[/quote:de244f7994]
Onde o Titulo? contém o ´titulo´ do meu programa gravado no Project >> Options do projeto, que consequentemente, é o titulo dele no Windows.
Neste caso o meu usuário abre o Atualizador.exe por fora do meu sistema pq ainda não criei o link pra abrir por dentro. Porém mesmo colocando o link dentro do sistema vai funcionar tranquilamente.
Qq coisa eu mando o fonte do projeto Atualizador.exe, sem problemas.
GOSTEI 0
Felipeaj
09/04/2007
[b:ce96e550f5]Adriano Santos[/b:ce96e550f5], valeu aí cara!
Muito interessante teu sistema. Em casa, com mais calma, vou dar uma olhada melhor!
Eu precisei montar o meu da seguinte forma: durante o uso do sistema, ele chama o update.exe (via WinExec) com parâmetro ´download´, p/ somente baixar (da internet) e guardar numa pasta os arquivos atualizados
Na próxima execução, antes do login, o sistema se fecha, chama o update.exe (parâmetro copia), e o update.exe chama de volta o principal.exe
O por que essa mão toda? Porque o cliente não tem que clicar em NADA! Quanto menos o usuário (em específico) clicar ou mecher nisso, melhor! O sistema se atualiza bonitinho e o cliente fica feliz!! :wink:
Como eu fiz tá funcionando, mas mesmo assim vou dar uma lida na tua idéia, quem sabe mais pra frente... 8)
Novamente, valeu a todos pelas dicas!!
Muito interessante teu sistema. Em casa, com mais calma, vou dar uma olhada melhor!
Eu precisei montar o meu da seguinte forma: durante o uso do sistema, ele chama o update.exe (via WinExec) com parâmetro ´download´, p/ somente baixar (da internet) e guardar numa pasta os arquivos atualizados
Na próxima execução, antes do login, o sistema se fecha, chama o update.exe (parâmetro copia), e o update.exe chama de volta o principal.exe
O por que essa mão toda? Porque o cliente não tem que clicar em NADA! Quanto menos o usuário (em específico) clicar ou mecher nisso, melhor! O sistema se atualiza bonitinho e o cliente fica feliz!! :wink:
Como eu fiz tá funcionando, mas mesmo assim vou dar uma lida na tua idéia, quem sabe mais pra frente... 8)
Novamente, valeu a todos pelas dicas!!
GOSTEI 0
Adriano Santos
09/04/2007
[b:753a37dc50]Adriano Santos[/b:753a37dc50], valeu aí cara!
Muito interessante teu sistema. Em casa, com mais calma, vou dar uma olhada melhor!
Eu precisei montar o meu da seguinte forma: durante o uso do sistema, ele chama o update.exe (via WinExec) com parâmetro ´download´, p/ somente baixar (da internet) e guardar numa pasta os arquivos atualizados
Na próxima execução, antes do login, o sistema se fecha, chama o update.exe (parâmetro copia), e o update.exe chama de volta o principal.exe
O por que essa mão toda? Porque o cliente não tem que clicar em NADA! Quanto menos o usuário (em específico) clicar ou mecher nisso, melhor! O sistema se atualiza bonitinho e o cliente fica feliz!! :wink:
Como eu fiz tá funcionando, mas mesmo assim vou dar uma lida na tua idéia, quem sabe mais pra frente... 8)
Novamente, valeu a todos pelas dicas!!
Concordo com vc. Quanto menos o burro do usuário precisar mexer melhor...rsrs...Esta ainda é a 1ª versão do Atualizador, mas no futuro quero que ele possa atualizar via Internet (hoje já faz) e tb via rede. Tb quero fazer algo que o usuário não precise fazer nada, mas cai no problema de atualizar um executável com ele aberto, por isso criei um novo sistema. ;)
GOSTEI 0
Raserafim
09/04/2007
djjunior,
tentei usar a sua sugestão mas tive problemas com a linha
Info: TShellExecuteInfo; (identificador não declarado)
qual unit tenho que declarar?
e que parâmetros são este?
você pode dar um exemplo de como utulizar a função?
tentei usar a sua sugestão mas tive problemas com a linha
Info: TShellExecuteInfo; (identificador não declarado)
qual unit tenho que declarar?
e que parâmetros são este?
você pode dar um exemplo de como utulizar a função?
GOSTEI 0
Adriano Santos
09/04/2007
ShellApi? Veja se é isso.
GOSTEI 0