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 https://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