0

I have the following script that will loop through each web/list/content type looking for a specific content type. If it finds it, and that content type is not in use, then it will delete it and update() the list, otherwise the error will be caught.

Seems to work fine except I have somehow created an infinite loop and the same lists will be outputted to the console over and over until I break out of the script. Can someone see where in my code this maybe happening?

    foreach ($web in $site.AllWebs) 
 {
  foreach ($lst in $web.lists | ?{$_.Fields.ContainsField($field)}) 
  { 
  foreach ($ctype in $lst.ContentTypes) 
  {
   if ($ctype.Name -eq $ctName)
   { 
        try
        {
            $ctToRemove = $ctype
            $location = $lst.DefaultViewUrl
            Write-Host "attempting to delete content type: $ctName at: $location" -ForegroundColor Yellow
            $lst.ContentTypes.Delete($ctToRemove.Id)
            $lst.Update()
            Write-Host "$ctype.Name deleted"
            write-Host "--------------------------------------------"
        }
        catch
        {
            write-host "Unable to delete the content type at $location, it is probably in use" -ForegroundColor Yellow
            write-Host "--------------------------------------------"
        }
   }
   }
  } 

 }
 $web.Dispose()

1 Answer 1

1

This may be because you're modifying a collection ($lst.ContentTypes.Delete()) while you're looping through it. This is not permitted.
Try:

 foreach ($web in $site.AllWebs) 
 {
    foreach ($lst in $web.lists | ?{$_.Fields.ContainsField($field)}) 
    { 
        foreach ($ctype in $lst.ContentTypes) 
        {
            $ctToRemove = $null
            if ($ctype.Name -eq $ctName) # We found the CT we want to delete
            { 
                $ctToRemove = $ctype # we keep a reference to it
                break # No need to continue iterating $lst.ContentTypes as we got what we were looking for
            }
        }

        if ($ctToRemove -ne $null) # Delete the CT we found, if any
        {
            try
            {
                $location = $lst.DefaultViewUrl
                Write-Host "attempting to delete content type: $ctName at: $location" -ForegroundColor Yellow
                $lst.ContentTypes.Delete($ctToRemove.Id)
                #$lst.Update() # Not sure that one is needed
                Write-Host "$ctype.Name deleted"
                write-Host "--------------------------------------------"
            }
            catch
            {
                write-host "Unable to delete the content type at $location, it is probably in use" -ForegroundColor Yellow
                write-Host "--------------------------------------------"
            }
        }
    } 
    $web.Dispose() # Must be inside the outer loop, otherwise it's pointless
}
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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