2010-10-24 21 views
7

Sunucumdan Changeset'ler ve ilgili WorkItems hakkında bazı bilgileri almaya çalışmak için PowerShell'deki TFS PowerTools Cmdlet'lerini kullanıyorum. Sorunu anlamadım ve anlayamadığım bir davranışa sahibim TFS'ye özgü değil (yani birisi bana sorunu açıklayabiliyor) :)PowerShell ForEach/Piping karışıklığı

İşte yapabileceğim tek komut işe geri almak:

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

Ben beklediğiniz yok - Get-TfsItemHistory 5 changesets bir listesini verir ve bu borular birinci bağlantılı Workitem Başlığını yazdıran bir foreach için bu. Peki benim sorunum nedir? Büyük bir senaryo yazmaya çalışıyorum ve bir C# programına benzemeye çalışıyorum (powershell sözdizimi beni ağlatıyor). Yukarıda belirtilenleri başka bir şekilde yazmayı denediğimde, WorkItems koleksiyonu boştur.

(Ben mantıken eşdeğer olarak yorumlamak) Aşağıdaki komutları

(WorkItems koleksiyonu null) çalışmaz:

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

Gerçekten tercih ediyorum: biri Okuduğum

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

'foreach' operatörü ve ForEach-Object Cmdlet arasındaki fark hakkında bir makale, ancak bu daha fazla bir performans tartışması gibi görünüyor. Bu gerçekten boruların kullanıldığı zamanlar için bir sorun gibi görünüyor.

Bu yaklaşımların üçünün neden çalışmadığından emin değilim. Herhangi bir fikir takdir edilir.

+3

Sorunun ne olduğundan emin değilim, ancak kesinlikle TFS Cmdlet'lerine özgüdür (oldukça korkunç, imo). Görünüşe göre, cmdlet tembel yükleme yapıyordu ve boru hattı bittiğinde, veri içeriği gitmiş ve verileri yüklemek için çok geç kalmıştı, ancak cmdlet'lerin tasarımı o kadar kıvrıktı ki, reflektörde bu kadar uzağa gidemedim . – Jaykul

cevap

8

Bu gerçekten kafa karıştırıcıdır. Şimdilik bir-etrafında çalışma öylesine gibi öğeleri kapmak için geçerli:

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

Bu, bu özelliği doldurulur neden görünüyor WorkItems koleksiyonunu erişir (biliyorum - WTF?). Foreach anahtar kelimesini kullanmak istediğim durumlarda bir dizi oluşturmak için @() kullanıyorum. Foreach anahtar kelimesiyle olan şey, $ null dahil olmak üzere bir skaler değer yinelemesidir. Bu nedenle, sorgu hiçbir şey döndürmezse, $items $ null atanır ve foreach, $item null değerine ayarlıyken bir kez döngü yinelemelidir. Şimdi PowerShell genellikle nulllarla çok güzel ilgilenir. Ancak, bu değeri .NET Framework'e geri verirseniz, genellikle affedici değildir. @(), içinde 0, 1 veya N öğesi bulunan bir diziyi garanti edecektir. 0 ise, o zaman foreach döngüsü, kendi vücudunu yürütmeyecektir.

BTW son yaklaşımınız - foreach ($item in $items) { ... } - iyi çalışması gerekir.

+0

Teşekkürler, bu işe yarıyor. Yoldayım ve delirmedim! Bu çok garip, neyin neyle ilgili olduğunu bilmek güzel olurdu ama bu noktada gremlinlere bir daha tebeşir çizmeye hazırım. – Hexate