2012-01-25 15 views
7

¿Cómo se puede corregir este script?PowerShell: enumerar a través de una colección y cambiar la colección

Sí, estoy cambiando la colección en el ciclo foreach y este es el motivo de este error.

Ocurrió un error al enumerar a través de una colección: Se modificó la colección; la operación de enumeración no puede ejecutar .. en C: \ Users \ usuario \ Documents \ PowerShell \ ChangeAllListsV2.ps1: 47 Char: 20 + foreach < < < < (lista $ en $ webLists) + CategoryInfo: InvalidOperation: (Microsoft .Share ... + en SPEnumerator: SPEnumerator) [], RuntimeException + FullyQualifiedErrorId: BadEnumeration

#Script change in all lists the required field property "testfield" to false 


#Part 0 - Configuration 

$urlWebApp = "http://dev.sharepoint.com" 
$countFound = 0 
$countList = 0 
$countFoundAndChange = 0 

#Part 1 - PreScript 

$snapin = Get-PSSnapin | Where-Object {$_.Name -eq "Microsoft.SharePoint.Powershell"} 

if ($snapin -eq $null) 

{ 
    Write-Host “Loading SharePoint Powershell” 
    Add-PSSnapin Microsoft.SharePoint.Powershell 
} 

#Part 2 - Script 

$webApp = Get-SPWebApplication $urlWebApp 

#$webApp | fl 

    $webAppSites = $webApp.sites 

    foreach($site in $webAppSites) 
    { 
     Write-Host "***********************************************************************" 
     Write-Host "Found site: " $site -foreground blue 

     $siteAllWebs = $site.AllWebs 

     foreach($web in $siteAllWebs) 
     { 
      Write-Host "Found web: " $web -foreground blue 
      #$web | fl 

      $webLists = $web.Lists 

      foreach($list in $webLists) 
      { 
      $countList ++ 

      Write-Host "Found list: " $list -foreground blue 

       #Change list property 

       $field = $Null 
       $field = $list.Fields["testfield"] 

        if($field){ 
        Write-Host "Field found: " $list -foreground green 
        #Write-Host "in web: " $web -foreground green 
        $countFound ++ 

         try{ 

          if($field.Required) 
          { 

          ####################################################### 
          $field.Required = $False 
          $field.Update() 
          ####################################################### 

          $field = $Null 
          Write-Host "Done!: Change list: " $list -foreground green 
          $countFoundAndChange ++      

          }else{ 
          Write-Host "Already!: Change list: " $list -foreground green  

          } 

         } 
         catch{ 
          $field = $Null 
          Write-Host "Error!: Change list: " $list -foreground red 
          Write-Host "in web: " $web -foreground red 
          $_ 

         } 

        } 


      } 


     } 


    } 



Write-Host "Found lists: " $countList 
Write-Host "Found lists with column [testfield]: " $countFound 
Write-Host "Change lists with column [testfield]: " $countFoundAndChange 

Respuesta

20

El SPListCollection tiende a modificar la colección al actualizar sus propiedades (campos, receptores de eventos, etc.). Puede utilizar un bucle para el lugar:

for ($i = 0; $i -lt $webLists.Count; $i++) 
{ 
    $list = $web.Lists[$i]; 
    # ... 
} 
3

puede intentar copiar la colección de la que se está iterando a otra colección (una matriz o una lista) y luego iterar en esa nueva colección.

Algo como esto:

$collection = @(1, 2, 3, 4) 
$copy = @($collection) 
$collection[0] = 10 
$collection -join " " 
$copy -join " " 

El código anterior muestra el siguiente resultado:

10 2 3 4 
1 2 3 4 

Tenga en cuenta que la variable $copy se refiere a una colección diferente.

+0

¿Quieres decir como $ webAppSites = $ webApp.sites? Copio cada colección y después de esto estoy usando el foreach – LaPhi

+0

@LaPhi: No, no así. De lo que estás hablando es solo una tarea, no una copia. Actualicé mi respuesta para mostrar cómo se copia una matriz. – Gebb

+1

Una copia profunda de un sitio completo no es la mejor de las ideas. Un bucle 'para' regular es el camino a seguir. – Servy

0

Comprobar: http://soreddymanjunath.blogspot.in/2014/07/collection-was-modified-enumeration.html

Aquí es anonther ejemplo para misma edición

if($web.IsMultilingual -eq $true ) 
    { 

    foreach($cul in $web.SupportedUICultures) 
    { 
    if($cul.LCID -ne $webCul.LCID -and $cul.LCID -ne "1033") 
    {  

     $web.RemoveSupportedUICulture($cul) 


     } 
    } 
$web.Update() 
    } 

por primera vez va a pasar por el foreach bucle eliminará cultura soportada por primera vez, cuando se trata de un ciclo para la segunda iteración, entonces se lanza la excepción "La colección fue modificada; la operación de enumeración no puede ejecutarse ",

La solución al problema de arriba es Almacenar en valores a modificar en un Arraylist e intentar modificar cuál solucionará el problema. Aquí estoy almacenando el Arraylist llamado enumcul e insertando valores en él y modificándolo ...

$enumcul=New-Object Collections.ArrayList 
$i=0 
if($web.IsMultilingual -eq $true ) 
    { 

    foreach($cul in $web.SupportedUICultures) 
    { 
    if($cul.LCID -ne $webCul.LCID -and $cul.LCID -ne "1033") 
    { 

     $enumcul.Insert($i, $cul) 
     $i=$i+1 
     } 

    } 


foreach($k in $enumcul) 
{ 

    $web.RemoveSupportedUICulture($k) 
    $web.Update() 
} 
Cuestiones relacionadas