There are 2 ways to deal with this problem. The easiest ones are to simply save query first to variable and then either use ForEach-Object or foreach to gather results.
$Objects = Get-GPOZaurrAD @getGPOZaurrADSplat
$Objects | ForEach-Object -Process {
Write-Verbose "Get-GPOZaurrOwner - Processing GPO: $($_.DisplayName) from domain: $($_.DomainName)"
$ACL = Get-ADACLOwner -ADObject $_.GPODistinguishedName -Resolve -ADAdministrativeGroups $ADAdministrativeGroups
$Object = [ordered] @{
DisplayName = $_.DisplayName
DomainName = $_.DomainName
GUID = $_.GUID
DistinguishedName = $_.GPODistinguishedName
Owner = $ACL.OwnerName
OwnerSid = $ACL.OwnerSid
OwnerType = $ACL.OwnerType
}
if ($IncludeSysvol) {
$FileOwner = Get-FileOwner -JustPath -Path $_.Path -Resolve
$Object['SysvolOwner'] = $FileOwner.OwnerName
$Object['SysvolSid'] = $FileOwner.OwnerSid
$Object['SysvolType'] = $FileOwner.OwnerType
$Object['SysvolPath'] = $_.Path
}
[PSCUstomObject] $Object
}
From my own testing if I am already saving data to variable I prefer the later
$Objects = Get-GPOZaurrAD @getGPOZaurrADSplat
foreach ($_ in $Objects) {
Write-Verbose "Get-GPOZaurrOwner - Processing GPO: $($_.DisplayName) from domain: $($_.DomainName)"
$ACL = Get-ADACLOwner -ADObject $_.GPODistinguishedName -Resolve -ADAdministrativeGroups $ADAdministrativeGroups
$Object = [ordered] @{
DisplayName = $_.DisplayName
DomainName = $_.DomainName
GUID = $_.GUID
DistinguishedName = $_.GPODistinguishedName
Owner = $ACL.OwnerName
OwnerSid = $ACL.OwnerSid
OwnerType = $ACL.OwnerType
}
if ($IncludeSysvol) {
$FileOwner = Get-FileOwner -JustPath -Path $_.Path -Resolve
$Object['SysvolOwner'] = $FileOwner.OwnerName
$Object['SysvolSid'] = $FileOwner.OwnerSid
$Object['SysvolType'] = $FileOwner.OwnerType
$Object['SysvolPath'] = $_.Path
}
[PSCUstomObject] $Object
}
Alternatively, you can change Active Directory Web Services timeout to a higher value. The second option has two significant issues. One, you need to be in charge of your Active Directory environment, which may be hard enough in environments you would hit this issue. Also, your scripts would only work on AD that has higher values set, hitting errors as soon as you try to use it on similar scale environments that don't have adjusted timeout settings. Second, Microsoft discourages this change. You can read about it in the following article What's New in AD DS: Active Directory Web Services.
Changing the default value of this parameter is strongly discouraged. Most of the search results are returned within 30 minutes.
This means that a single call for Get-ADObject, Get-ADUser, Get-ADComputer (and so on) has to finish in 30 minutes or less. Using ForEach-Object, due to its nature, can impact the time it takes to deliver all records; therefore, you should use it with caution. Knowing this, I opted for the first approach – making sure I can use my scripts anywhere I want to.