2012-01-25 2 views
7

Как можно исправить этот скрипт?PowerShell - Перечисление через коллекцию и изменение коллекции

Да, я меняю коллекцию в цикле foreach, и это является причиной этой ошибки.

Произошла ошибка при перечислении через коллекцию: коллекция была изменена; операции перечисления не может выполнить .. В C: \ Users \ пользователь \ Documents \ PowerShell \ ChangeAllListsV2.ps1: 47 полукокса: 20 + Еогеасп < < < < ($ список в $ webLists) + CategoryInfo: InvalidOperation: (Microsoft .Share ... на + 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 

ответ

20

SPListCollection имеет тенденцию изменять коллекцию при обновлении ее свойств (полей, приемников событий и т. Д.). Вы можете использовать для цикла вместо:

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

вы можете попытаться скопировать коллекцию вы в настоящее время итерации на другую коллекцию (массив или список) а затем повторить эту новую коллекцию.

Что-то вроде этого:

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

Код выше, дает следующий результат:

10 2 3 4 
1 2 3 4 

Обратите внимание, что переменная $copy относится к другой коллекции.

+0

Вы имеете в виду $ webAppSites = $ webApp.sites? Я копирую каждую коллекцию, и после этого я использую foreach – LaPhi

+0

@LaPhi: Нет, не так. То, о чем вы говорите, это просто задание, а не копирование. Я обновил свой ответ, чтобы показать, как копируется массив. – Gebb

+1

Глубокая копия всего сайта - не лучшая идея. Правильный цикл «за» - это путь. – Servy

0

Проверил: http://soreddymanjunath.blogspot.in/2014/07/collection-was-modified-enumeration.html

Вот anonther пример тот же вопрос

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() 
    } 

впервые будет пройти через цикл по каждому элементу будет удалить поддерживая культуру для времени frist, когда дело доходит до цикла для второй итерации, тогда оно выдает вам исключение ». Коллекция была изменена; операция перечисления не может выполняться »,

Решение проблемы выше, чтобы сохранить значения, измененные в Arraylist, и попытаться изменить, что устранит проблему. Здесь я храню Arraylist под названием enumcul и вставляя в него значения и изменяя его ...

$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() 
} 
Смежные вопросы