2010-10-24 6 views
7

Sto utilizzando i cmdlet di TFS PowerTools in PowerShell per cercare di ottenere alcune informazioni su changeset e workItem correlati dal mio server. Ho ridotto il problema a comportamenti che non capisco e spero che non sia specifico per TFS (quindi qualcuno là fuori potrebbe spiegarmi il problema :))Confusione di PowerShell Per ogni connessione/piping

Ecco l'unico comando che posso andare al lavoro:

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

non quello che mi aspettavo - Get-TfsItemHistory restituisce una lista di 5 gruppi di modifiche, e tubi di quelle ad un foreach che stampa il titolo del primo WorkItem associato. Allora, qual è il mio problema? Sto cercando di scrivere uno script di grandi dimensioni, e preferisco codificare le cose per sembrare più come un programma C# (la sintassi di PowerShell mi fa piangere). Ogni volta che provo a fare quanto sopra scritto in altro modo, la collezione WorkItems è nullo.

i seguenti comandi (che interpreto essere logicamente equivalenti) non funzionano (La collezione elementi di lavoro è nullo):

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

quella che avrei veramente preferisco:

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

ho letto un articolo sulla differenza tra l'operatore 'foreach' e il cmdlet ForEach-Object, ma sembra essere più un dibattito sul rendimento. Questo sembra essere un problema su quando viene utilizzata la piping.

Non sono sicuro del motivo per cui tutti e tre questi approcci non funzionano. Qualsiasi intuizione è apprezzata.

+3

Non sono sicuro di quale sia il problema, ma è decisamente specifico per i cmdlet TFS (sono piuttosto orribili, imo). Sembra che il cmdlet stia eseguendo il caricamento lento e una volta terminata la pipeline, il contesto dei dati è scomparso ed è troppo tardi per caricare i dati, ma il design dei cmdlet è così complicato che non riesco a rintracciarlo così lontano nel riflettore . – Jaykul

risposta

8

Questo è davvero fonte di confusione. Per ora un work-around è quello di afferrare gli oggetti in questo modo:

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

Questa accede all'insieme elementi di lavoro, che sembra causare questa proprietà per essere popolato (lo so - WTF?). Io tendo ad usare @() per generare un array nei casi in cui voglio usare la parola chiave foreach. La cosa con la parola chiave foreach è che itererà un valore scalare che include $ null. Quindi se la query non restituisce nulla, $items viene assegnato $ null e foreach itererà il ciclo una volta con $item impostato su null. Ora PowerShell si occupa in genere di null molto bene. Tuttavia, se si restituisce tale valore a .NET Framework, di solito non è così indulgente. Lo @() garantirà un array con elementi 0, 1 o N in esso. Se è 0 allora il ciclo foreach non eseguirà affatto il suo corpo.

BTW il tuo ultimo approccio - foreach ($item in $items) { ... } - dovrebbe funzionare bene.

+0

Grazie, funziona. Sono tornato in pista e non sono pazzo! Questo è strano, certo, sarebbe bello sapere di cosa si tratta, ma a questo punto sono pronto a dare un altro gesso ai gremlin. – Hexate