2009-12-16 19 views
7

Tôi tự hỏi liệu có ai biết cách thực hiện chương trình theo điều kiện tùy thuộc vào thành công/lỗi thoát của chương trình trước đó hay không. Có cách nào để tôi thực hiện một chương trình 2 ngay lập tức sau khi program1 nếu program1 thoát thành công mà không thử nghiệm biến LASTEXITCODE? Tôi đã thử các toán tử-và-và vô ích, mặc dù tôi đã có cảm giác rằng họ sẽ không làm việc anyway, và thay thế tốt nhất là một sự kết hợp của một dấu chấm phẩy và một tuyên bố nếu. Ý tôi là, khi nói đến việc xây dựng một gói phần nào tự động từ nguồn trên Linux, các nhà điều hành & & không thể bị đánh đập:Thực thi quy trình có điều kiện trong Windows PowerShell (ví dụ: toán tử && và || trong Bash)

# Configure a package, compile it and install it 
./configure && make && sudo make install 

PowerShell sẽ yêu cầu tôi làm như sau, giả sử tôi thực sự có thể sử dụng cùng một xây dựng hệ thống trong PowerShell:

# Configure a package, compile it and install it 
.\configure ; if ($LASTEXITCODE -eq 0) { make ; if ($LASTEXITCODE -eq 0) { sudo make install } } 

chắc chắn, tôi có thể sử dụng nhiều dòng, lưu nó trong một tập tin và thực thi kịch bản, nhưng ý tưởng là cho nó được súc tích (tiết kiệm tổ hợp phím). Có lẽ nó chỉ là một sự khác biệt giữa PowerShell và Bash (và thậm chí cả dấu nhắc lệnh Windows được tích hợp sẵn hỗ trợ toán tử & &). Tôi sẽ cần điều chỉnh, nhưng nếu có cách dọn dẹp, tôi rất muốn biết .

+0

Bất kỳ ai quan tâm đến kiểu Bash & '' 'và' || 'trở thành một phần của PowerShell: vui lòng bỏ phiếu cho tính năng [ở đây] (https://windowsserver.uservoice.com/forums/301869-powershell/suggestions/11087898-implement-the-and-operator-that-bash-has). – mklement0

Trả lời

2

Bạn có thể tạo một hàm để thực hiện việc này, nhưng không có cách trực tiếp để làm điều đó mà tôi biết.

function run-conditionally($commands) { 
    $ranAll = $false 
    foreach($command in $commands) { 
     invoke-command $command 
     if ($LASTEXITCODE -ne 0) { 
      $ranAll = $false 
      break; 
     } 
     $ranAll = $true 
    } 

    Write-Host "Finished: $ranAll" 

    return $ranAll 
} 

Sau đó gọi nó là tương tự như

run-conditionally(@(".\configure","make","sudo make install")) 

Có lẽ một vài lỗi có này không được lưu cuff mà không có một môi trường PowerShell tiện dụng.

+0

Tôi sẽ tinh chỉnh nó để làm việc (Invoke-Expression là cần thiết vì Invoke-Command dường như không hoạt động theo cách nó phải ... hoặc một cái gì đó), nhưng đó chắc chắn là một cái gì đó hữu ích. Cảm ơn đã giúp đỡ. Nó được đánh giá cao. – Dustin

+3

Vấn đề với việc sử dụng '$ LASTEXITCODE' là nó chỉ được thiết lập khi PowerShell thực hiện một giao diện điều khiển EXE. Bạn có thể sử dụng '$?' Tốt hơn. –

+0

Sau đó, bạn có thể đặt tên cho hàm đó để dễ gọi hơn. – GrayWizardx

0

Tôi đã thực sự làm tổn thương cho sự thiếu & &, quá, vì vậy đã viết kịch bản sau đây đơn giản dựa trên câu trả lời GrayWizardX (mà không làm việc như nó vốn có):

foreach($command in $args) 
{ 
    $error.clear() 
    invoke-command $command 
    if ($error) { break; } 
} 

Nếu bạn lưu nó như là rc.ps1 (đối với "chạy có điều kiện") trong một thư mục trong đường dẫn của bạn, bạn có thể sử dụng nó như:

rc {.\configure} {make} {make install} 

sử dụng khối kịch bản (các dấu ngoặc nhọn) như các đối số thay vì chuỗi có nghĩa là bạn có thể sử dụng hoàn tab trong khi gõ các lệnh, đó là muc h đẹp hơn. Tập lệnh này gần như tốt bằng & & và hoạt động.

+1

Ngoài ra, thay đổi dòng thứ tư thành 'if ($?) {Break; } 'làm cho kịch bản hoạt động như ||, trong trường hợp đó không rõ ràng. – Abram

+0

Không phải là một ý tưởng hay khi xóa bộ sưu tập '$ Error'; kiểm thử '$?' sẽ làm ('if ($?) {break}' cho '&&', và 'if (-not $?) {break}' cho '||'). Để sử dụng 'Invoke-Command', bạn phải vượt qua một _script block_, vì vậy tốt hơn bạn nên nhập tham số' $ args' theo cách đó: '[scriptblock []] $ args'. Ngoài ra, để ngăn chặn các hiệu ứng phụ, sử dụng 'Invoke-Command -NoNewScope' - hoặc đơn giản là sử dụng toán tử' .'. – mklement0

Các vấn đề liên quan