PowerShell - Перечисление через коллекцию и изменение коллекции - PullRequest
7 голосов
/ 25 января 2012

Как можно исправить этот скрипт?

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

Произошла ошибка при перечислении в коллекции: коллекция была изменена; операция перечисления может не выполняться .. В C: \ Users \ user \ Documents \ PowerShell \ ChangeAllListsV2.ps1: 47 char: 20 + foreach <<<< ($ list в $ webLists) + CategoryInfo: InvalidOperation: (Microsoft.Share ... on + SPEnumerator: SPEnumerator) [], RuntimeException + FullyQualifiedErrorId: BadEnumeration </strong>

#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

Ответы [ 3 ]

20 голосов
/ 25 января 2012

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

for ($i = 0; $i -lt $webLists.Count; $i++)
{
  $list = $web.Lists[$i];
  # ...
}
3 голосов
/ 25 января 2012

Вы можете попробовать скопировать коллекцию, с которой вы сейчас работаете, в другую коллекцию (массив или список), а затем выполнить итерацию по этой новой коллекции.

Примерно так:

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

Приведенный выше код дает следующий вывод:

10 2 3 4
1 2 3 4

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

0 голосов
/ 03 июля 2014

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

Вот еще один пример для той же проблемы

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

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

Решение вышеуказанной проблемы - сохранить значения, измененные в 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()
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...