Since I got a comment complaining about the lack of PowerShell version (I did it in C# since I got the impression that's what the forum user needed), here's how I'd do it in PowerShell. While using the ListProjects | %{ ... } is certainly pithier, I'm sticking with foreach-style to keep it closer to the C# version and (IMHO) more readable. Additionally, it should help make it clear that translating one to the other is simple to do in most cases.
param ($serverName = $(throw 'please specify a TFS server name')) $tfs = get-tfs $serverName foreach ($project in $tfs.css.ListProjects()) { foreach ($projectGroup in $tfs.gss.ListApplicationGroups($project.Uri)) { $directMembers = $tfs.gss.ReadIdentity('Sid', $projectGroup.Sid, 'Direct') foreach ($memberSid in $directMembers.Members) { $member = $tfs.gss.ReadIdentity('Sid', $memberSid, 'None') $isGroup = $member.SecurityGroup -or $member.Type -eq 'WindowsGroup' -or $member.Type -eq 'ApplicationGroup' if (-not $isGroup) { write-warning ('Member {0} of group {1} in project {2} is not a group' -f $member.DisplayName, $projectGroup.DisplayName, $project.Name) } } } }