Dealing with “System.InvalidOperationException: Collection was modified; enumeration operation may not execute” error message in provisioning code.


This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm


 


This error message always gets me by surprise, so finally I decided to document this potential pitfall.


I typically get this error message in the provisioning code when I am trying to disconnect multiple connectors from different connector spaces. So here a sample code that will cause this error


 


If mventry(“oracleEnabled”).value = false


 For Each MA As ManagementAgent In mventry.ConnectedMAs


    If MA.Name.StartsWith("oracle") Then


       Mventry.ConnectedMAs(MA.Name).Connectors.DeprovisionAll()


    End If


 Next


Endif


 


So in this peace of code I am checking if the oracleEnabled Boolean attribute is set to false, and if yes (according to my business logic), I need to go through all of the connectors for Oracle and disconnect them. At first, this peace of code looks quite logical, we go through every connector space attached to the mventry and if it is an Oracle connector space, we deprovision all connectors. But if this code gets executed you will get an exception: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.


So what is the problem with this code? Well, the issue is really not related to MIIS, but rather how .NET handles enumeration of collections. Basically, the issue here is that inside the FOR EACH loop we are changing the collection that is used to control the loop. So in our case, we are using mventry.ConnectedMAs collection to control the loop, but inside the loop we are disconnecting some of the connector spaces which changes the mventry.ConnectedMAs collection, which in turn impacts the enumeration of the loop, and .NET throws an exception and rightly so.


So how do we get around this? Here is one way, simply save the MA names to a string array and then use that array for controlling the FOR EACH loop.


 


Dim ConnectedOraMAs() As String


Dim i As Integer = 0


    For Each MA As ManagementAgent In mventry.ConnectedMAs


        If MA.Name.StartsWith("oracle") Then


           ReDim Preserve ConnectedOraMAs(i)


           ConnectedOraMAs(i) = MA.Name


           i = i + 1


         End If


Next


 


If Not ConnectedOraMAs Is Nothing Then


 If mventry(“oracleEnabled”).value = false Then


   For Each MA As String In ConnectedOraMAs


mventry.ConnectedMAs(MA).Connectors.DeprovisionAll()                                  


   Next


End If


 


 


 

Skip to main content