2

What is the proper way to free up memory in Powershell when looping trough list items? This loop is slowly eating up the memory:

for ($ID= 94368; $ID -le 98970 ; $ID++)
# foreach ($ID in $Ids)
{

try
{

    $item = $list.GetItemById($ID)
    $ctx.Load($item)
    $ctx.ExecuteQuery()

    if ($item["TaskStatus"] -eq "Nezačaté" )
    {

        Write-Host "Nastavim jedinecne prava na polozku $ID" -NoNewline
        changePermissions -listName $listName -itemId $ID
        Write-Host " OK" -ForegroundColor Green

    } else {

        Write-Host "Nastavim dedenie prav na polozku $ID" -NoNewline
        resetPermissions -listName $listName -itemId $ID
        Write-Host " OK" -ForegroundColor Green

    }
} 
catch 
{
  write-host "$($_.Exception.Message)" -foregroundcolor red
} 
finally
{
    $item.Dispose()  # Not existing method
    [GC]::Collect()  # Not helping

}


}

I think the $ctx (ClientContext) variable is getting bigger in each loop, but it is just my opinion. Is there something like $ctx.unload($item)? Or I must dispose the $ctx in each loop and retrieve it again? (it will impact on speed) Appreciate any help.

EDIT: Our best solution right now is, to select items with modified date greater or equal than today-1day, and run the script each day at night. Because TaskStatus cannot be changed by user without changing the modified date.

3
+50

You could optimize the code by getting all the items that you need before the for loop, instead of requesting every item and going to the server to get it from within the loop. So, basically, you need to create a query object, get all items in one call to the server, and then loop through items and do whatever you need to do. This way you will save both the memory and the execution time.

Try using this code and put the body of your for loop in it:

    $camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery
    $caml = "<View><Query><Where><And><Gt><FieldRef Name='ID' /><Value Type='Number'>94367</Value></Gt><Lt><FieldRef Name='ID' /><Value Type='Number'>98971</Value></Lt></And></Where></Query></View>" 
    $camlQuery.Query = $caml 

    $items = $list.GetItems($camlQuery)
    $ctx.Load($items)
    $ctx.ExecuteQuery()     

    foreach ($item in $items)
    {            
        $ID = $item.FieldValues["ID"]            
        if ($item.FieldValues["TaskStatus"] -eq "Nezačaté" )
        {

          Write-Host "Nastavim jedinecne prava na polozku $ID" -NoNewline
          changePermissions -listName $listName -itemId $ID
          Write-Host " OK" -ForegroundColor Green

        } else {

          Write-Host "Nastavim dedenie prav na polozku $ID" -NoNewline
          resetPermissions -listName $listName -itemId $ID
          Write-Host " OK" -ForegroundColor Green

       }
    }

EDIT: One additional thing to be aware of... judging by the way you call changePermissions and resetPermissions functions it might be the case that they also make more than one call to the server internally. If that is the case it would be good to modify them also to reduce the number of those calls as much as possible - you could call the $ctx.ExecuteQuery() only after 50 or 100 items have been changed (sasfrog mentioned this approach in the comment).

  • 1
    This should be the answer! Making the script talk to the server fewer times will greatly reduce your memory hit and runtime. – BigRaj Jun 24 at 15:54
  • 1
    Yep this is spot-on. Looking at those ID values, you may need to also handle list threshold issues, which might preclude the full range in your query. If this is an issue, you could chunk up your query into batches of say 100 items, dynamically building each chunk’s query in an outer loop and doing the item-by-item loop for each set/chunk. – sasfrog Jun 24 at 22:14
  • Yes, this could be the way, if I want to process few thousand items, but the problem is, that the list have 100 000 items, and sometimes we have to process the whole list. The point of the resetting unique permissions of closed tasks is that, the list can not have more than 50 000 unique permissions. – Bálint Jun 25 at 6:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.