Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I'm hoping that someone can give me a hand with two issues in Powershell that I have with modifying views in SharePoint 2010. I've had some help on this from someone over at stackoverflow but hasn't been able to progress further on two follow-up questions on the script.

They are hopefully quite simple to solve, just beyond my meagre grasp of powershell.

The goal of the script is to: Loop through all Document Libraries in a Web Application, check if there is a view already defined called "Detailed" and if not then create that view.

Issue 1) The script is generating an error when it runs. It was mentioned that you can't modify an element of the collection that is being enumerated. Can you show me how to work around this? Despite changes being made to avoid the problem it's still happening

An error occurred while enumerating through a  collection: Collection was modified; enumera tion operation may not execute.. At C:\Users\quickdev1\Documents\LoopThroughAl lLibrariesCreateView.ps1:7 char:10
+   foreach <<<< ($list in $web.Lists) {
    + CategoryInfo          : InvalidOperati     on: (Microsoft.Share...on+SPEnumerator:S     PEnumerator) [], RuntimeException
    + FullyQualifiedErrorId : BadEnumeration

Issue 2) I would like to put in some logic to check if an existing view is already there with the name "Detailed" and if so to skip that Library but I'm not sure how to achieve it.

Any assistance on these two items would be greatly appreciated.

Thanks,

Ashley

Add-PSSnapin Microsoft.SharePoint.PowerShell -erroraction SilentlyContinue

$siteURL = "http://sp14fdev01/"
$site = Get-SPSite($siteURL)

foreach($web in $site.AllWebs) {
  foreach($list in $web.Lists) {
    if($list.BaseType -eq "DocumentLibrary") {
// the variables `$web` and `$list` already reference the objects you need
      //$site = New-Object Microsoft.SharePoint.SPSite($SiteURL) ;
      //$web = $site.OpenWeb($SiteURL);

// new instance of the list is necessary to avoid the error "Collection was modified"
      $newList = $web.Lists.item($list.ID);

      $viewfields = New-Object System.Collections.Specialized.StringCollection 
      $viewfields.Add("DocIcon") 
      $viewfields.Add("LinkFilename") 
      $viewfields.Add("_UIVersionString") 
      $viewfields.Add("FileSizeDisplay") 
      $viewfields.Add("Created") 
      $viewfields.Add("Modified") 
      $viewfields.Add("Editor") 
      [void]$newList.Views.Add("Detailed", $viewfields, "", 100, $true, $true)

      $newList.Update();

// setting the default view
      $view=$newList.Views["Detailed"]
      $view.DefaultView = $true
      $view.Update()
    }
  }

  $web.Dispose();
}

$site.Dispose();
share|improve this question
add comment

2 Answers

Issue 1 During the loop through $web.Lists I'd only add to an array listids to work with and then loop throught that array later

Issue 2 Just get $list.Views["Detailed"] and check if what you get is $null

So all in all you'll get

Add-PSSnapin Microsoft.SharePoint.PowerShell -erroraction SilentlyContinue 

$siteURL = "http://sp14fdev01/" 
$site = Get-SPSite($siteURL) 

foreach($web in $site.AllWebs) {
  $listIds = @(); 
  foreach($list in $web.Lists) { 
    if($list.BaseType -eq "DocumentLibrary") {
      $existingView = $list.Views["Detailed"];
      if ($existingView -eq $null) {
        $listIds += $list.ID;
      }
    }
  }
  foreach ($listId in $listIds) {
    $newList = $web.Lists.item($listId); 
    Write-Host "Adding view to list $($newList.Title)"

    $viewfields = New-Object System.Collections.Specialized.StringCollection  
    $viewfields.Add("DocIcon")  
    $viewfields.Add("LinkFilename")  
    $viewfields.Add("_UIVersionString")  
    $viewfields.Add("FileSizeDisplay")  
    $viewfields.Add("Created")  
    $viewfields.Add("Modified")  
    $viewfields.Add("Editor")  
    [void]$newList.Views.Add("Detailed", $viewfields, "", 100, $true, $true) 

    $newList.Update(); 

#   setting the default view 
    $view=$newList.Views["Detailed"] 
    $view.DefaultView = $true 
    $view.Update() 
  } 

  $web.Dispose(); 
} 

$site.Dispose(); 
share|improve this answer
    
Thanks guys, I'll test it later on tonight. –  AshFlaw Apr 5 '12 at 14:43
add comment

Well, I can address the first issue. Even if you add the item to a different list, it's still the same item. So modifying it via an intermediary list is still modifying the original item, which is a part of the collection you are iterating through.

Have you tried just not calling the Update() method until after iterating all the way through the loop? Like:

foreach($list in $web.Lists){
  if($list.BaseType -eq "DocumentLibrary") {
    Check if "Detailed" view exists (if ($list.Views["Detailed"].Exists()) ?
                                     or something to that affect)
    Add Your View
    Add item to $newlist (as a collection, rather than an item)
  }
}
$list.Update();

foreach($list in $newlist){
  Change your view
}
$newlist.Update();

That way you aren't actually updating the item until after the entire collection has been iterated through. You still use an intermediary list to store which lists you actually modified, so you can set the Detailed view as default after the view has been added.

I haven't tried it, but I'm pretty sure that will remedy your problem.

share|improve this answer
    
Thanks, I look into it tonight. –  AshFlaw Apr 5 '12 at 14:43
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.