Wednesday, 23 May 2018

Powershell processstartinfo waitforexit


Como iniciar um processo e esperar para completar? #PowerShell.
Como iniciar um processo e esperar que ele seja concluído? #PowerShell.
Um dos novos Cmdlets apresentados com o PowerShell v2 é chamado Start-Process. Ele inicia um processo no computador local e, opcionalmente, aguarda a conclusão se você usar o parâmetro de Comutação Wait do Cmdlet. Start-Process é implementado usando o método Start da classe System. Diagnostics. Process do NET Framework.
A primeira versão do Windows PowerShell não veio com um cmdlet como Start-Process. A função abaixo, também chamada de Start-Process, aguarda a conclusão do processo por padrão. Além disso, a função aguardará que todos os processos filho do processo sejam concluídos se você usar o parâmetro de opção WaitForChildProcesses. Além disso, a função não esperará infinitamente, pois suporta um parâmetro Timeout. Por padrão, ele aguardará 600 segundos para que um processo (e processos filho) seja concluído. Como o Start-Process de Posh v2, a função usa a classe System. Diagnostics. Process NET Framework.
Então, por que esperar por processos filhos? Se é importante aguardar a conclusão do processo, talvez esperar que seus processos filhos também concluam os problemas. Por exemplo, o instalador do Oracle chama o Java e termina enquanto o Java Runtime ainda está ocupado instalando o software.
Além disso, considero um tempo limite como obrigatório para evitar uma espera infinita devido a um processo de suspensão (ou processo filho).
BTW, é claro que você pode usar a função no PowerShell v2 também. Lembre-se de que a função tem duas vantagens: aguardar processos filhos e tempo limite!

Powershell processstartinfo waitforexit
se eu iniciar outro aplicativo CF usando o seguinte código no NetCF2.0, o aplicativo nunca sai, ele simplesmente parece travar?
Dim p como novo processo.
Dim info As New ProcessStartInfo (& quot; Sync. exe & quot ;, & quot; 1 & quot;)
Se eu executar o aplicativo manualmente ou percorrê-lo, ele sai conforme o esperado. É quase como se o WaitForExit estivesse vivo ou algo assim?
Se você tiver uma repro fi nição confiável que não esteja usando componentes de terceiros, preencha um relatório de bug aqui.
Todas as respostas.
Não, WaitForExit () apenas espera por aplicativo para saídas, ele não o mantém ativo. Deve ser algo no Sync. exe que nunca sai se for lançado pelo aplicativo principal. Pode ser que o Sync. exe espere pelo recurso mantido pelo aplicativo principal, cabe a você investigar.
Sim, eu acho que vou ter que fazer mais algumas escavações.
Eu escrevi um programa de exemplo com um formulário com um botão ligado, quando o botão foi clicado, disparou Sync. exe e chamou WaitForExit () e tudo funcionou bem! Confuso!!
Pode ter algo a ver com o fato de que o código que chama o Sync. exe está em um thread separado, talvez? Vou postar de volta quando encontrar a resposta!
Essa fila é usada para o IPC enviar mensagens básicas do Sync. exe para o aplicativo de chamada principal. Essas mensagens são strings básicas, geralmente um caractere "c"; para completo, & quot; e & quot; para o erro "u" para uma atualização de software disponível etc.
Eu criar a fila apenas antes de chamar o aplicativo Sync. exe e algo nele parece manter o Sync. exe vivo, quando eu fechar o aplicativo principal Sync. exe fecha também.
Essa implementação funciona bem em um dispositivo CE 4.2, mas não no dispositivo WM5 que tenho aqui.
Alguma idéia de como eu poderia modificar o código para WM5, ou devo considerar o uso de MSMQ ou algo parecido?
Ok, apenas no caso de alguém estar lendo isso ... a história até agora.
Alterei o código da fila de mensagens para usar o OpenNetCF. WindowsCE. Messaging. P2PMessageQueue e ainda tenho o mesmo problema. O problema ocorre quando o aplicativo de chamada abre uma Fila nomeada, inicia o segundo aplicativo como um processo e chama WaitForExit. O segundo aplicativo abre a mesma fila nomeada e envia mensagens que são recebidas pelo aplicativo de chamada. No entanto, quando o segundo aplicativo termina, ele nunca é realmente fechado, fazendo com que o WaitForExit bloqueie o aplicativo de chamada. Se eu parar o aplicativo de chamada, os dois aplicativos serão fechados.
Isso só ocorre se eu usar a mesma fila nomeada em ambos os aplicativos. É como se eles estivessem ligados através da fila? Isso tudo funcionou bem no PPC2003 e no CE4.2, mas no WM5.0 está causando uma dor de cabeça real! Socorro!!

Gerenciando Processos no PowerShell.
Várias pessoas perguntaram recentemente sobre como gerenciar processos no PowerShell. Esta postagem do blog deve responder a várias dessas perguntas.
Como se poderia esperar do & # 8220; shell & # 8221; Como parte do PowerShell, você não precisa fazer nada especial para iniciar um processo. Em uma linguagem de programação como o VBScript, você precisa fazer algo bastante complexo como:
Defina objWMIService = GetObject (& # 8220; winmgmts: & # 8221; _.
Defina objStartup = objWMIService. Get (& # 8220; Win32_ProcessStartup & # 8221;)
Defina objConfig = objStartup. SpawnInstance_.
Defina objProcess = GetObject (& # 8220; winmgmts: raiz \ cimv2: Win32_Process & # 8221;)
objProcess. Create & # 8220; Notepad. exe & # 8221 ;, Null, objConfig, intProcessID.
mas em shells (PowerShell, cmd. exe, bash, etc.) você pode simplesmente iniciar um programa como o bloco de notas simplesmente digitando & # 8220; notepad & # 8221; como mostrado.
Agora você notará que, quando fizer isso, o shell retornará imediatamente e solicitará o próximo comando. Isso porque o notepad é um processo de GUI do win32 e é executado em segundo plano. Por outro lado, se você iniciar um aplicativo de console como o & # 8220; ping. exe & # 8221 ;, o PowerShell esperará até que esse processo seja concluído.
Mas e se eu quiser esperar pelo processo do Win32? No cmd. exe, você faria isso com & # 8220; start / wait & # 8221; mas esse comando não está (diretamente) disponível no PowerShell. Então, o que fazemos?
O PowerShell executa diretamente executáveis. Se aguarda a saída do processo, o código de saída será deixado em $ LASTEXITCODE. Agora, se um executável do Win32 for o último comando em um pipeline e não for redirecionado, o processo será executado em segundo plano. No entanto, se você enviar sua saída para algo, o PowerShell aguardará a saída do comando.
Portanto, essa é uma espera simples (se não intuitiva) para aguardar a saída de um processo da GUI.
Como alternativa, se o processo já estiver em execução, você poderá usar Get-Process para recuperar as informações necessárias e, em seguida, executar um WaitForExit () nesse objeto.
Aqui está um exemplo um pouco mais sofisticado, onde abrimos um documento em vez de iniciar um processo. Dessa vez, encontraremos o processo pelo título da janela, e não pelo nome do executável.
Infelizmente, procurar um processo sempre significa que você pode encontrar o processo errado. Idealmente, você gostaria de obter o objeto Process diretamente. Portanto, para um gerenciamento de processos mais preciso, você terá que usar a classe System. Diagnostics. Process e iniciar os processos por conta própria. Por exemplo, você pode usar [diagnostics. process] :: Start () para aguardar um processo:
Observe o uso de & # 8220; $ pwd \ foo. txt & # 8221; para especificar o caminho completo para o arquivo. Isso ocorre porque o PowerShell mantém sua própria ideia do diretório atual. (Esta nota se aplica ao uso de qualquer API que acesse o sistema de arquivos - você precisa dar um caminho absoluto.)
Agora, estamos começando a voltar ao nível de complexidade que você encontra em uma linguagem de programação. No entanto, você também tem todo o poder dessas linguagens. Aqui está um script de exemplo & # 8220; background. ps1 & # 8221; Isso permitirá que você execute um scriptblock desanexado em uma janela separada (ou na mesma janela se você especificar o parâmetro – inconsole.
Este script permite que você faça coisas no PowerShell que você não pode fazer a partir do cmd. exe, mas pode fazer a partir do VBScript.
Finalmente, aqui estão mais duas maneiras de trabalhar com processos. Mesmo que o PowerShell não tenha um comando de início, o cmd. exe faz isso, você pode iniciar / esperar fazendo.
E, por último, mas não menos importante, o PowerShell Community Extensions inclui um cmdlet Start-Process. Você pode obter uma lista desses recursos em:
Bruce Payette [MSFT]
Windows PowerShell Tech Lead.
Top Server & # 038; Blogs de ferramentas.
Postagens recentes.
DSC Resource Kit versão de fevereiro de 2018 7 de fevereiro de 2018 Configuração do estado desejado (DSC) Planning Update & # 8211; Janeiro de 2018 26 de janeiro de 2018 PowerShell Core 6.1 Roadmap 24 de janeiro de 2018 PowerShell Core 6.0: disponível em geral (GA) e com suporte! 10 de janeiro de 2018.
Eu tenho um script master powershell chamando um subscrito. O subscrito lança um erro, mas $ LASTEXITCODE em MASTER não parece pegá-lo.
Basicamente meu processo pára no momento em que o comando throw é executado e o processo não é retornado para o MASTER.
Existe uma maneira de contornar isso?
Muito obrigado por este artigo !
Seria muito bom ver uma versão atualizada disso com todas as extensões V2 como Start-Process e as extensões Jobs.
Obrigado por todo o trabalho duro, o PowerShell está se preparando para ser uma ferramenta realmente incrível para automação de processos!
Você pode encontrar mais detalhes aqui: [link] Shay [link]
Uma breve pesquisa no google: & amp; lt; [link] & gt; onde é dada a ponta a saída do pipe para out-null. bloco de anotações.
Na verdade eu estou integrando o VB e um programa escrito em C ++. Eu sou capaz de executar este programa C ++, clicando em um botão projetado em VB. Quando clico no botão, o prgram é executado na plataforma DOS. Eu não quero essa plataforma DOS visível. Mas o processo C ++ deve continuar rodando em segundo plano, invisível.
Se eu passar o scriptblock que contém variável, o código não parece funcionar. Isso ocorre porque o processo filho não herda as variáveis ​​do pai. Como posso superar isso?
Bruce, eu tenho andado por aí com runspaces para obter processamento em background de scriptblocks (em ps1.soapyfrog / 2007/01/22 / running-pipelines-in-the-background /)
Será que provavelmente veremos isso se tornando mais amigável nos próximos lançamentos?
Eu percebo que os runspaces estão realmente disponíveis para aplicativos host, mas eles parecem úteis.
Seu comentário no & quot; site de conexão do PowerShell & quot; é notado.
& # 8220; $ np = bloco de notas do processo get & # 8221; é * extemely * acertar ou errar se você usar muito o bloco de notas. Você poderia classificar os processos por data de início, criados por você, etc., em um esforço para mitigar os erros, mas sim & # 8211; deveríamos ter fornecido uma maneira de obter o processo mais recente criado em um runspace. Em vez de ter uma única variável $ LASTPROCESS, eu estava pensando que uma matriz de $ process ao longo das linhas de $ error seria legal. O processo criado mais recentemente seria mantido em $ process [0].
& gt; como o PowerShell é um shell, o controle de processos / tarefas não deve ser um cidadão de primeira classe.
Isso parece óbvio se não tivesse implementado um cmdlet New-Process / Start-Process, mas foi cortado do projeto em um ponto. Na triagem do que ocorreu na V1, nada além do gerenciamento básico de processos obteve uma classificação relativamente baixa, pois o PowerShell permite que você tenha acesso ao [Diagnostics. Process]. Isso significa que, embora possa ser complexo, você pode fazer praticamente qualquer coisa. Enviar é escolher como Jeffrey diz.
Poste uma solicitação no site de conexão do PowerShell para que outras pessoas possam modificá-lo. Esta é uma fonte de dados importante no processo de tiragem para o que vai para a próxima versão. Se um número suficiente de pessoas pedir, então ele vai para a lista curta do V. Next.
E, respondendo a um comentário anterior:
& gt; Qual é o poder de equivalência dos processos de inicialização em máquinas remotas, ele ainda usa o WMI?
As operações remotas no 1.0 exigem que você use o WMI, APIs remotos ou outros mecanismos de remoting existentes. O PowerShell 1.0 não possui recursos remotos explícitos. Suporte para remoting é um Pri 0 para o próximo lançamento.

Powershell processstartinfo waitforexit
Eu estou tentando iniciar um processo e pegue o StandardOutput e StandardError usando EventHandlers e BeginOutputReadLine. Eu posso iniciar o processo, mas recebo.
Exceção chamando & quot; BeginOutputReadLine & quot; com & quot; 0 & quot; argumento (s): & quot; Não é possível misturar operação síncrona e assíncrona no fluxo do processo. & quot;
Aqui está a minha função de lançamento:
Estou violando o modelo de segmentação Powershell? Obrigado!
Eu estou tentando iniciar um processo e pegue o StandardOutput e StandardError usando EventHandlers e BeginOutputReadLine. Eu posso iniciar o processo, mas recebo.
Exceção chamando & quot; BeginOutputReadLine & quot; com & quot; 0 & quot; argumento (s): & quot; Não é possível misturar operação síncrona e assíncrona no fluxo do processo. & quot;
A mensagem de erro está dizendo o que você está fazendo errado.
Você não pode atribuir funções a um processo síncrono. As funções não são delegadas, portanto, não funcionarão. Você precisa usar um modelo de evento ou usar a variação de asynch.
Use isso como um modelo:
Marcado como Resposta Oliver Lipkau Moderator quarta-feira, 12 de outubro de 2011 2:32.
Todas as respostas.
Eu acredito que você tenha alguns erros no seu código. Eu sou a pessoa mais humilde que você já conheceu.
Eu estou tentando iniciar um processo e pegue o StandardOutput e StandardError usando EventHandlers e BeginOutputReadLine. Eu posso iniciar o processo, mas recebo.
Exceção chamando & quot; BeginOutputReadLine & quot; com & quot; 0 & quot; argumento (s): & quot; Não é possível misturar operação síncrona e assíncrona no fluxo do processo. & quot;
A mensagem de erro está dizendo o que você está fazendo errado.
Você não pode atribuir funções a um processo síncrono. As funções não são delegadas, portanto, não funcionarão. Você precisa usar um modelo de evento ou usar a variação de asynch.
Use isso como um modelo:
Marcado como Resposta Oliver Lipkau Moderator quarta-feira, 12 de outubro de 2011 2:32.
Ok, eu não entendi a implementação do BeginOutputReadline. Eu pensei que isso funcionaria com o. WaitForExit - olhando para ele agora, vejo por que isso não acontece.
Em VB, eu sei como 1) gerar threads para lidar com isso e eu sei que você pode colocar o processo em um loop 2) até que seja concluído como uma maneira de lidar com isso.
Eu não quero fazer # 2. Existe uma maneira multithreaded ou assíncrona para ler a saída de um determinado processo como o processo está gerando?
Ok, eu não entendi a implementação do BeginOutputReadline. Eu pensei que isso funcionaria com o. WaitForExit - olhando para ele agora, vejo por que isso não acontece.
Em VB, eu sei como 1) gerar threads para lidar com isso e eu sei que você pode colocar o processo em um loop 2) até que seja concluído como uma maneira de lidar com isso.
Eu não quero fazer # 2. Existe uma maneira multithreaded ou assíncrona para ler a saída de um determinado processo como o processo está gerando?
Na verdade, a menos que você queira criar um delegado de evento. Mas então este é o PowerShell, não é VB.
Você pode começar aqui e ver se o evento que você está procurando pode ser "viciado"
help Register-ObjectEvent - full.
A resposta marcada não resolve o problema com o qual o OP está lutando - isto é, redirecionando StdErr e StdOut e sofre com o bug de conflito discutido aqui:
& quot; Uma condição de deadlock pode resultar se o processo pai chama p. WaitForExit antes de p. StandardOutput. ReadToEnd e o processo filho grava texto suficiente para preencher o fluxo redirecionado. O processo pai aguardaria indefinidamente que o processo filho fosse encerrado. O processo filho esperaria indefinidamente que o pai lesse o fluxo StandardOutput completo. & Quot;
Eu também estou tentando a melhor resposta para fazer este trabalho no Powershell, mas todos os exemplos de código que estou executando em que usam System. Diagnostics. Process no powersehll estão replicando o deadlock nesta implementação ou não estão redirecionando stderr e stdout.
A solução que estou usando usa o cmdlet Start-Process da seguinte maneira:
Não é uma ótima solução, pois só redirecionará stdout e stderr para um arquivo de texto. mas funcionará o tempo todo e redirecionará stdout e stderr.
Se formos usar saída redirecionada, não usaremos espera. Esse foi o design de CreateProcess desde o NT4.
O uso de arquivos para capturar a saída funcionará porque um fluxo é anexado e envia uma leitura constante para o fluxo de saída. O fluxo de saída nunca é suspenso. Yu não pode fazer isso em um loop de código. O córrego corre o contexto do sistema do pecado eu acredito e começarei sempre a possibilidade de ler. A espera está no seu thread, então você não pode fazer uma leitura manual. É um impasse como afirmado.
O uso da leitura do console é geralmente porque estamos procurando por um prompt. Nesse caso, nunca esperamos a conclusão. O código ZTHe provavelmente será enviado para 'quit' e nós iremos verificar o processo e girá-lo até que ele seja desligado.
A questão aqui é que não podemos gerar um thead. Em VB ou C #, C nós apenas usamos threads separe para IO e um para espera. Melhor ainda, eu usaria um semáforo como ele pode capturar dinamicamente um desligamento inesperado.
Talvez a próxima versão do PowerSHell tenha boas possibilidades de multithreading.
Esta é apenas mais uma lição de que o Powershell é uma linguagem de script, não uma linguagem de programação e, por mais poderosa que seja, existem armadilhas.
O código de exemplo da Microsoft simplesmente não é abrangente o suficiente para um hacker Powerhell perceber que eles não podem chegar lá a partir daqui. Isso é o que me pegou e acredito no OP também, porque houve uma certa expectativa de que BeginOutputReadline implementou a mágica para fazer com que funcionasse threads que teriam resolvido o problema de bloqueio. Não, então acabamos aqui.
E uma ligeira correcção ao meu código - deixei o sinalizador - wait que é necessário para o resto do código funcionar:
Esta é apenas mais uma lição de que o Powershell é uma linguagem de script, não uma linguagem de programação e, por mais poderosa que seja, existem armadilhas.
O código de exemplo da Microsoft simplesmente não é abrangente o suficiente para um hacker Powerhell perceber que eles não podem chegar lá a partir daqui. Isso é o que me pegou e acredito no OP também, porque houve uma certa expectativa de que BeginOutputReadline implementou a mágica para fazer com que funcionasse threads que teriam resolvido o problema de bloqueio. Não, então acabamos aqui.
E uma ligeira correcção ao meu código - deixei o sinalizador - wait que é necessário para o resto do código funcionar:
Certo. O PowerShell é propositadamente limitado para torná-lo mais seguro para a população em geral e para reduzir os problemas que ocorrem com as linguagens compiladas.
Sim - o sinalizador de espera ajudaria, pois o arquivo pode não ter terminado o spool antes de o programa ser encerrado.
O Start-Process é um wrapper fraco na API do processo, mas protege os desavisados ​​dos deadlocks porque você não pode redirecionar a entrada, exceto de um arquivo.
Você não precisa de esperar para redirecionar. Você precisa esperar pelos arquivos e como uma maneira fácil de detectar a terminação. Usando a API, isso tem que ser feito consultando o objeto de processo ou extraindo a saída e aguardando que o processo envie sua mensagem de término e então gire o status.
Isso é tudo demais para os administradores de scripts e, como você apontou, os deixará sem problemas.

Propriedade ProcessStartInfo. UseShellExecute.
A documentação de referência da API tem uma nova casa. Visite o Navegador da API em docs. microsoft para ver a nova experiência.
Obtém ou define um valor indicando se deve usar o shell do sistema operacional para iniciar o processo.
Assembly: System (no System. dll)
Valor da propriedade.
true se o shell deve ser usado ao iniciar o processo; false se o processo deve ser criado diretamente do arquivo executável. O padrão é verdadeiro .
Configurar essa propriedade como false permite redirecionar fluxos de entrada, saída e erro.
UseShellExecute deve ser false se a propriedade UserName não for nula ou uma string vazia, ou uma InvalidOperationException será lançada quando o processo. Start (ProcessStartInfo) método é chamado.
Quando você usa o shell do sistema operacional para iniciar processos, é possível iniciar qualquer documento (que é qualquer tipo de arquivo registrado associado a um executável que tenha uma ação aberta padrão) e executar operações no arquivo, como impressão, usando o objeto Process. . Quando UseShellExecute é false, você pode iniciar apenas executáveis ​​usando o objeto Process.
UseShellExecute deve ser true se você definir a propriedade ErrorDialog como true.
A propriedade WorkingDirectory se comporta de maneira diferente dependendo do valor da propriedade UseShellExecute. Quando UseShellExecute é true, a propriedade WorkingDirectory especifica o local do executável. Se WorkingDirectory for uma string vazia, presume-se que o diretório atual contenha o executável.
Quando UseShellExecute é false, a propriedade WorkingDirectory não é usada para localizar o executável. Em vez disso, ele é usado apenas pelo processo que é iniciado e tem significado apenas dentro do contexto do novo processo. Quando UseShellExecute é false, a propriedade FileName pode ser um caminho completo para o executável ou um nome executável simples que o sistema tentará localizar nas pastas especificadas pela variável de ambiente PATH.

o log de Walter.
. Escrevendo enquanto aprende.
Sexta-feira, 18 de novembro de 2011.
Process. WaitForExit (Int32) trava o problema.
Como você pode ver, o código inicia um processo "cmd. exe" e passa para ele o comando que eu quero executar.
No código eu usei o comando ping - t 8.8.8.8 que, por causa da opção - t, pinga o host sem parar. O que acontece? O processo "cmd. exe" juntamente com o comando ping - t nunca sai e nunca fecha o fluxo stdout e, portanto, o código trava no Output = process. StandardOutput. ReadToEnd (); linha porque não pode ter sucesso lendo todo o fluxo.
O mesmo acontece também se um comando em um arquivo de lote for interrompido por algum motivo e, portanto, o código acima poderia funcionar continuamente por anos e, em seguida, travar repentinamente sem nenhum motivo aparente.
Você pode experimentar um deadlock se o comando que você anexar a "cmd. exe" ou o processo que você está chamando preencher a saída padrão ou o erro padrão. Isso porque nosso código não pode alcançar as linhas.
Na verdade, o processo filho (o comando ping ou um arquivo em lote ou qualquer outro processo que você esteja executando) não pode continuar se nosso programa não ler os buffers preenchidos dos fluxos e isso não pode acontecer porque o código está pendurado na linha com o processo. WaitForExit (), que irá esperar eternamente para o projeto filho sair.
O tamanho padrão de ambos os fluxos é de 4096 bytes. Você pode testar esses dois tamanhos com esses arquivos em lotes:

No comments:

Post a Comment