Get all AD groups and Exchange features of users We have about 15000 users and 1000 groups in AD. I have been getting of all AD groups of all AD users and their Exchange features  via script like below. But now I have been waiting for more than 3 hours already. My question is: How can I improve the speed of the script?

$groups = Get-ADGroup -filter * -SearchBase "OU=Security Groups,DC=contoso,DC=com"
$groupsCSV = "Username;"
$groups | foreach {
$groupsCSV += $_.sAMAccountName
$groupsCSV += ";"
}
$groupsCSV += "ActiveSyncEnabled; OWAEnabled; POPEnabled; IMAPEnabled; MAPIEnabled; MAPIBlockOutlookRpcHttp"
$groupsCSV += "`n"
$users = Get-ADUser -filter {Name -like "*"} -SearchBase "OU=test,OU=test,DC=contoso,DC=com"
$users | foreach {
$currentUser = $_
ECHO Examine: $_.Name
$isMemberList=""
$groups | foreach {
$currentGroup = $_
$currentMembers = Get-ADGroupMember $_
$isMember = ""
$currentMembers | foreach  {
if ($_.sAMAccountName -like $currentUser.sAMAccountName )  {
$isMember = "x"
}
}
$isMemberList += $isMember
$isMemberList += ";"
}
$isMemberListCSV += $currentUser.Name
$isMemberListCSV += ";"
$isMemberListCSV += $isMemberList
$MBFeatures = Get-CasMailbox $currentUser.DistinguishedName
if( $MBFeatures.ActiveSyncEnabled){
$isMemberListCSV += "x"
}
$isMemberListCSV += ";"

if( $MBFeatures.OWAEnabled){
$isMemberListCSV += "x"
}
$isMemberListCSV += ";"

if( $MBFeatures.POPEnabled){
$isMemberListCSV += "x"
}
$isMemberListCSV += ";"

if( $MBFeatures.IMAPEnabled){
$isMemberListCSV += "x"
}
$isMemberListCSV += ";"

if( $MBFeatures.MAPIEnabled){
$isMemberListCSV += "x"
}
$isMemberListCSV += ";"

if( $MBFeatures.MAPIBlockOutlookRpcHttp){
$isMemberListCSV += "x"
}
$isMemberListCSV += ";"
$isMemberListCSV += "`n"
}
$fullCSV = $groupsCSV + $isMemberListCSV
ECHO $fullCSV &gt; fullCSV.txt
The lack of proper indentation hides the fact that for each user you request all the members of every group. That's 15000*1000 = 15 million remote calls, most of which redundant. Even if 100 calls would get answered per second, it would still take more than a day to receive all answers. 

The solution is simple: Only call Get-ADGroupMember once for each group, cache the results and then use them to check what groups each user is a member of.

If Get-CASMailbox can return the mailbox information for all users at once instead of one call/user (haven't used it but the documentation indicates it might) you reduce the number of calls even further.