【问题标题】:PowerShell - Enumerating through a collection and change the collectionPowerShell - 枚举集合并更改集合
【发布时间】:2012-02-18 18:59:15
【问题描述】:

如何修复这个脚本?

是的,我正在更改 foreach 循环中的集合,这就是导致此错误的原因。

枚举集合时出错:集合已修改;枚举操作可能无法执行.. 在 C:\Users\user\Documents\PowerShell\ChangeAllListsV2.ps1:47 char:20 + foreach

#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

【问题讨论】:

    标签: sharepoint powershell foreach


    【解决方案1】:

    我知道这是一个相当古老的线程。这是给任何最终到此页面寻找答案的人。

    这个想法是,就像其他答案所暗示的那样,将集合(使用 clone() 方法)复制到另一个并迭代“另一个”并修改循环内的原始变量而不必使用for 代替 foreach

    ArrayList 类型的集合:

    [System.Collections.ArrayList]$collection1 = "Foo","bar","baz"
    $($collection1.Clone()) | foreach {
    $collection1.Remove("bar")
    }
    

    输出:

    PS H:\> $collection1
    Foo
    baz
    

    Hashtable 类型的集合:

    [System.Collections.Hashtable]$collection2 = @{
            "Forum" = "Stackoverflow"
            "Topic" = "PowerShell"
            }
    
    $($collection2.Clone())| foreach {
    $collection2.Remove("Forum")
    }
    

    输出: PS H:> $collection2

    Name                           Value                                                              
    ----                           -----                                                              
    Topic                          PowerShell                                                         
    

    还有一个基本数组:

    [System.Array]$collection3 = 1, 2, 3, 4
    $($collection3.Clone()) | foreach {
    $collection3[$collection3.IndexOf($_)] = 10
    }
    

    输出:

    PS H:\> $collection3
    10
    10
    10
    10
    

    只要您的收藏不是固定大小的。

    【讨论】:

      【解决方案2】:

      检查: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 中并尝试修改哪个可以解决问题,这里我存储名为 enumcul 的 Arraylist 并将值插入其中并对其进行修改...

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

      【讨论】:

        【解决方案3】:

        SPListCollection 倾向于在更新其属性(字段、事件接收器等)时修改集合。您可以改用 for 循环:

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

        【讨论】:

          【解决方案4】:

          您可以尝试将当前正在迭代的集合复制到另一个集合(数组或列表),然后在该新集合上进行迭代。

          类似这样的:

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

          上面的代码给出以下输出:

          10 2 3 4
          1 2 3 4
          

          请注意,$copy 变量指的是不同的集合。

          【讨论】:

          • 你的意思是像 $webAppSites = $webApp.sites ?我复制每个集合,然后我使用 foreach
          • @LaPhi:不,不是那样的。你说的只是作业,不是抄袭。我更新了答案以显示如何复制数组。
          • 整个网站的深拷贝并不是最好的主意。常规的“for”循环是可行的方法。
          • @Servy 我不建议深度复制。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-14
          • 2013-01-25
          • 2011-04-09
          • 1970-01-01
          • 2012-04-30
          • 1970-01-01
          相关资源
          最近更新 更多