Delphi: Exemplo utilizando CreateProcess

Publicado por Marcos Dell Antonio em 29/11/2006 | Delphi

Já comentei há alguns dias que existem três formas para rodar uma aplicação externa em um programa escrito em Delphi. São elas: ShellExecute, WinExec e CreateProcess.

Ontem precisei executar o MySQL Dump para gerar um backup de uma base de dados. Até aqui nenhum segredo, pois o WinExec faz isso facilmente. No entanto, eu precisava manter a aplicação esperando até que o comando terminasse de executar.

A única forma de fazer isto é utilizando o CreateProcess. Veja a rotina que utilizei:

Exemplo utilizando o CreateProcess
Download do código fonte

Para realizar o dump, usei o seguinte comando:

cmd.exe /c “c:\executavel\Utils\mysqldump.exe -hHOST -uUSUARIO -pSENHA -c –add-drop-table teste > C:\teste.sql”

Algumas informações importantes sobre esta rotina:

  • O CreateProcess requer vários parâmetros. No entanto, veja que a rotina acima pede um só, portanto ela assume um comportamento padrão;
  • Enquanto a aplicação externa está em execução, o programa que criou ela fica esperando (graças ao WaitForSingleObject);
  • Como utilizei o cmd.exe para rodar o MySQL Dump, precisei passar o nome do executável e seus parâmetros dentro de ” ” (até descobrir isso passaram-se algumas horas);
  • A aplicação criada é executada em modo SW_HIDE, ou seja, escondida.

Fonte: Dicas de Delphi

Não deixe de conferir as sugestões de livros sobre Delphi que eu elaborei. Lá você encontrará informações sobre este e outros comandos.

É isso aí! T+ :P

27 comentários

  1. 1
    HPJ // March 23rd, 2007 at 10:03 am

    Olá estou usando o delphi 8 e o compilador não reconhece a função fillchar.
    Vc pode me ajudar ?

  2. 2
    Marcos // March 23rd, 2007 at 1:30 pm

    Opa.

    Você deu um uses na unit System?

    T+

  3. 4
    daniel // July 25th, 2007 at 11:25 am

    Funciona no .net?

  4. 5
    Marcos Dell Antonio // July 25th, 2007 at 6:31 pm

    Talvez com P/Invoke ou algo do gênero ;)

    T+

  5. 6
    marcelo // September 20th, 2007 at 4:48 pm

    Olá…
    será que alguém pode me ajudar?
    Tenho uma aplicação que chama outro executável, já utilizei o CreateProcess, o WinExec e o ShellExecute, todos deram certo para chamar o outro executável, no entanto eu gostaria é que se o executável estiver aberto ele restaurar e não abrir um novo.
    Utilizei também o seguinte código:
    ——————————-
    TesteExecutável := FindWindow(nil,’Caption do formulário principal’);
    if TesteExecutável 0 then
    SetForegroundWindow(TesteExecutável)
    else
    ShellExecute(Handle,’Open’,'Executável’,nil,’diretório’,sw_shownormal);
    ——————————-

    Este código dá certo, acontece que se o executável estiver no form principal funciona tudo certinho, mas se o executável tiver aberto qualquer outra tela(ShowModal) o programa abre a tela principal deixando esta outra tela(ShowModal) atráz fazendo com que o executável trave uma vez que o formulário ativo ficou por tráz do form principal.

    Se alguém tiver uma solução para isso ficaria muito grato.

    Desde já agradeço.

  6. 7
    Eric // October 18th, 2007 at 11:17 am

    Caro Marcos,

    Cara essa rotina CreateProcess resolveu minha vida :D eu usava o winexec com um sleep depois para aguardar mais isso era uma m%$%#$%. Obrigado

  7. 8
    Gilberto // November 22nd, 2007 at 10:06 pm

    Marcos,

    Funcionou perfeitamente, utilizei com o mesmo propósito que o seu, só que no meu caso utilizei para o PostgreSQL.

    Parabéns, excelente dica.

    Gilberto

  8. 9
    Humberto // December 18th, 2007 at 1:35 pm

    Pessoal,

    essa função (CreateProcess), poderia ser usado em um windows service?

    Preciso abrir uma aplicação, mas ela fica escondida, não abre uma janela.

    Alguma sugestão???

  9. 10
    Lucas // January 4th, 2008 at 10:03 am

    Ola,
    estou trabalhando com o a mesma função porem quando o WaitForSingleObject estra em ação ele para o sistema todo, eu precisaria que pelo menos um form dele continua-se em execução normal.
    Existe alguma outra função que não parace o sistema todo … ou q faça algo parecido ?

    Obrigado pela atenção
    Adios

  10. 11
    Deophanes // January 11th, 2008 at 2:09 pm

    Enquanto a aplicação externa está em execução, o programa que criou ela fica esperando (graças ao WaitForSingleObject). Tem como deixar as duas funcionando sumultaneamente, pois tirei esse comando e não deu certo.

  11. 12
    André // September 27th, 2008 at 5:34 pm

    Me perdoem por comentar um post de 2006, mas só hoje me deparei com a necessidade de usar esta rotina. Funciona perfeitamente meu unico problema é que ela estará dentro de um software que distribuirei entre os funcionarios de uma grande empresa e me pergunto sobre a questao de segurança.

    Rodando um analisador de processos do windows, vejo la claramente a senha passada pelo controle.

    caso queiram ver com os proprios olhos o link do sistema que estou usando para monitorar estes processos é:
    http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx

    minha duvida… nao existe a possibilidade de criar o processo… aguardar que ele me solicite outras informações ou até mesmo automatizar isso…

    Podendo-se “ler” a saida do console, como por exemplo.. executarmos lá o comando

    “cmd.exe /c date”

    o console ira aguardar com a seguinte entrada:
    “Data atual: sáb 27/09/2008
    Digite a nova data: (dd-mm-aa)”

    como eu consigo informar estes dados sem a intervenção do usuario ?

    a idéia é fornecer os dados de segurança como login e senha depois de executado, e não na linha de comando.

    teoricamente, ficaria mais dificil de ser visto essas informaços se passados como um input no console e não diretamente via parametros.

    caso alguem consiga resolver isto me dê uma luz. estou procurando esta resposta a dias sem nenhum sucesso ate o presente momento.

    deixo aqui meu email para caso uma boa alma apareça…

    campsoft@gmail.com

    Grato. !

  12. 13
    alex // October 6th, 2008 at 9:34 pm

    e como chamar o visualizador de imagens do windows ??

  13. 14
    alex // October 7th, 2008 at 1:49 pm

    como executo o visualisador de imagens do windows atraves do delphi ?

  14. 15
    Ricardo // December 3rd, 2008 at 5:06 pm

    Estou querendo chamar um programa externo dentro de um serviço que criei no delphi.. usando timer,, o serviço fica verificando se o programa externo está aberto, se não estiver ele abre.. e funciona… mas o form não abre… é necessário fazer alguma coisa?

    Obrigado

  15. 16
    Lucas Ferreira // December 19th, 2008 at 2:45 pm

    Amigo Marcos, tudo bom?
    Tentei realizar esta função, porém não obtive resultado. A função é de 2006 e talvez a IDE de hoje não aceite mais isto. Digo porque estou tentado no Delphi 2009, MySQL 5.0, Windows XP SP2
    Quando executo a função com o mesmo comando seu, alterando somente para minhas atribuições, tais como localhost, username, password, banco de dados, etc.
    Me resulta este erro: “Acess violation at address 7C82F293 in module ‘kernel32.dll’. Write of address 0053F4E6″.
    Poderia me ajudar, como proceder? Nescessito justamente desta função.
    Grato.

  16. 17
    Daniel Gonçalves // February 17th, 2009 at 7:20 pm

    Estou com o mesmo problema do Lucas Ferreira, meu Delphi tambem é 2.009.
    Se alguem tiver uma luz eu agradeço.
    Daniel.

  17. 18
    Luis Fernando ferrari // April 30th, 2009 at 2:43 pm

    Marcos montei esta rotina exatamente igual e ele vai para o prompt mas nao executa o comando veja se eu estou fazendo alguma coisa errada
    primeiro eu carrego toda a linha de comando para uma variavel chamada vadditional é esta abaixo ela é grande mesmo por causa dos parametros
    vadditional_data := ‘cmd.exe /c C:\Maxtrack\MaxtrackServer\Decode_Additional_Data.exe –d –mtc ‘ + serial + ‘ –if C:\Maxtrack\MaxtrackServer\XMLData\’ + arq_xml.text +
    ‘ -of C:\Maxtrack\MaxtrackServer\XMLDecode\’ + serial + copy(arq_xml.text,9,10) ;

    depois chamo a funcao

    Cria_Processo(vadditional_data);

    Aqui esta a função como vc demonstra o que ele faz é somente ir ao prompt mas nao executa e nem traz a linha de comando,,se puder me ajudar

    Funcao :::

    Function TForm1.Cria_Processo(cmd : string) : boolean ;
    var
    SUInfo : TStartupInfo;
    ProcInfo : TProcessInformation;
    Begin
    FillChar(SUInfo, SizeOf(SUInfo), #0) ;
    SUInfo.cb := Sizeof(SUInfo);
    SUInfo.dwFlags := STARTF_USESHOWWINDOW;
    SUInfo.wShowWindow := SW_HIDE ;
    result := createprocess(nil,
    pchar(cmd),
    nil,
    nil,
    false,
    REALTIME_PRIORITY_CLASS,
    nil,
    nil,
    SUInfo,
    ProcInfo) ;

    if (result) then
    Begin
    WaitForSingleObject(ProcInfo.hProcess, INFINITE);
    CloseHandle(ProcInfo.hProcess);
    CloseHandle(ProcInfo.hThread);
    end
    End;

  18. 19
    André // June 5th, 2009 at 9:21 am

    Olá.
    Não sei se ajuda vocês.
    Testei a função e sobre o “travamento” do sistema, resolvi, substituindo a linha :
    WaitForSingleObject(ProcInfo.hProcess, INFINITE);
    por :
    sleep(2000);
    onde o “2000″ é o tempo que escolhi para a minha necessidade.

  19. 20
    Thiago Gaspar // November 4th, 2009 at 3:57 pm

    Parabenizo o autor por manter este post até a presente data, pois mesmo ao longo dos 3 anos de existência, este me ajudou muito e é justamente o que buscava a um bom tempo.

    Muito grato pela dica.

    Abs a todos

  20. 21
    Marcos Moreno // November 5th, 2009 at 9:49 pm

    Ola Marcos Dell’ Antonio.
    Muito bom esse seu post foi a solucao que achei para executar o mysql de um pendrive funcionou certinho com o delphi 2007 mas no delphi 2009 ele consegue instalar como um servico do windows mas quanto eu tento iniciar o mysql ele trava, vc tem alguma ideia de como eu resolvo este problema, ja tentei de varia maneira mas parece q o delphi 2009 tem muitas coisa diferentes das versoes anteriores

    CreateProcessSimple(’cmd.exe /c “”‘ + ExtractFilePath(Application.ExeName) + ‘mysql\bin\mysqld.exe” –install mysql_new –defaults-file=”‘ + ExtractFilePath(Application.ExeName) + ‘mysql\my.ini”"‘);

    Acima esta o fonte de instalacao do mysql no serviço do windos

    CreateProcessSimple(’cmd.exe /c “”net start mysql_new”"‘);

    e acima é onde esta dando o problema

    Grato Marcos Moreno

  21. 22
    Sergio // January 27th, 2010 at 12:56 am

    Boa Noite, estou tentando usar o createprocess com o delphi2009 mas estou tendo um access violation no Kernel32 (como o lucas Ferreira e o Daniel, alguém tem uma dica ? Thanks

  22. 23
    Roberto Novakosky // April 23rd, 2010 at 12:20 pm

    André, para fornecer a senha e login para o processo, sugiro você passá-los como argumentos criptrografados.
    Também é possível vc identificar a window que vc abriu pelo processo e setar manualmente lá a senha e login do usuário, ou fazer o inverso também, fazer a window que vc abriu acessar variáveis do teu aplicativo que abriu o processo, mas já é assunto para um outro escopo.

  23. 24
    Fernando // May 18th, 2010 at 2:29 pm

    Obrigado!
    D+

  24. 25
    Valdeci Lunguinho // May 21st, 2010 at 3:42 pm

    Olá, Marcos/Todos

    Parabén pelo post…
    Tenho um serviço criado que roda perfeitamente em XP, tanto com WinExec, ShellXecute ou CreateProcess, ocorre que no VISTA/Delphi 7, o aplicativo que é chamado não executa. Já debuguei o serviço chega até alinha onde é executado o ShellExecute ou WinExec, mas não acontece nada. Alguém pode me ajudar ?

  25. 26
    Taylor Lopes // June 12th, 2010 at 12:11 am

    Boa noite, passei aqui para agradecer o Post… me ajudou bastante! Falouuu…

  26. 27
    Gustavo // June 17th, 2010 at 9:14 am

    Olá Marcos, vi seu post e achei muito interessante. Utilizo algo parecido, mas quando passo o comando

    C:\****\***\ não é reconhecido como um comando interno
    ou externo, um programa operável ou um arquivo em lotes.
    Desde já agradeço

Trackbacks

  1. Marcos Dell Antonio » Delphi: WinExec, ShellExecute ou CreateProcess?

Deixe o seu comentário

Anúncios

Anúncio provido pelo BuscaPé