2013-05-22 3 views
0

Я собираю массив данных в исполняемую программу, но мне нужно ее блокировать после каждого вызова в цикле foreach. Он покинет цикл, прежде чем он даже откроет программу с первого вызова.Труба Powershell в exe и ждать

Set-Alias program "whatever.exe" 

foreach ($data in $all_data) 
    { 
     $data| %{ program /command:update /path:"$_" /closeonend:2 } 
    } 
+0

Это не относится к вашей проблеме, но у вас есть ненужный цикл foreach в коде. Вы можете упростить цикл для одного из них: 'Еогеасп ($ данные в $ all_data) { программа/команда: данные $/closeonend:: обновление/путь 2} }' или '$ all_data | % {program/command: update/path: "$ _"/closeonend: 2} ' –

+0

Итак,« вам нужно подождать, пока внешний вызов не завершится до следующей итерации »? – Neolisk

ответ

0

В зависимости от сценария, wait-job может быть излишним. Если у вас есть программный способ узнать, что whatever.exe сделал свое дело, вы можете попробовать что-то вроде

do {start-sleep -sec 2} until ($done -eq $true)

Oh and.

2

Мне нравится PowerShell, но я никогда не учился Invoke-Command. Поэтому всякий раз, когда мне нужно запускать EXE, я всегда использую cmd. Если вы наберете cmd /?, вы получите его помощь, посмотрите на переключатель «c». Я хотел бы сделать что-то вроде этого:

foreach ($data in $all_data){ 
    $data | 
    Foreach-Object{ 
     cmd /c "whatever.exe" /command:update /path:"$_" /closeonend:2 
    } 
} 

Если вы не любите cmd /c вещи, которую вы могли бы использовать Джобс.

foreach ($data in $all_data){ 
    $data | 
    Foreach-Object{ 
     $job = Start-Job -InitializationScript {Set-Alias program "whatever.exe"} -ScriptBlock {program /command:update /path:"$($args[0])" /closeonend:2} -ArgumentList $_ 
     while($job.Status -eq 'Running'){ 
      Start-Sleep -Seconds 3 
      #Could make it more robust and add some error checking. 
     } 
    } 
} 
2

Я могу думать о двух способов решения этой:

  1. трубу исполняемый вызов в Out-Null
  2. раскошеливаться вызов cmd.exe/с (как показано на @ BobLobLaw годов ответ)

Я сделал ваш образец кода более конкретным, чтобы я мог запускать и тестировать свои решения; надеюсь, это будет переводиться. Вот что я начал с того, чтобы быть эквивалентным вашему образцу кода, т. Е. Скрипт выполняется без ожидания завершения исполняемого файла.

# I picked a specific program 
Set-Alias program "notepad.exe" 

# And put some values in $all_data, specifically the paths to three text files. 
$all_data = Get-Item B:\matt\Documents\*.txt 

# This opens each file in notepad; three instances of notepad are running 
# when the script finishes executing. 
$all_data | %{ program "$_" } 

Вот тот же код, что и выше, но трубопровод к Out-Null заставляет скрипт ждать на каждой итерации цикла.

# I picked a specific program 
Set-Alias program "notepad.exe" 

# And put some values in $all_data, specifically the paths to three text files. 
$all_data = Get-Item B:\matt\Documents\*.txt 

# Piping the executable call to out-null forces the script execution to wait 
# for the program to complete. So in this example, the first document opens 
# in notepad, but the second won't open until the first one is closed, and so on. 
$all_data | %{ program "$_" | Out-Null} 

И, наконец, тот же код (более или менее) с использованием cmd /c для вызова исполняемого файла и сделать ожидание сценария.

# Still using notepad, but I couldn't work out the correct call for 
# cmd.exe using Set-Alias. We can do something similar by putting 
# the program name in a plain old variable, though. 
#Set-Alias program "notepad.exe" 
$program = "notepad.exe" 

# Put some values in $all_data, specifically the paths to three text files. 
$all_data = Get-Item B:\matt\Documents\*.txt 

# This forces script execution to wait until the call to $program 
# completes. Again, the first document opens in notepad, but the second 
# won't open until the first one is closed, and so on. 
$all_data | %{ cmd /c $program "$_" } 
Смежные вопросы