2010-10-24 15 views
7

Tôi đang sử dụng TFS PowerTools Cmdlets trong PowerShell để tìm cách lấy một số thông tin về changesets và WorkItems liên quan từ máy chủ của tôi. Tôi đã đun sôi vấn đề xuống với hành vi mà tôi không hiểu và tôi hy vọng nó không phải là TFS cụ thể (vì vậy ai đó có thể giải thích vấn đề cho tôi :))PowerShell ForEach/Piping confused

Đây là lệnh duy nhất tôi có thể đến cơ quan:

 
Get-TfsItemHistory C:\myDir -recurse -stopafter 5 | % { Write-Host $_.WorkItems[0]["Title"] } 

nó là những gì tôi mong đợi - Get-TfsItemHistory trả về một danh sách 5 changesets, và nó ống những để một foreach mà in ra Tiêu đề của WorkItem liên quan đến đầu tiên. Vậy vấn đề của tôi là gì? Tôi đang cố gắng viết một kịch bản lớn, và tôi thích viết mã những thứ trông giống như một chương trình C# (cú pháp của powerhell khiến tôi khóc). Bất cứ khi nào tôi cố gắng làm điều trên bằng bất kỳ cách nào khác, bộ sưu tập WorkItems là null.

Các lệnh sau đây (mà tôi giải thích được một cách logic tương đương) không làm việc (Bộ sưu tập WorkItems là null):

 
$items = Get-TfsItemHistory C:\myDir -recurse -stopafter 5 
$items | ForEach-Object { Write-Host $_.WorkItems[0]["Title"] } 

Người Tôi thực sự muốn:

 
$items = Get-TfsItemHistory C:\myDir -recurse -stopafter 5 
foreach ($item in $items) 
{ 
    $item.WorkItems[0]["Title"] 
    # do lots of other stuff 
} 

Tôi đọc một bài viết về sự khác biệt giữa toán tử 'foreach' và Formach-Object Cmdlet, nhưng điều đó có vẻ là một cuộc tranh luận về hiệu năng hơn. Điều này thực sự có vẻ là một vấn đề về thời điểm đường ống đang được sử dụng.

Tôi không chắc tại sao cả ba phương pháp này đều không hoạt động. Bất kỳ cái nhìn sâu sắc được đánh giá cao.

+3

Tôi không chắc vấn đề là gì, nhưng nó chắc chắn cụ thể đối với các Cmdlets TFS (chúng khá khủng khiếp, imo). Có vẻ như lệnh ghép ngắn đang làm việc tải chậm, và khi đường ống kết thúc, bối cảnh dữ liệu đã biến mất và đã quá trễ để tải dữ liệu, nhưng thiết kế của các lệnh ghép ngắn lại phức tạp đến mức tôi không thể theo dõi nó. . – Jaykul

Trả lời

8

Điều này thực sự khó hiểu. Hiện tại, công việc xung quanh là lấy các mặt hàng như vậy:

$items = @(Get-TfsItemHistory . -r -Stopafter 25 | 
      Foreach {$_.WorkItems.Count > $null; $_}) 

Việc này truy cập bộ sưu tập WorkItems dường như khiến tài sản này được điền (Tôi biết - WTF?). Tôi có xu hướng sử dụng @() để tạo một mảng trong trường hợp tôi muốn sử dụng từ khóa foreach. Điều với từ khóa foreach là nó sẽ lặp lại một giá trị vô hướng bao gồm $ null. Vì vậy, nếu truy vấn trả về không có gì, $items được gán $ null và foreach sẽ lặp lại vòng lặp một lần với $item được đặt thành rỗng. Bây giờ PowerShell thường giao dịch với null rất độc đáo. Tuy nhiên, nếu bạn trao giá trị đó cho .NET Framework, nó thường không phải là sự tha thứ. @() sẽ đảm bảo một mảng có các phần tử 0, 1 hoặc N trong đó. Nếu nó là 0 thì vòng lặp foreach sẽ không thực thi cơ thể của nó chút nào.

BTW cách tiếp cận cuối cùng của bạn - foreach ($item in $items) { ... } - chỉ hoạt động tốt.

+0

Cảm ơn, điều đó hoạt động. Tôi trở lại đúng hướng và tôi không điên! Đó là kỳ lạ chắc chắn, nó sẽ được tốt đẹp để biết những gì đó là tất cả về nhưng tại thời điểm này tôi đã sẵn sàng để phấn một thêm lên đến gremlins. – Hexate