Làm cách nào để báo cho PowerShell đợi mỗi lệnh kết thúc trước khi bắt đầu tiếp theo?


211

Tôi có một tập lệnh PowerShell 1.0 để chỉ mở một loạt các ứng dụng. Đầu tiên là một máy ảo và những cái khác là các ứng dụng phát triển. Tôi muốn máy ảo hoàn thành việc khởi động trước khi các ứng dụng còn lại được mở.

Trong bash tôi chỉ có thể nói "cmd1 && cmd2"

Đây là những gì tôi đã có ...

C:\Applications\VirtualBox\vboxmanage startvm superdooper
    &"C:\Applications\NetBeans 6.5\bin\netbeans.exe"

Câu trả lời:


366

Thông thường, đối với các lệnh nội bộ, PowerShell sẽ đợi trước khi bắt đầu lệnh tiếp theo. Một ngoại lệ cho quy tắc này là EXE dựa trên hệ thống con bên ngoài. Bí quyết đầu tiên là đường ống để Out-Nullthích như vậy:

Notepad.exe | Out-Null

PowerShell sẽ đợi cho đến khi quá trình Notepad.exe được thoát trước khi tiếp tục. Đó là tiện lợi nhưng loại tinh tế để nhận từ việc đọc mã. Bạn cũng có thể sử dụng Start-Process với tham số -Wait:

Start-Process <path to exe> -NoNewWindow -Wait

Nếu bạn đang sử dụng phiên bản Tiện ích mở rộng cộng đồng PowerShell thì đó là:

$proc = Start-Process <path to exe> -NoNewWindow -PassThru
$proc.WaitForExit()

Một tùy chọn khác trong PowerShell 2.0 là sử dụng công việc nền:

$job = Start-Job { invoke command here }
Wait-Job $job
Receive-Job $job

2
Lỗi của tôi. Start-Process -Wait hoạt động rất tốt, nhưng bây giờ tôi thấy nó không phải là thứ tôi đang tìm kiếm ... Tôi thực sự đang tìm cách đợi cho đến khi vm hoàn thành việc khởi động. Tôi tưởng tượng đó sẽ là khó khăn. Tôi cho rằng tôi sẽ phải tìm một chủ đề mới cho điều đó. Cám ơn, nhưng mà.
John Mee

7
Rực rỡ, | out-nullđã làm những gì tôi cần. Đã thử sử dụng Start-Jobnhưng vì tôi chuyển kết quả của các hàm làm tham số, nên tôi có một chút skitzoid, vì vậy tôi không thể sử dụng đề xuất cuối cùng ...
jcolebrand

6
Là một lưu ý phụ, nếu bạn cần truyền nhiều đối số -ArgumentList, hãy phân tách chúng bằng dấu phẩy như thế nào -ArgumentList /D=test,/S.
sschuberth

1
Cảm ơn bạn vì giải pháp "<path to exe> | Out-Null" đơn giản! Vấn đề với phương thức "Start-Process <path to exe> -NoNewWindow -Wait" là PowerShell tạm dừng cho đến khi tất cả các tiến trình con được sinh ra bởi cha mẹ đã hoàn tất, ngay cả khi cha mẹ chấm dứt trước chúng. Điều này gây ra vấn đề chương trình thiết lập của chúng tôi.
zax

Đây là những gì tôi sử dụng để chờ VM khởi động Start-AzureRmVM -ResourcegroupName $ ResourcegroupName -Name $ VmName trong khi ((Get-AzureRmVM -ResourcegroupName $ ResourcegroupName -Name $ VmName -Status | `select -ExpandProperty _.Code -match "PowerState"} | `select -ExpandProperty DisplayStatus) -ne" VM running ") {Start-Sleep -s 2} Start-Sleep -s 5 ## Hãy cho thời gian VM xuất hiện để nó có thể chấp nhận yêu cầu từ xa
andrewmo

47

Bên cạnh việc sử dụng Start-Process -Wait, đường ống đầu ra của một tệp thực thi sẽ khiến Powershell chờ đợi. Tùy thuộc vào nhu cầu, tôi sẽ thường ống để Out-Null, Out-Default, Out-Stringhoặc Out-String -Stream. Dưới đây là một danh sách dài của một số tùy chọn đầu ra khác.

# Saving output as a string to a variable.
$output = ping.exe example.com | Out-String

# Filtering the output.
ping stackoverflow.com | where { $_ -match '^reply' }

# Using Start-Process affords the most control.
Start-Process -Wait SomeExecutable.com

Tôi nhớ các toán tử kiểu CMD / Bash mà bạn đã tham chiếu (&, &&, ||). Có vẻ như chúng ta phải dài dòng hơn với Powershell .


Đây là một giải pháp cực kỳ tốt nếu bạn cần phân tích đầu ra!
Jan Rothkegel

Việc chỉ ra danh sách các bộ chuyển hướng Out-xxxx nhanh chóng cho phép tôi hiểu lý do tại sao tôi nên sử dụng Out-Default thay vì Out-Null , vì tôi cần giữ đầu ra của giao diện điều khiển.
Julio Nobre

Lưu ý rằng không cần thêm công việc để thực thi đồng bộ các ứng dụng bảng điều khiển - như trong bất kỳ trình bao nào, đó là hành vi mặc định. Đường ống để Out-String thay đổi đầu ra thành một chuỗi nhiều dòng , trong khi PowerShell theo mặc định trả về một mảng các dòng . Start-Processnên tránh cho các ứng dụng bảng điều khiển (trừ khi bạn thực sự muốn chạy chúng trong một cửa sổ mới ) vì bạn sẽ không thể chụp hoặc chuyển hướng đầu ra của chúng.
mkuity0

Trên thực tế, việc một lệnh gốc chạy đồng bộ (có đầu ra) hay không đồng bộ phụ thuộc vào thực thi. Ví dụ, không bắt được đầu ra, sau đây chỉ xuất ra "bingo". & 'C: \ Tệp chương trình \ Mozilla Firefox \ firefox.exe' -? ; 'lô tô'
Nathan Hartley

12

Chỉ cần sử dụng "Wait-process":

"notepad","calc","wmplayer" | ForEach-Object {Start-Process $_} | Wait-Process ;dir

việc đã hoàn thành


8

Nếu bạn dùng Start-Process <path to exe> -NoNewWindow -Wait

Bạn cũng có thể sử dụng -PassThrutùy chọn để lặp lại đầu ra.


Lưu ý rằng -PassThrukhông phải đầu ra echo (một ứng dụng không phải là bàn điều khiển theo định nghĩa sẽ không tạo ra đầu ra của bàn điều khiển), nó xuất ra một System.Diagnostics.Processthể hiện đại diện cho quá trình mới được khởi chạy, vì vậy bạn có thể kiểm tra các thuộc tính của nó và đợi cho nó thoát ra sau.
mkuity0

6

Một số chương trình không thể xử lý luồng đầu ra rất tốt, sử dụng đường ống để Out-Nullcó thể không chặn nó.
Start-Processcần -ArgumentListchuyển đổi để vượt qua đối số, không thuận tiện.
Ngoài ra còn có một cách tiếp cận khác.

$exitCode = [Diagnostics.Process]::Start(<process>,<arguments>).WaitForExit(<timeout>)

1
Làm thế nào để nhiều đối số hoạt động trong cuộc gọi đó? Làm thế nào họ được phân định? Làm thế nào để xử lý một chuỗi thoát lồng nhau? ty!
AnneTheAgile

1
@AnneTheAgile doc sử dụng không gian để phân tách các đối số, để thoát char sử dụng dấu gạch chéo ngược
ifree 14/1/2015

ty @ifree, tôi đã nhận được testcomplete để chạy theo cách đó! Tôi đã sử dụng các trích dẫn đơn xung quanh danh sách các đối số được phân tách bằng dấu cách. [1]; nhưng bây giờ echo $ exitcode = false, đó không phải là mã trả về của tôi trong quá trình? [1] $ exitCode = [Chẩn đoán.Process] :: Start ("c: \ Program Files (x86) \ SmartBear \ TestComplete 10 \ Bin \ TestComplete.exe", '"c: \ Users \ ME \ Documents \ TestComplete 10 Dự án \ hig4TestProject1 \ hig4TestProject1.pjs "/ run / project: myProj / test:" KeywordTests | zTdd1_ood "/ exit ') .WaitForExit (60)
AnneTheAgile

3

Bao gồm tùy chọn -NoNewWindowcho tôi một lỗi:Start-Process : This command cannot be executed due to the error: Access is denied.

Cách duy nhất tôi có thể khiến nó hoạt động là gọi:

Start-Process <path to exe> -Wait

0

Đưa nó đi xa hơn, bạn thậm chí có thể phân tích cú pháp khi đang bay

ví dụ

& "my.exe" | %{
    if ($_ -match 'OK')
    { Write-Host $_ -f Green }
    else if ($_ -match 'FAIL|ERROR')
    { Write-Host $_ -f Red }
    else 
    { Write-Host $_ }
}

0

Luôn có cmd. Nó có thể ít gây phiền nhiễu hơn nếu bạn gặp khó khăn khi trích dẫn các đối số để bắt đầu quá trình:

cmd /c start /wait notepad
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.