Wednesday, January 30, 2013

Find and Replace Old Link URLs in Quick Launch, Top Navigation Menus during Migration

Found so many hard-coded links (Absolute links) in SharePoint Quick launch and in Top navigation bar. This PowerShell script, Scans and Replaces the provided Old URL with the New URL all over the SharePoint web Application.

PowerShell Script to Find and Replace Quick Launch & Top Navigation Links:
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

#Set Old & New URLs
$OldURL = "http://moss2007.crescent.com"
$NewURL = "http://sharepoint2010.crescent.com"

#Get all sites of the web application
$webs = Get-SPWebApplication "http://sharepoint.crescent.com" | Get-SPSite -Limit All | Get-SPWeb -Limit All
 
#Iterate through webs
foreach ($web in $webs)
{
 #Get the Quick Launch Bar Nodes
 $QuickLaunchNodes = $Web.Navigation.QuickLaunch 
 #For Top Navigation use: $Web.Navigation.TopNavigationBar . TOp Nav may or May not have child nodes

 #Iterate through each Parent nodes of Quick launch
 foreach ($parentNode in $QuickLaunchNodes)
 { 
    if($parentNode.Url -match $OldURL)  #if you want to match Link text, use: $parentNode.Title
 {
        $parentNode.Url = $parentNode.Url.Replace($OldURL,$NewURL)
        $parentNode.Update()
  Write-Host "$OldURL Updated!"
    }
 #Get the Child Nodes
 $childNodes = $parentNode.Children
 
 #Iterate through child nodes
 foreach ($childNode in $childNodes)
  {
         if($childNode.Url -match $OldURL)
   {
             $childNode.Url = $childNode.Url.Replace($OldURL,$NewURL)
             $childNode.Update()
    Write-Host "$OldURL Updated!"
   }
     }
 }
$Web.Dispose()
 
This script may even helpful when you move your SharePoint web application to different URL.


You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Monday, January 28, 2013

SharePoint Top Navigation Link: Open in New Window

There was a requirement is to add a link in intranet portal's top navigation bar. Provided on clicking the link, it should open in new window, as the site link added was developed in a different platform & environment other than SharePoint.

If publishing feature is enabled, we can just go to: Site Actions >> Site Settings >> Navigation (Under Look and Feel), Add a New link with "Open link in new window" check-box selected. That's all, We are done with opening top navigation link in new window!
sharepoint navigation hyperlink open new window
However, In the provided site we don't have publishing feature enabled. So, in site settings page, we saw "Top link bar" link instead of "Navigation". Unfortunately, it doesn't provide us an option to open links in new window.
sharepoint top link new window
Here is the Trick to Open SharePoint top navigation link in New Window: JavaScript!
In URL field, just enter: javascript:void(window.open('http://your-link.aspx','_blank')) 
open url new window sharepoint 2010
Even javascript:void(window.open('http://your-link.aspx')) will work!

In my case, I had to enter:
javascript:void(window.open('https://peoplesoft.crescent.com/employee/profile.aspx','_blank')) 
Same trick can be used to open SharePoint quick launch links in new window.

Follow this post to open SharePoint Link list links to new window: SharePoint Link list: Open in a New Window

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


How to Start a SharePoint Workflow using PowerShell

Requirement is: To start a specific Workflow on All documents in a document library.

Solution: Lets use PowerShell to Start workflow Programmatically on all Items in a Document Library! After making sure, Manual start is enabled for the workflow:
# For MOSS 2007 compatibility
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

#Region MOSS2007-CmdLets
Function global:Get-SPSite()
{
  Param( [Parameter(Mandatory=$true)] [string]$SiteCollURL )

   if($SiteCollURL -ne '')
    {
    return new-Object Microsoft.SharePoint.SPSite($SiteCollURL)
   }
}
 
Function global:Get-SPWeb()
{
 Param( [Parameter(Mandatory=$true)] [string]$SiteURL )
  $site = Get-SPSite($SiteURL)
        if($site -ne $null)
            {
               $web=$site.OpenWeb();
            }
    return $web
}
#EndRegion

#Get the Web
$web = Get-SPWeb "http://sharepoint.company.com"

#Get the List
$list=$web.Lists["Review Documents"]

#Get Workflow Manager
$WFManager=$Web.site.WorkFlowManager

#Get the specifi workflow, Associated with the list
$WFAssociation = $list.WorkFlowAssociations | where {$_.Name -eq "Approval Workflow"}

#Start Workflow on Each List Item
foreach ($item in $list.Items)
  {
    $WFManager.StartWorkFlow($item,$WFAssociation,$WFAssociation.AssociationData)
    write-host "Started Workflow on $($item.Name)"
  }
$web.Dispose()
Using this method, We can Start/Stop/Cancel even Nintex Workflows!


You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Sunday, January 27, 2013

Set Permissions and Restrict Access to SharePoint Views

Little background: PMO from Sales domain came with this requirement: They Have a list for capturing project metrics in a project collaboration SharePoint Site with below columns:
sharepoint restrict access to views

There are two requirements:
  1. When Project Managers logs in, they should get projects in which they are assigned as "Project Managers".
  2. When Program Manager logs in, He should get all of the projects.
To solve the first requirement, I asked them to set the view filter as: "[Project Manager] is equals to [ME]", simple, uh?

For the second requirement, Program Manager should get all projects, nothing comes to my mind other than creating a separate view without filters. But how do we restrict normal users/ project managers from accessing the view for Program Managers? (of course, PMOs can create private views, but they don't wanted to!). So, Lets restrict access and secure view by setting permissions.

Set Permission on SharePoint View:

SharePoint doesn't provide any direct ways to Set Permissions and Restrict Access to SharePoint Views Out-of-the-box. Lets use this trick to get the permissions applied to SharePoint list views.
1. Create a List view page in the list, Say "PMO.aspx"
2. Move the View to any document library (E.g. to "Site Pages" library)
3. Break the Permissions of the page, Grant access to "Program Managers" group
4. Move the View page back to List.


Here is the detailed Step by Step:

Step 1: Create a List view page in the list
Open the site in SharePoint Designer, Navigate to the List (say: Project Metrics), Right click the List in Treeview >> Click on "New" >> List View Page
sharepoint restrict access list views

Give it a Name, Say: "PMO" and click "OK". This will create new aspx page: PMO.aspx.
sharepoint secure list view

Step 2: Move the View Page to "Site Pages" Library
Since lists doesn't provide a way to apply item level permissions on list view forms, we need to move the list page to a document library, Apply the permissions and then move the view page back to the list. So lets cut the PMO.aspx from Project Metrics List
sharepoint 2010 set permissions view

Paste the PMO.Aspx into "Site Pages" Libary
set permissions on a view sharepoint

Set permissions on SharePoint views: Now, Navigate to "Site Pages" library from browser. Click on "Manage Permissions"
restrict access sharepoint views

Click on "Stop Inhering permissions" from Ribbon to break the list view's permissions.
set permissions list views sharepoint 2010
Leave the users/groups who needs access to the view and remove all others. By this we have restricted access to views with required users and groups.
restrict access to sharepoint list views
Now, Go back to the SharePoint Designer, Cut the page from "Site Pages" Library and Paste it back to "Project Metrics" list.
set permissions sharepoint list view

That's all, We are done setting permissions for SharePoint view!

When users logged in to the site, they'll get to see the secured view.
set permissions sharepoint views

But if they try to access our secured view "PMO" which is restricted access, they'll get "Access Denied"
sharepoint 2010 secure view


You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Monday, January 21, 2013

Dynamic Fusion Charts from SharePoint 2010 List Data

I said it before, and I'm saying it again: "Fusion Charts is a great product!" .In my earlier fusion chart implementations, most of the cases, charts are generated with predefined category. In some cases, I've fusion charts generated for SharePoint 2010 with dynamic categories as well.

How to use fusion chart in SharePoint 2010
Here is one among them: Had a List for tracking project risks and the requirement is to generate a Pie chart based on Risk count. Here is my "Risk Metrics" List structure. Among bunch of fields, I took only "Project Name" field and calculate its count for my requirement.
Fusion Chart SharePoint 2010

Steps to Create Dynamic Fusion Charts from SharePoint List
Simple! just download the Fusion Chart Free version and upload the SWF files to a SharePoint Document library. Create a Web Part Page, Insert a Empty Data View Web Part, Drag & Drop Relevant fields to the web part (in my case its "Project Name"), Change the XSL accordingly. Refer my existing posts on Fusion Chart for SharePoint - step by step procedures.

XSL for Generating Dynamic Fusion Charts from SharePoint List Data:
After Removing everything between
<xsl:template name="dvt_1.body">
 <xsl:param name="Rows"/>
and
</xsl:template>

<xsl:template name="dvt_1.body">
       <xsl:param name="Rows"/>
          <xsl:variable name="varColorString" select="'XXXXXXAFD8F8F6BD0F8BBA00FF8E46008E8ED646468E468E588526B3AA00008ED69D080DA186BE'" />
     <xsl:variable name="varChartValue">
           <xsl:for-each select="$Rows[not(preceding-sibling::Row/@Project_x0020_Name = @Project_x0020_Name ) and @Project_x0020_Name!='']">
     <xsl:sort select="@Project_x0020_Name"/> 
    <xsl:variable name="varTemp" select="@Project_x0020_Name"/>
  
  
 &lt;set name=&apos;<xsl:value-of select="translate(@Project_x0020_Name,'&amp;','-')"/>&apos; value=&apos;<xsl:value-of select=" count($Rows[@Project_x0020_Name = $varTemp])"/>&apos; color=&apos;<xsl:value-of select="substring($varColorString, position()*6+1,6)" />&apos; /&gt; 
</xsl:for-each>
<br/>
     </xsl:variable>
   <xsl:variable name="varChartData">
   &lt;graph caption=&apos;Open risks &apos; xAxisName=&apos;Project Name&apos; yAxisName=&apos;Count&apos; showNames=&apos;1&apos; decimalPrecision=&apos;0&apos; formatNumberScale=&apos;0&apos; pieYScale=&apos;45&apos; pieRadius=&apos;70&apos; animation=&apos;1&apos; shadowXShift=&apos;4&apos; shadowYShift=&apos;4&apos; shadowAlpha=&apos;40&apos; pieFillAlpha=&apos;95&apos; &gt;
   <xsl:value-of select="$varChartValue" />
      &lt;/graph&gt;   
      </xsl:variable>
     
  <tr>
  <td>
       <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="500" height="400">
       <param name="movie" value="http://sharepoint.crescent.com/charts/FCF_Pie2D.swf?chartWidth=500&amp;chartHeight=400" >
   <xsl:text xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" ddwrt:whitespace-preserve="yes" xml:space="preserve">
</xsl:text>
 <param name="FlashVars" value="&amp;dataXML={$varChartData}&amp;chartWidth=500&amp;chartHeight=400"><param name="quality" value="high" /></param></param>
  
       </object>

   </td>
   </tr> 
 </xsl:template>

Chart Output:
Dynamic Fusion Charts from SharePoint 2010 List Data

Refer my old posts on Fusion Charts for more info:


You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Sunday, January 20, 2013

SharePoint Document Versions Size Report with PowerShell

This is a PowerShell version of my existing post Version History Size Report for SharePoint which uses C# object model to generate versioning report and gives insights, such as:
  • Site/Library's Total versions size
  • Total No. of versions created
  • Which documents are with more versions
  • Type of the documents
  • Library in which the document stored. Library Size with/Without versions
  • When was the last version modified
  • Size of the document's latest version
  • How much storage space being occupied by versions
  • Total size of the document including versions
PowerShell Script to generate Document Versions Report:
# Get Size of all Sub-sites in a Site Collection
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

#Region MOSS2007-CmdLets

Function Get-SPWebApplication()
{   
  Param( [Parameter(Mandatory=$true)] [string]$WebAppURL )
  return [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($WebAppURL)
}

Function global:Get-SPSite()
{
  Param( [Parameter(Mandatory=$true)] [string]$SiteCollURL )

   if($SiteCollURL -ne '')
    {
    return new-Object Microsoft.SharePoint.SPSite($SiteCollURL)
   }
}
 
Function global:Get-SPWeb()
{
 Param( [Parameter(Mandatory=$true)] [string]$SiteURL )
  $site = Get-SPSite($SiteURL)
        if($site -ne $null)
            {
               $web=$site.OpenWeb();
            }
    return $web
}
#EndRegion

 Function GenerateVersionSizeReport()
 {  
    #Define 'Web Application URL' as Mandatory Parameter
    Param( [Parameter(Mandatory=$true)] [string]$WebAppURL )
 
 #Get the Web Application
    $WebApp=Get-SPWebApplication($WebAppURL)

    #Write the CSV Header - Tab Separated
 "Site Name`t Library `t File Name `t File URL `t File Type `t Last Modified `t No. of Versions `t Latest Version Size(MB) `t Versions Size(MB) `t Total File Size(MB)" | out-file VersionSizeReport.csv

 #Loop through each site collection
  foreach($Site in $WebApp.Sites)
   {
    #Loop through each site in the site collection
     foreach($Web in $Site.AllWebs)
   {
            #Loop through  each List
            foreach ($List in $Web.Lists)
            {
                #Get only Document Libraries & Exclude Hidden System libraries
                if ( ($List.BaseType -eq "DocumentLibrary") -and ($List.Hidden -eq $false) )
                {
                    foreach ($ListItem  in $List.Items)
                    {
          #Consider items with 1+ versions
                        if ($ListItem.Versions.Count -gt 1)
                        {
          $versionSize=0

                            #Get the versioning details
                            foreach ($FileVersion in $ListItem.File.Versions)
                            {
                                $versionSize = $versionSize + $FileVersion.Size;
                            }
       #To Calculate Total Size(MB)
       $ToalFileSize= [Math]::Round(((($ListItem.File.Length + $versionSize)/1024)/1024),2)
       
                            #Convert Size to MB
                            $VersionSize= [Math]::Round((($versionSize/1024)/1024),2)
       
       #Get the Size of the current version
       $CurrentVersionSize= [Math]::Round((($ListItem.File.Length/1024)/1024),2)
       
                            #Get Site Name
                            if ($Web.IsRootWeb -eq $true)
                            {
                                $siteName = $Web.Title +" - Root";
                            }
                            else
                            {
                                $siteName= $Site.RootWeb.Title + " - " + $Web.Title;
                            }

                            #Log the data to a CSV file where versioning size > 0MB!
                            if ($versionSize -gt 0)
                            {
                                "$($siteName) `t $($List.Title) `t $($ListItem.Name) `t $($Web.Url)/$($ListItem.Url) `t $($ListItem['File Type'].ToString()) `t $($ListItem['Modified'].ToString())`t $($ListItem.Versions.Count) `t $CurrentVersionSize `t $($versionSize) `t $($ToalFileSize)" | Out-File VersionSizeReport.csv -Append
                            }
                        }
                    }
                }
            }
  $Web.Dispose()          
        }
 $Site.Dispose()          
    }
 
    #Send message to console
    write-host "Versioning Report Generated Successfully!"
}

#Call the Function to Generate Version History Report
GenerateVersionSizeReport "http://sharepoint.crescent.com"

and the output after importing Data to Microsoft Excel:
 After adding Pivot chart for analysis:

You can download the script from MSDN: SharePoint Document Versions Size Report for SharePoint 2010 and MOSS 2007

Few Additions to the Script:
  1. Exclude SharePoint's System Lists & Libraries: You may want to exclude Lists and Libraries SharePoint uses for its own operations. E.g. "Pages". Just have a array with all system lists and exclude them from processing. 
  2. You may want to compare date. Such as: consider documents which are more than one year old (in other words, Last modified date > 1 year from now)
Here is the updated script, satisfying above requirements:
# Get Size of all Sub-sites in a Site Collection
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") > $null

#Region MOSS2007-CmdLets

Function Get-SPWebApplication()
{   
  Param( [Parameter(Mandatory=$true)] [string]$WebAppURL )
  return [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($WebAppURL)
}

Function global:Get-SPSite()
{
  Param( [Parameter(Mandatory=$true)] [string]$SiteCollURL )

   if($SiteCollURL -ne '')
    {
    return new-Object Microsoft.SharePoint.SPSite($SiteCollURL)
   }
}
 
Function global:Get-SPWeb()
{
 Param( [Parameter(Mandatory=$true)] [string]$SiteURL )
  $site = Get-SPSite($SiteURL)
        if($site -ne $null)
            {
               $web=$site.OpenWeb();
            }
    return $web
}
#EndRegion

 Function GenerateVersionSizeReport()
 {  
    #Define 'Web Application URL' as Mandatory Parameter
    Param( [Parameter(Mandatory=$true)] [string]$WebAppURL )
 
 #Get the Web Application
    $WebApp=Get-SPWebApplication($WebAppURL)

    #Write the CSV Header - Tab Separated
 "Site Collection Name `t Site Name`t Library `t File Name `t File URL `t File Type `t Last Modified `t No. of Versions `t Latest Version Size(MB) `t Versions Size(MB) `t Total File Size(MB)" | out-file VersionSizeReport.csv

 #Arry to Skip System Lists and Libraries
 $SystemLists =@("Pages", "Converted Forms", "Master Page Gallery", "Customized Reports", "Documents", 
                 "Form Templates", "Images", "List Template Gallery", "Theme Gallery", "Reporting Templates", 
         "Site Collection Documents", "Site Collection Images", "Site Pages", "Solution Gallery", 
                               "Style Library", "Web Part Gallery","Site Assets", "wfpub")
 
 #Get Last Year's Same day!
 $DateFilter=([DateTime]::Now.AddYears(-1))

   #Loop through each site collection
  foreach($Site in $WebApp.Sites)
   {
    #Loop through each site in the site collection
     foreach($Web in $Site.AllWebs)
   {
            #Loop through  each List
            foreach ($List in $Web.Lists)
            {
                #Get only Document Libraries & Exclude Hidden System libraries
                if ( ($List.BaseType -eq "DocumentLibrary") -and ($List.Hidden -eq $false) -and($SystemLists -notcontains $List.Title) )
                {
                    foreach ($ListItem  in $List.Items)
                    {
          #Consider items with 5+ versions And apply Date Filter
                        if ( ($ListItem.Versions.Count -gt 5) -and ( $ListItem['Modified'] -lt $DateFilter))
                        {
          $versionSize=0

                            #Get the versioning details
                            foreach ($FileVersion in $ListItem.File.Versions)
                            {
                                $versionSize = $versionSize + $FileVersion.Size;
                            }
       #To Calculate Total Size(MB)
       $ToalFileSize= [Math]::Round(((($ListItem.File.Length + $versionSize)/1024)/1024),2)
       
                            #Convert Size to MB
                            $VersionSize= [Math]::Round((($versionSize/1024)/1024),2)
       
       #Get the Size of the current version
       $CurrentVersionSize= [Math]::Round((($ListItem.File.Length/1024)/1024),2)

                            #Log the data to a CSV file where versioning size > 0MB!
                            if ($versionSize -gt 0)
                            {
                                "$($Site.RootWeb.Title) `t $($Web.Title) `t $($List.Title) `t $($ListItem.Name) `t $($Web.Url)/$($ListItem.Url) `t $($ListItem['File Type'].ToString()) `t $($ListItem['Modified'].ToString())`t $($ListItem.Versions.Count) `t $CurrentVersionSize `t $($versionSize) `t $($ToalFileSize)" | Out-File VersionSizeReport.csv -Append
                            }
                        }
                    }
                }
            }
  $Web.Dispose()          
        }
 $Site.Dispose()          
    }
 
    #Send message to console
    write-host "Versioning Report Generated Successfully!"
}

#Call the Function to Generate Version History Report
GenerateVersionSizeReport "http://sharepoint.crescent.com"



You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


My Site, My Profile Links Not Found in SharePoint 2010

Problem:
End-Users were unable to create my site in SharePoint 2010 as the "My Site" link doesn't appear on Welcome Menu!
sharepoint 2010 my site link is missing

Cause:
After making sure User Profile Service Application is properly configured, found UPS is not associated with the particular web application! That's why SharePoint 2010 my site link is missing!

Solution:
Associate UPS Service Application with the web application. Go to
  • Central Administration >> Application Management >> Manage Web Applications
  • Pick the Relevant Web Application (In my case: user tried creating my site from: http://intranet.crescent.com")
  • Click on "Service Connections" button from the Ribbon
  • Enable the User Profile Service Application to associate it with the particular web application.
mysite link not visible sharepoint 2010
Done! We've fixed my site link missing issue! Now "My Site" link is visible in SharePoint 2010 welcome menu!
mysite link not visible sharepoint 2010 This doesn't' solve your issue? No worries, Check out this Troubleshooting Checklist: SharePoint My Site Creation Error - "There has been an error creating the personal site. Contact your site administrator for more information"

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Friday, January 18, 2013

How to Change SharePoint List or Library Settings Programmatically with PowerShell

Today there was a requirement to change SharePoint document library draft item security on all document libraries in a sub-site. We used to achieve it by going to
  • Document Library settings >>
  • Versioning Settings >>
  • Change "Draft Item Security" from "Any user who can read items (default setting)" to "Only users who can edit items" as per the requirement.
Not bad! but there were 50+ document libraries! OMG!! It kept the developer busy for some time!!! Why don't we script it? sure, Lets change SharePoint List or Library settings programmatically with PowerShell.

Change SharePoint List Settings Programmatically with PowerShell
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

#Function to Get a Single List
function Get-SPList([string]$URL, [string]$ListName) 
{
  $Web = Get-SPWeb $URL
  $List = $Web.Lists[$ListName]
  return $List
  $Web.Dispose()
}

$WebURL= "http://sharepoint.crescent.com"
#Get the List 
$list= Get-SPList $WebURL "Shared Documents"

#Set Draft item security - Who should see draft items in this list? 
$list.DraftVersionVisibility = 1
#Any user who can read items = 0. Only users who can edit items = 1. Only users who can approve items (and the author of the item) = 2

#Update list settings
$list.Update()

After making sure it works as expected, I changed the code to loop through required document libraries and apply the settings.
# For MOSS 2007 compatibility
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

#Region MOSS2007-CmdLets
Function global:Get-SPSite()
{
  Param( [Parameter(Mandatory=$true)] [string]$SiteCollURL )

   if($SiteCollURL -ne '')
    {
    return new-Object Microsoft.SharePoint.SPSite($SiteCollURL)
   }
}
 
Function global:Get-SPWeb()
{
 Param( [Parameter(Mandatory=$true)] [string]$SiteURL )
  $site = Get-SPSite($SiteURL)
        if($site -ne $null)
            {
               $web=$site.OpenWeb();
            }
    return $web
}
#EndRegion


#Site URL 
$WebURL= "https://sharepoint.crescent.com/regions/emea/"

$Web=Get-SPWeb $WebURL
 
 foreach($List in $web.lists)
 {
   #Change the setting for all document libraries
   if ( ($List.BaseType -eq "DocumentLibrary") -and ($List.Hidden -eq $false) )
   {
       write-host "Applying Settings on List: $($list.title)"
         
        #Set Draft item security - Who should see draft items in this list?
        $list.DraftVersionVisibility = 1
        #Any user who can read items = 0. Only users who can edit items = 1. Only users who can approve items (and the author of the item) = 2
         
        #Update list settings
        $list.Update()
   }

 }

Later, I was playing a bit with list properties programmatically. I'm giving it for reference:
Title, description and navigation
#List Name
$list.Title = "Project Metrics"

#List Description
$list.Description = "List to Capture Project Artifacts"

#Navigation: Display this document library on the Quick Launch? 
$list.OnQuickLaunch=$false
Versioning Settings
#Content Approval
$list.EnableModeration = $true

#Document Version History Settings
$list.EnableVersioning = $true
$list.EnableMinorVersions = $true #Applicable only to Libraries
$list.MajorWithMinorVersionsLimit = 5 #No. of Drafts in Lists
$list.MajorVersionLimit = 5

#Set Draft item security
#Who should see draft items in this list? 
$list.DraftVersionVisibility = [Microsoft.SharePoint.DraftVisibilityType]::Author
#Any user who can read items = 0. Only users who can edit items = 1. Only users who can approve items (and the author of the item) = 2

#Require Check Out:
$list.ForceCheckout = $true

#Set Validation Settings
$list.ValidationFormula = "=[EndDate] > [StartDate] "
$list.ValidationMessage = "End Date must be > Start Date!"
Advanced Settings
#Allow management of content types? 
$list.ContentTypesEnabled = $true
Opening Documents in the Browser - Applicable only to Libraries
#Open in the client application
$list.DefaultItemOpen = "PreferClient"

#Open in the browser 
$list.DefaultItemOpen = "Browser"

#Use the server default (Open in the client application)
$list.DefaultItemOpenUseListSetting = $false

#Custom Send To Destination - Applicable only to Libraries
$list.SendToLocationName = "Record Center"
$list.SendToLocationUrl = "http://recordcenter.crescent.com/archives/2013/"

#enable disable New Folders
$list.EnableFolderCreation = $false

#Search - Allow items from this document library to appear in search results? 
$list.NoCrawl = $true
E-Mail Notification - Send e-mail when ownership is assigned or when an item has been changed. - Applicable only to Task list
# Send e-mail when ownership is assigned?  
$list.EnableAssignToEmail = $true

#Offline Client Availability: Allow items from this document library to be downloaded to offline clients? 
$list.ExcludeFromOfflineClient = $true

#Site Assets Library: Should this document library be a site assets library? 
$list.IsSiteAssetsLibrary = $false

#Datasheet - Allow items in this document library to be edited using the datasheet? 
$list.DisableGridEditing = $true

#Dialogs - Launch forms in a dialog? 
$list.NavigateForFormsPages = $true
Item-level Permissions: Applicable only to Lists!
#Read access
$list.ReadSecurity = 2
#Read all items = 1. Read items that were created by the user = 2

#Create and Edit access
$list.WriteSecurity = 4
#Create and edit all items = 1. Create items and edit items that were created by the user = 2
.None = 4

#Attachments - Applicable only to Lists!
$list.EnableAttachments = $false
Incoming E-mail settings
$list.EnableAssignToEmail = $true
$list.EmailAlias="TravelClaims" #Incoming E-mail Address
$list.rootFolder.Properties["vti_emailusesecurity"] = 0
$list.rootFolder.Properties["vti_emailsaveattachments"] = 1
#Group attachments in folders. "subject"  "sender"  "root"
$list.rootFolder.Properties["vti_emailattachmentfolders"] = "subject"
$list.rootFolder.Properties["vti_emailoverwrite"] = 0
$list.rootFolder.Properties["vti_emailsavemeetings"] = 0
$list.rootFolder.Properties["vti_emailsaveoriginal"] = 1
$List.RootFolder.Update();
RSS Settings
$List.EnableSyndication = $true;
$List.RootFolder.Properties["vti_rss_LimitDescriptionLength"]=0
$List.RootFolder.Properties["vti_rss_DocumentAsEnclosure"] = 0
$List.RootFolder.Properties["vti_rss_DocumentAsLink"] = 1
$List.RootFolder.Properties["vti_rss_ItemLimit "] = 25
$List.RootFolder.Properties["vti_rss_DayLimit"] = 7
$List.RootFolder.Update();
Dont forget to Update the list settings!
$list.Update()


You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Thursday, January 17, 2013

Audit Specific User Permissions in SharePoint 2007 with PowerShell

In continuation with my earlier post: SharePoint Permission Report: Check Access Rights for a Specific User, got few requests to make the PowerShell script compatible with MOSS 2007. Hence, I'm posting the code here. Make sure you are running the script from Farm Admin credentials who has "FULL Control" Policy created on the Web Application!

It checks the following areas of SharePoint and generates a Log file as in the below screen:
  • Farm Administrator's Group
  • Central Administration Web Application Policies
  • Site Collection Administrators 
  • Scans the all Site collections and Sub-sites with Unique Permissions
  • Scans all Lists and Libraries with unique permissions
  • Scans all Groups which has permissions on sites and Lists

PowerShell Script to Check Access Rights for a Particular user all over SharePoint:

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") 


#Get All Web Applications
Function global:Get-SPWebApplication($WebAppURL)
{  
 if($WebAppURL -eq $null)  #Get All Web Applications
    {
  $Farm = [Microsoft.SharePoint.Administration.SPFarm]::Local
  $websvcs = $farm.Services | where -FilterScript {$_.GetType() -eq [Microsoft.SharePoint.Administration.SPWebService]}
  $WebApps = @()
  foreach ($websvc in $websvcs) {
      foreach ($WebApp in $websvc.WebApplications) {
          $WebApps = $WebApps + $WebApp 
      }
  }
  return $WebApps
 }
 else #Get Web Application for given URL
 {
  return [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($WebAppURL)
 }
}

Function global:Get-SPSite($url)
{
 if($url -ne $null)
    {
    return New-Object Microsoft.SharePoint.SPSite($url)
 }
}
 
Function global:Get-SPWeb($url)
{
  $site= Get-SPSite($url)
        if($site -ne $null)
            {
               $web=$site.OpenWeb();
      
            }
    return $web
}

Function GetUserAccessReport($WebAppURL, $SearchUser)
{
 #Get All Site Collections of the WebApp
 $SiteCollections = Get-SPWebApplication($WebAppURL)
 $SiteCollections= $SiteCollections.Sites
 

 #Write CSV- TAB Separated File) Header
 "URL `t Site/List `t Title `t PermissionType `t Permissions" | out-file UserAccessReport.csv

  #Check Whether the Search Users is a Farm Administrator
        $ca= [Microsoft.SharePoint.Administration.SPAdministrationWebApplication]::Local.Sites[0].RootWeb
        #Get Central Admin
    $AdminSite = Get-SPWeb($ca.URL)
    $AdminGroupName = $AdminSite.AssociatedOwnerGroup.Name

    $FarmAdminGroup = $AdminSite.SiteGroups[$AdminGroupName]

     foreach ($user in $FarmAdminGroup.users)
      {
       if($user.LoginName -eq $SearchUser)
    {
     "$($AdminSite.URL) `t Farm `t $($AdminSite.Title)`t Farm Administrator `t Farm Administrator" | Out-File UserAccessReport.csv -Append
    }      
      }

 #Check Web Application Policies
 $WebApp= Get-SPWebApplication $WebAppURL

 foreach ($Policy in $WebApp.Policies) 
   {
   #Check if the search users is member of the group
  if($Policy.UserName -eq $SearchUser)
     {
    #Write-Host $Policy.UserName
     $PolicyRoles=@()
     foreach($Role in $Policy.PolicyRoleBindings)
    {
     $PolicyRoles+= $Role.Name +";"
    }
    #Write-Host "Permissions: " $PolicyRoles
    
    "$($WebAppURL) `t Web Application `t $($AdminSite.Title)`t  Web Application Policy `t $($PolicyRoles)" | Out-File UserAccessReport.csv -Append
   }
   }
  
  
  #Loop through all site collections
   foreach($Site in $SiteCollections) 
    {
   #Check Whether the Search User is a Site Collection Administrator
   foreach($SiteCollAdmin in $Site.RootWeb.SiteAdministrators)
       {
    if($SiteCollAdmin.LoginName -eq $SearchUser)
   {
    "$($Site.RootWeb.Url) `t Site `t $($Site.RootWeb.Title)`t Site Collection Administrator `t Site Collection Administrator" | Out-File UserAccessReport.csv -Append
   }      
  }
  
    #Loop throuh all Sub Sites
       foreach($Web in $Site.AllWebs) 
       { 
   if($Web.HasUniqueRoleAssignments -eq $True)
             {
          #Get all the users granted permissions to the list
             foreach($WebRoleAssignment in $Web.RoleAssignments ) 
                 { 
                   #Is it a User Account?
      if($WebRoleAssignment.Member.userlogin)    
       {
          #Is the current user is the user we search for?
          if($WebRoleAssignment.Member.LoginName -eq $SearchUser)
         {
          #Write-Host  $SearchUser has direct permissions to site $Web.Url
          #Get the Permissions assigned to user
           $WebUserPermissions=@()
             foreach ($RoleDefinition  in $WebRoleAssignment.RoleDefinitionBindings)
             {
                             $WebUserPermissions += $RoleDefinition.Name +";"
                            }
          #write-host "with these permissions: " $WebUserPermissions
          #Send the Data to Log file
          "$($Web.Url) `t Site `t $($Web.Title)`t Direct Permission `t $($WebUserPermissions)" | Out-File UserAccessReport.csv -Append
         }
       }
     #Its a SharePoint Group, So search inside the group and check if the user is member of that group
     else  
      {
                        foreach($user in $WebRoleAssignment.member.users)
                            {
           #Check if the search users is member of the group
         if($user.LoginName -eq $SearchUser)
          {
           #Write-Host  "$SearchUser is Member of " $WebRoleAssignment.Member.Name "Group"
            #Get the Group's Permissions on site
         $WebGroupPermissions=@()
            foreach ($RoleDefinition  in $WebRoleAssignment.RoleDefinitionBindings)
            {
                           $WebGroupPermissions += $RoleDefinition.Name +";"
                           }
         #write-host "Group has these permissions: " $WebGroupPermissions
         
         #Send the Data to Log file
         "$($Web.Url) `t Site `t $($Web.Title)`t Member of $($WebRoleAssignment.Member.Name) Group `t $($WebGroupPermissions)" | Out-File UserAccessReport.csv -Append
        }
       }
      }
                    }
    }
    
    #********  Check Lists with Unique Permissions ********/
              foreach($List in $Web.lists)
              {
                  if($List.HasUniqueRoleAssignments -eq $True -and ($List.Hidden -eq $false))
                  {
                     #Get all the users granted permissions to the list
                foreach($ListRoleAssignment in $List.RoleAssignments ) 
                    { 
                      #Is it a User Account?
         if($ListRoleAssignment.Member.userlogin)    
          {
             #Is the current user is the user we search for?
             if($ListRoleAssignment.Member.LoginName -eq $SearchUser)
            {
             #Write-Host  $SearchUser has direct permissions to List ($List.ParentWeb.Url)/($List.RootFolder.Url)
             #Get the Permissions assigned to user
              $ListUserPermissions=@()
                foreach ($RoleDefinition  in $ListRoleAssignment.RoleDefinitionBindings)
                {
                                $ListUserPermissions += $RoleDefinition.Name +";"
                               }
             #write-host "with these permissions: " $ListUserPermissions
             
             #Send the Data to Log file
             "$($List.ParentWeb.Url)/$($List.RootFolder.Url) `t List `t $($List.Title)`t Direct Permissions `t $($ListUserPermissions)" | Out-File UserAccessReport.csv -Append
            }
          }
          #Its a SharePoint Group, So search inside the group and check if the user is member of that group
         else  
          {
                             foreach($user in $ListRoleAssignment.member.users)
                                 {
              if($user.LoginName -eq $SearchUser)
               {
                #Write-Host  "$SearchUser is Member of " $ListRoleAssignment.Member.Name "Group"
                 #Get the Group's Permissions on site
              $ListGroupPermissions=@()
                 foreach ($RoleDefinition  in $ListRoleAssignment.RoleDefinitionBindings)
                 {
                                $ListGroupPermissions += $RoleDefinition.Name +";"
                                }
              #write-host "Group has these permissions: " $ListGroupPermissions
              
              #Send the Data to Log file
              "$($Web.Url) `t Site `t $($List.Title)`t Member of $($ListRoleAssignment.Member.Name) Group `t $($ListGroupPermissions)" | Out-File UserAccessReport.csv -Append
             }
            }
         } 
                       }
                }
              }
    } 
   }
     
  }

#Call the function to Check User Access
GetUserAccessReport "http://SharePoint.company.com" "Domain\User"

and the Output in Excel:
Audit & Permissions Report for a particular user Access in SharePoint


You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


SharePoint Versioning Manager - Control Versioning Settings & Clean Up Old Versions

We have document libraries with unlimited versioning enabled for years. As part of regular auditing Version History Size Report for Entire SharePoint Web Application , found many documents have more than 100 versions!  In order to free up more database storage space and for better performance, We understand that we'll have to disable or limit versions.

Although, versions are very useful to track changes, each of the versions is a copy of the document and takes up a disk space (Till SharePoint 2010, BTW). As per Microsoft design changing versioning limits will not delete existing minor/major versions of the file until we update it.

Its a best practice to limit versions. You can Navigate to Document Library Settings >> Version Settings >> and set versioning limits, set versioning ON/OFF in SharePoint versioning settings page. But this will not have any effect on existing documents until you make edits on the document and update. (You can Check-out and check-in them back as a Shortcut). Also its not possible to get into each document library and set these settings manually, isn't it? As there were thousands of files in the document library I would like to programmatically approach the change to simply get rid of the old versions across the site and regain space.

PowerShell can Set Versioning Limits and Cleanup Old Versions:
All of these issues can resolved with a powershell script which does clean up of old versions in SharePoint library by looping through all the site collections, webs, lists and items. From each item it checks the versions and delete. Take a look at my post: Limit and Cleanup Versioning in SharePoint with PowerShell
SharePoint SharePoint doesn't enable versioning by default!
However, not all SharePoint guys are good at PowerShell scripting (You must be good at PowerShell, SharePoint Admins!) and obviously its easy to make disaster if you are novice! So, would like to have a GUI based SharePoint utility to fix versioning of document libraries.

SharePoint Versioning Manager Utility to Set Limits and Cleanup Old Versions
I've created a SharePoint tool using C# object model, which gives the functionality to manage document versions and  programmatically remove extraneous versions either for a selected list or library or of all lists and libraries in a SharePoint site. It takes parameters such as:
  • Site collection URL, Site
  • List/Library (or All List & Libraries)
  • Define Version limits (No. of major versions / No. of minor versions to keep)
  • Turn OFF/Turn ON versioning for selected or all lists/libraries.
and perform desired operations. Here are some screen shots of SharePoint Versioning Manager in action.
This utility is built on SharePoint server object model and must be running from SharePoint Web Front End Servers! Not from your desktop!!
Get Versioning Analysis of all document libraries and lists:
Tool to Analyze sharepoint versioning Settings
Analyze Versionings of a Selected Library:Reduce sharepoint versioning to get storage space
Set Versioning Limit and Cleanup for a Selected Library:
SharePoint Versioning Manager - Control and Clean Up Old Versions Set the versioning limits either for selected list/library or for entire site.
Tool to Trim and Cleanup SharePoint Versions
 In a Project collaboration environment, with this utility, We had a doc library setup with versioning 5 major and 5 minor. we recovered about to 28 GB of free space!

Download: SharePoint Versioning Manager from CodePlex

Versioning Manager for SharePoint 2013 released at: https://versioningmanager.codeplex.com/releases/view/612871

As always, I see there are room for enhancements to the tool, will update and release a new version as and when time allows!

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


MOSS 2007 List Toolbar in SharePoint 2010

After migrating from MOSS 2007 to SharePoint 2010, some users still face difficulty with SharePoint 2010 interface, especially ribbon. What they are asking for is: List toolbar is missing! We need MOSS 2007 style list view toolbar!!

As SharePoint 2010 list toolbar integrated with ribbon, SharePoint doesn't show list toolbar separately, by default.
sharepoint 2010 list toolbar

However, we can just tweak this settings to show SharePoint 2010 list view toolbar as in SharePoint 2007. Here is how:


Go to Site Actions >> Edit Page >> Modify List View Web Part
sharepoint 2010 list view show toolbar

Set list view toolbar type  from "Full Toolbar" to "Show Toolbar"
sharepoint 2010 list view toolbar type

That's all. See the toolbar appears on list!

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Monday, January 14, 2013

User's Account Name Changed in Active Directory. How to Sync it in SharePoint?

We had a user account in Active Directory: EU\susanapi. Later there was a change in User name. It become: EU\suzanapi. But even after several user profile imports, the old user name: EU\susanapi was still showing up in SharePoint, and SharePoint treated the new user account as a separate account.

What is the Fix?
Unfortunately, Sharepoint doesn't understand this change automatically. We need to make it understand by giving instruction via STSADM command.

When user's Account Name (or Login Name: Domain\User) renamed in Active Directory, you have to use stsadm -o migrateuser command to associate the new AD account with an existing SharePoint profile.

stsadm -o migrateuser -oldlogin EU\susanapi -newlogin EU\suzanapi -ignoresidhistory

PowerShell cmdlet to migrate user: Move-SPUser –Identity "DOMAIN\OldUserName" –NewAlias "Domain\NewUserName"

Before the Fix:

After the Fix:
I had to do the same thing When users left the company, their accounts are deleted in AD (But their profiles are not deleted in SharePoint). After some time they came back! New AD-Account created and I just used the "MigrateUser" command to associate the new account with their existing user profile.

By this, All their profile Data, Security Settings, Tasks assigned and My Site are associated back with the users.  This procedure also applies when we migrate users from other domains. (or during domain Renames!) KB: http://support.microsoft.com/kb/953131

BTW, If its for any other properties like Display Name, First Name, Last Name, etc, Profile imports should sync it back with SharePoint. If you need the change urgently either you can trigger the Profile import on-demand or you can update the user property by SPUser.Property=something or with PowerShell Set-SPUser.

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Get SharePoint Library Size with PowerShell

SharePoint 2010 document library sizes can be easily retrieved via Storage metrics: Site Actions >> Site Settings >> Storage Metrics if you have SP1 installed.
sharepoint get document library size

You can get SharePoint library size, ONLY when you have Quotas applied to the site collection. otherwise, you get "The storage space allocation page cannot be used for sites that do not have a storage quota defined." error message in MOSS 2007.
The storage space allocation page cannot be used for sites that do not have a storage quota defined

How to find a particular document library's size in SharePoint programmatically?
Lets see the PowerShell approaches to find SharePoint 2007/SharePoint 2010 document library size, picture library size or for any other libraries.

Approach 1: Using StorageManagementInformation API:
It retrieves storage management information about the site collection. More info on StorageManagementInformation , It takes these parameters:

1. ltVar: Which object
        List = 1
        DocumentLibrary = 2
        Document = 3
2. sordVar: sort order
        Increasing = 0×10
        Decreasing = 0×11
3. soVar: Sort based on size or date
        Size=0
        Date = 1
4. nMaxResults: number of results to return

Lets get the size of the "Shared Documents" Library with PowerShell:
#SharePoint library size report
#Get the Site collection
$Site = Get-SPsite "http://sharepoint.crescent.com"

#Returns a DataTable similar to "Storage Management Page" in Site settings
$DataTable = $Site.StorageManagementInformation(2,0x11,0,0)

#Loop through the Rows and Fetch the row matching "Shared Documents" in subsite "team"
 foreach($Row in $DataTable.Rows)
{
    if ($Row.Title -eq "Shared Documents" -and $Row.Directory -eq "team")
        {
            $LibrarySize = [Math]::Round(($Row.Size/1MB),2)
            Write-Host $LibrarySize "MB"
        }
} 

You can retrieve Top 10 large libraries based on their size as:
#Get the Site collection
$Site = Get-SPsite "http://sharepoint.crescent.com"

#Returns a DataTable similar to "Storage Management Page" in Site settings
$DataTable = $Site.StorageManagementInformation(2,0x11,0,10)

$DataTable | Select Title, ItemCount, Size, Directory | Format-Table
and the output:
However MSDN says this API is obsolete. So lets try with an alternate approach. Found this Article in MSDN on getting the storage information through object model.

Approach 2: Iterate through each document and its versions stored in the library to calculate the library size:
Lets use PowerShell to iterate each folder & sub-folder of a particular document library. This script can be used in MOSS 2007 or SharePoint 2010 get library size.
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

# Function to calculate Library size
Function GetLibrarySize($Folder)
{
    $FolderSize = 0
    foreach ($File in $Folder.Files)
    {
        #Get File Size
        $FolderSize += $File.TotalLength;

        #Get the Versions Size
        foreach ($FileVersion in $File.Versions)
        {
            $FolderSize += $FileVersion.Size
        }
    }

      #Get Files in Sub Folders
        foreach ($SubFolder in $Folder.SubFolders)
        {
           if($SubFolder.Name -ne "Forms") #Leave "Forms" Folder which has List default Aspx Pages.
             {
                 $FolderSize += GetLibrarySize($SubFolder)
             }
        }

       return [Math]::Round(($FolderSize/1MB),2)
}

$Web = Get-SPWeb "http://sharepoint.crescent.com/team/"

#Get the Library's Root Folder
$Library =  $Web.Lists["Shared Documents"].RootFolder

#Call the function to Calculate Size
$LibrarySize=GetLibrarySize($Library)

Write-Host "Library Size:" $LibrarySize "MB"



You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Wednesday, January 9, 2013

Customized Master Pages Report for All SharePoint Sites

Today, wanted to audit customized Master pages which are deviating from our corporate Branding in my Team Sites environment.

Generated the report for customized master pages with help of PowerShell.

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

#Get all site collections of provided web app
$SiteCollections = Get-SPWebApplication "http://sharepoint.crescent.com" | Get-SPSite -Limit All

#Loop through all site collections
   foreach($Site in $SiteCollections)
    {
        #Loop throuh all Sub Sites
       foreach($Web in $Site.AllWebs)
       {    
          #Get the Master Page
          $MasterPage = $Web.GetFile($Web.URL+"/"+$Web.MasterUrl)
          
          #Check the Customization Status
          if($MasterPage.CustomizedPageStatus -eq "Customized")
           {
               $MasterPage.Name  +" : " +$Web.Url  
           }
       }

    }

If you want to use it in MOSS 2007, use these two lines of code to get a specific web application:
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
$webApp = [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup("http://sharepoint.crescent.com")

Here is the One Liner:
Get-SPWebApplication "http://sharepoint.crescent.com" | Get-SPSite -Limit All | Get-SPWeb -Limit All | Select Title, URL, MasterUrl

Frankly, SharePoint Designer is a tool inducing people to get their site's look and feel just as they want. I blame you SharePoint Designer for that. I've no options left other than locking you down from ordinary users.

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Tuesday, January 8, 2013

SharePoint 2010 Permission Report: Check Access Rights for a Specific User

Update: This script has been updated to scan Folders and List Items with Claims support at: SharePoint User Permission Analysis & Reporting using PowerShell
Requirement: To ensure security, generate permissions report on all locations like (sites, lists, etc.) where a specific user has permissions.

When people moving from one role to another, Its necessary to audit their permissions on sites and lists where user has access rights. But unfortunately, There is no out of the box ways to find all sites and lists where a particular user has been granted access in SharePoint with out using third party tools. Luckily, We've PowerShell! Lets find all SharePoint sites and lists where a particular user has access rights.

PowerShell Script to Check and Generate Report on Access Rights for a Specific User:
With this script, you can analyze and track the security effectively check what permissions on an account has been granted on each all places in SharePoint. This PowerShell script scans these areas to to retrieve a specific user's access rights:
  • Farm Administrator's Group
  • Central Administration Web Application Policies
  • Site Collection Administrators 
  • Scans the all Site collections and Sub-sites with Unique Permissions
  • Scans all Lists and Libraries with unique permissions
  • Scans all Groups which has permissions on sites and Lists
After executing the script, it generates a CSV file (Tab Separated, In fact!) with details: URL, Site/List, Title, Permission Type, Permissions as in the below screenshot.
SharePoint Permission Report: Check Access Rights for a Specific User

We want to track How many Sites user has permissions, How many Lists or Libraries user has explicitly added and so on based on business needs.

PowerShell Script to Retrieve User Access Rights Across web application:
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
 
Function GetUserAccessReport($WebAppURL, $SearchUser)
{

    #Output Report location
    $OutputReport = "C:\Scripts\UserAccessReport.csv"
    #delete the file, If already exist!
    if (Test-Path $OutputReport)
     {
        Remove-Item $OutputReport
     }

Write-host "Scanning Farm Administrator Group..." 

#Write CSV- TAB Separated File) Header
"URL `t Site/List `t Title `t PermissionType `t Permissions" | out-file $OutputReport
 
  ####Check Whether the Search Users is a Farm Administrator ###
  #Get the SharePoint Central Administration site
  $AdminWebApp= Get-SPwebapplication -includecentraladministration | where {$_.IsAdministrationWebApplication}
    $AdminSite = Get-SPweb($AdminWebApp.Url)
    $AdminGroupName = $AdminSite.AssociatedOwnerGroup
    $FarmAdminGroup = $AdminSite.SiteGroups[$AdminGroupName]
 
 #enumerate in farm adminidtrators groups
    foreach ($user in $FarmAdminGroup.users)
    {
     if($user.LoginName -eq $SearchUser)
     {
       "$($AdminWebApp.URL) `t Farm `t $($AdminSite.Title)`t Farm Administrator `t Farm Administrator" | Out-File $OutputReport -Append
     }     
    }
 
Write-host "Scanning Web Application Policies..." 

 ### Check Web Application Policies ###
  $WebApp= Get-SPWebApplication $WebAppURL
 
  foreach ($Policy in $WebApp.Policies)
  {
      #Check if the search users is member of the group
     if($Policy.UserName -eq $SearchUser)
       {
       #Write-Host $Policy.UserName
        $PolicyRoles=@()
       foreach($Role in $Policy.PolicyRoleBindings)
       {
        $PolicyRoles+= $Role.Name +";"
       }
       #Write-Host "Permissions: " $PolicyRoles
      "$($AdminWebApp.URL) `t Web Application `t $($AdminSite.Title)`t  Web Application Policy `t $($PolicyRoles)" | Out-File $OutputReport -Append
   }
  }

 Write-host "Scanning Site Collections..." 
 #Get All Site Collections of the WebApp
 $SiteCollections = Get-SPSite -WebApplication $WebAppURL -Limit All
    
  #Loop through all site collections
   foreach($Site in $SiteCollections)
    {
     Write-host "Scanning Site Collection:" $site.Url
     #Check Whether the Search User is a Site Collection Administrator
     foreach($SiteCollAdmin in $Site.RootWeb.SiteAdministrators)
        {
      if($SiteCollAdmin.LoginName -eq $SearchUser)
      {
       "$($Site.RootWeb.Url) `t Site `t $($Site.RootWeb.Title)`t Site Collection Administrator `t Site Collection Administrator" | Out-File $OutputReport -Append
      }     
    }
   
     #Loop throuh all Sub Sites
  foreach($Web in $Site.AllWebs)
  {
      if($Web.HasUniqueRoleAssignments -eq $True)
            {
             Write-host "Scanning Site:" $Web.Url
    
            #Get all the users granted permissions to the list
              foreach($WebRoleAssignment in $Web.RoleAssignments )
    {
                 #Is it a User Account?
          if($WebRoleAssignment.Member.userlogin)   
           {
              #Is the current user is the user we search for?
              if($WebRoleAssignment.Member.LoginName -eq $SearchUser)
             {
               #Write-Host  $SearchUser has direct permissions to site $Web.Url
               #Get the Permissions assigned to user
       $WebUserPermissions=@()
                foreach ($RoleDefinition  in $WebRoleAssignment.RoleDefinitionBindings)
                {
                 $WebUserPermissions += $RoleDefinition.Name +";"
                }
               #write-host "with these permissions: " $WebUserPermissions
          
         #Send the Data to Log file
               "$($Web.Url) `t Site `t $($Web.Title)`t Direct Permission `t $($WebUserPermissions)" | Out-File $OutputReport -Append
             }
           }
        #Its a SharePoint Group, So search inside the group and check if the user is member of that group
         else 
          {
                        foreach($user in $WebRoleAssignment.member.users)
                            {
                #Check if the search users is member of the group
               if($user.LoginName -eq $SearchUser)
                {
                  #Write-Host  "$SearchUser is Member of " $WebRoleAssignment.Member.Name "Group"
                  #Get the Group's Permissions on site
                $WebGroupPermissions=@()
                  foreach ($RoleDefinition  in $WebRoleAssignment.RoleDefinitionBindings)
                  {
                      $WebGroupPermissions += $RoleDefinition.Name +";"
                     }
                #write-host "Group has these permissions: " $WebGroupPermissions
               
               #Send the Data to Log file
               "$($Web.Url) `t Site `t $($Web.Title)`t Member of $($WebRoleAssignment.Member.Name) Group `t $($WebGroupPermissions)" | Out-File $OutputReport -Append
              }
             }
     }
    }
      } 
     
    ###*****  Check Lists with Unique Permissions *******###
   foreach($List in $Web.lists)
   {
             if($List.HasUniqueRoleAssignments -eq $True -and ($List.Hidden -eq $false))
                {
                 Write-host "Scanning List:" $List.RootFolder.Url
                    #Get all the users granted permissions to the list
     foreach($ListRoleAssignment in $List.RoleAssignments )
                    {
                     #Is it a User Account?
             if($ListRoleAssignment.Member.userlogin)   
              {
                 #Is the current user is the user we search for?
                 if($ListRoleAssignment.Member.LoginName -eq $SearchUser)
                {
                  #Write-Host  $SearchUser has direct permissions to List ($List.ParentWeb.Url)/($List.RootFolder.Url)
                  #Get the Permissions assigned to user
                   $ListUserPermissions=@()
                    foreach ($RoleDefinition  in $ListRoleAssignment.RoleDefinitionBindings)
                    {
                                 $ListUserPermissions += $RoleDefinition.Name +";"
                                }
                  #write-host "with these permissions: " $ListUserPermissions
              
                  #Send the Data to Log file
                  "$($List.ParentWeb.Url)/$($List.RootFolder.Url) `t List `t $($List.Title)`t Direct Permissions `t $($ListUserPermissions)" | Out-File $OutputReport -Append
                }
              }
              #Its a SharePoint Group, So search inside the group and check if the user is member of that group
             else 
              {
       foreach($user in $ListRoleAssignment.member.users)
       {
                   if($user.LoginName -eq $SearchUser)
                    {
                     #Write-Host  "$SearchUser is Member of " $ListRoleAssignment.Member.Name "Group"
                      #Get the Group's Permissions on site
                    $ListGroupPermissions=@()
                      foreach ($RoleDefinition  in $ListRoleAssignment.RoleDefinitionBindings)
                      {
                                  $ListGroupPermissions += $RoleDefinition.Name +";"
                                 }
                    #write-host "Group has these permissions: " $ListGroupPermissions
               
                    #Send the Data to Log file
                    "$($Web.Url) `t Site `t $($List.Title)`t Member of $($ListRoleAssignment.Member.Name) Group `t $($ListGroupPermissions)" | Out-File $OutputReport -Append
                  }
                }
             }
                    }
                }
            }
     }
 }
     
 Write-host "`n Access Rights Report Generated!" 
 }
 

#Call the function to Check User Access
GetUserAccessReport "http://sharepoint.crescent.com" "i:0#.w|Global\Salaudeen"

You can Download the complete PowerShell Script from MSDN Code Gallery: SharePoint Permission Report: Check Access Rights for a Specific User

Limitation: Currently, it doesn't count on active directory groups! Say, for e.g. an active directory security group may include the user you are searching for and that group may be granted with access rights. Also, it doesn't go til folder, list Item level. it stops at List.

Huh, another nifty script under my SharePoint Admin tool belt!

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Monday, January 7, 2013

Activate button Disabled in SharePoint Sandboxed Solutions

Developers reported an issue in a New SharePoint 2010 Environment: When they try to activate sandboxed solutions "Activate" button is disabled (greyed out)! This is because: By default, sandboxed solutions are disabled in SharePoint.
activate sandbox solution disabled
Confirmed, SharePoint 2010 activate sandbox solution disabled. Confirmed user has enough permissions (User needs to be a site collection administrator or with Full Control permission at the root site collection, to deploy and activate sandboxed solution), logged in to the server and found "SharePoint 2010 User Code Host" is disabled from Services console.
sharepoint 2010 sandboxed solution activate disabled
Solution: 
Enable Sandboxed solution by starting "Microsoft SharePoint Foundation Sandboxed Code Service"!

Go to Central Administration >> System Settings >> Manage Services on Server, start "Microsoft SharePoint Foundation Sandboxed Code Service".
sharepoint cannot activate sandboxed solution

Microsoft SharePoint Foundation Sandboxed Code Service can be stared with PowerShell:
Start-Service -Name SPUserCodeV4

Now, you will be able to upload & activate sandbox solutions!

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Change Site Collection Primary, Secondary Administrators in SharePoint

Site collection administrators have god like power within a site collection, They can add/delete sites, content, users, etc for any site within a site collection.

Change site collection administrator in SharePoint 2010: In SharePoint 2010 primary, secondary site collection administrators are set from Central Administration >> Application Management >> Change site collection administrators under Site Collection.
sharepoint 2010 change primary, secondary site collection administrator

How to change site collection administrator in SharePoint 2007 / SharePoint 2010 using STSADM:
To change primary site owner, secondary site owner in MOSS 2007, we use stsadm with siteowner switch.
stsadm -o siteowner -url https://my.crescent.com/personal/crescent_markh -ownerlogin domain\user -secondarylogin global\salaudeen"

You can find site collection Primary and Secondary administrators under site collection administrators group (Site Actions >> Site Settings >> Site collection administrators) along with other site collection administrators. But Primary and Secondary Administrators are the only users who receive e-mail notifications for events, such as the quota reached, Site usage confirmation, etc.

Set site collection administrator in SharePoint programmatically:
To change primary administrator in SharePoint site with object model code C#:
String PrimaryOwner="Global\Salaudeen";
SPSite oSpSite = new SPSite(URL);
SPWeb oSPWeb = oSpSite.OpenWeb();
oSpSite.Owner = oSPWeb.EnsureUser(PrimaryOwner);
//oSpSite.SecondaryContact = oSPWeb.EnsureUser(SecondaryOwner);
This code sets SharePoint primary site collection administrator

Change site collection administrator in SharePoint 2010 using PowerShell:
In SharePoint 2010 onwards PowerShell cmdlets makes it much simpler:
To get Primary and Secondary Site collection Administrators:
Get-SPSite -Limit all | Select URL, Owner, SecondaryContact | Out-Gridview

Similarly, to set Site collection Primary and secondary owners, we can use the powershell cmdlet: Set-SPSite
Set-SpSite "http://sharepoint.crescent.com" -owneralias "domain\user" -SecondaryOwnerAlias "<domain\user>"

Change site collection administrators for all site collections
We can just pipe them together to set site collection primary and secondary administrators for all sites in a web application

Get-SPWebApplication "http://intranet.crescent.com" | Get-SPSite -Limit All | ForEach-Object { Set-SPSite $_ -OwnerAlias "<domain\user>" -SecondaryOwnerAlias "<domain\user>" }

This will change SharePoint 2010 primary site collection administrator and secondary site collection administrator. Related Post: Add Site Collection Administrators Programmatically in SharePoint

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Friday, January 4, 2013

The terminal server has exceeded the maximum number of allowed connections - Solution

When trying to take a Remote desktop on Windows Servers, got the error message "The terminal server has exceeded the maximum number of allowed connections".

Root Cause: 
This is because, Windows 2003 Server supports only two active RDP connections. When you try as third, you may experience this issue. Ideally, user must "Log Off" to end-up the session rather disconnect.
The terminal server has exceeded the maximum number of allowed connections
Just closing the remote desktop window disconnects the user but it keeps the session active. Next time when user tries to login,  he gets the error message.

Solution:
Alright, what is the workaround to by pass this error and login to Windows Server 2003 or Windows Server 2008? Go to command line, or Run dialog box. If you are running remote desktop from Windows Server 2003 or Windows XP, enter: MSTSC /v: <MachineName or IP> /f -console

E.g. MSTSC /v:SPSrv01 /f -console

For Windows 2008/Windows 7, use: mstsc /v:SPSrv01 /f /admin

Now, you should be able to login to the server and logoff disconnected user sessions from Task Manager. For some reason, if the above methods didn't work, use the alternate: force log-off uses sessions. Here is how:
  1. Query the active user sessions to find who is logged in: query session /server:servername
  2. Terminate the user session by: Reset session [Session ID] /server:servername
This kills the session.

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Thursday, January 3, 2013

Import User Pictures from Active Directory to SharePoint 2010 My Site

My Organization decided to use Active Directory as a central repository for user profile photos to share with Lync 2010, Outlook and of course SharePoint!

Lets keep other products aside and talk about How to Import User Pictures from Active Directory to SharePoint 2010 My Site. Here is the default My site Profile page without Profile photo imported from AD:
import user pictures from active directory to sharepoint 2010

Well, this article addresses import user pictures from active directory to SharePoint 2010 step by step:
  1. Import user photo into Active Directory user profile's "thumbnailPhoto" attribute.
  2. Configure Property mapping between SharePoint and Active Directory and Run FULL Profile Import.
  3. Run Update-SPProfilePhotoStore cmdlet to generate thumbnails for SharePoint user profile picture.
Assuming UPS is in place, My Site is up and running, SharePoint 2010 SP1 is installed (or October 2010 Cumulative Update), Lets get into details.

Step 1: Import user photo into Active Directory user profile's "thumbnailPhoto" attribute.
If profile pictures are not already in Active Directory user profile's "thumbnailPhoto" attribute, We can import pictures into it. For SharePoint 2010 to import user photo from ad, it must have this attribute populated.
import photo from ad sharepoint 2010

Yes, there are 3rd party tools like AD Photo Edit to import user profile thumbnail photos in bulk,  PowerShell can do it well with just three lines!
Import-Module ActiveDirectory

$photo=[byte[]](Get-Content .\salaudeen_photo.jpg -Encoding byte)

Set-ADUser "Salaudeen" -Replace @{thumbnailPhoto=$photo}

PowerShell Script to Bulk Import User Profile Photos into AD:
Lets say, we've lot of users in AD and their user name, Profile Photo file names are stored in a CSV file with columns "UserName", "PhotoFileName". We can utilize PowerShell to import photo to AD in bulk.

#Read the CSV file - Map the Columns to Named Header (CSV File doesn't has Column Header)
$CSVData = Import-CSV -path "C:\Scripts\UpdateProfilePhoto\UserPhotos.csv" -Header("UserName", "PhotoFileName")

 #Iterate through each Row in the CSV
 foreach ($row in $CSVData)
   {
        #Get the User Name & Photos from CSV file
        $userName= $row.UserName
        $PhotoFile = Join-path "C:\Scripts\UpdateProfilePhoto" $row.PhotoFileName
        
        #Get the User from AD
        $domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
        $root = $domain.GetDirectoryEntry()
        $search = [System.DirectoryServices.DirectorySearcher]$root
        $search.Filter = "(&(objectCategory=User)(samAccountName=$userName))"
        $result = $search.FindOne()
         
        if ($result -ne $null)
        {
            #Get the User Object
            $user = $result.GetDirectoryEntry()
            
            #Get the Photo from Disk
            $photo=[byte[]](Get-Content $PhotoFile -Encoding byte)
           
            #Update User Profile Photo
            $user.put("thumbnailPhoto",  $photo )
            $user.setinfo()
            
            Write-Host $user.displayname " Photo has been updated."
        }
        
    }
Once imported, You can find the "thumbnailPhoto" property updated in AD User's properties.
import pictures from active directory to sharepoint 2010
BTW, User profile picture can be from any where! Not just AD, but any File Server, SharePoint Library, etc. So you can proceed by setting up a ProfileURL mapping and execute below steps.

Step 2: Configure Property mapping between SharePoint and Active Directory and Run FULL Profile Import.
Once user profile pictures are imported to Active directory, the next step is to make SharePoint aware of the Property by creating a Property Mapping. Go to:
  • Central Administration >> Manager Service Application
  • Click on "Manage" on User Profile Service Application
  • Click on "Manage User Properties"
  • Edit the "Picture" property
    import user profile photos from active directory into sharepoint 2010
  • We don't want users to override the photo from AD. So select "Do not allow users to edit value for this property" option
    import ad photos into sharepoint 2010
  • Specify the User Profile Connection, Attribute as "thumbnailPhoto" and direction as "Import"
    sharepoint 2010 import picture from active directory
  • click "Add" button and then "OK".
So, we've done mapping the AD property thumbnailPhoto with SharePoint via “PictureURL” User Profile property.

Trigger FULL User Profile Synchronization 
Since UPS didn’t know about this field previously, We've to Run FULL user profile sync. From User Profile Service Application, click on "Start Profile Synchronization" >> Select "Start Full" >> Click "OK" button.
 import pictures from active directory to sharepoint
wait for the user profile Synchronization to complete, and then proceed to next step. So now, we've import user profile photos from active directory into SharePoint 2010.

Step 3: Run Update-SPProfilePhotoStore cmdlet to generate thumbnails for SharePoint user profile picture.
SharePoint 2010 requires the thumbnails to be within 10kb size of 32x32, 96x96, 144x144 px resolutions. So, We've to instruct SharePoint to generate the image thumbnails and re-configure user profiles to reference the thumbnail.

PowerShell Script to create thumbnails in the right sizes and maps the images to the user profiles:
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

Update-SPProfilePhotoStore -CreateThumbnailsForImportedPhotos 1 -MySiteHostLocation  http://<My Site Host Web App URL> 
Make sure You have Administrator access and "FULL" control Permissions on User Profile Service Application.  Otherwise, You will get "Update-SPProfilePhotoStore: Object reference not set to an instance of an object." Error!
sharepoint 2010 import photo from active directory
In some cases, It’s also important to note that you must be a site collection administrator of the ‘My Site Host’, and also have administrative access to the SQL Databases. On successful execution, SharePoint 2010 Stores user profile pictures under My site Host's, "User Photos" library. E.g. http://mysite.crescent.com/User%20Photos

If you don't see Thumbnail photos appear even after full synchronization, One cause could be: You'll have to enable "CrossDomainPhotosEnabled" property of the web application to "True"
 $WebApp = Get-SPWebApplication http://intranet.crescent.com
 $WebApp.CrossDomainPhotosEnabled = $true
 $WebApp.Update()


Verify the Result: Navigate to My site Personal profile (person.aspx) page and verify the new photo. Same Procedure applies to SharePoint 2013 also.
sharepoint 2010 import user photo from ad
Remember, SharePoint search will still show you the old photo until the next incremental search crawl takes place on the content source with your sps3:// provider mapped!

On Going Maintenance: Once AD Profile photo is updated down the line, SharePoint 2010 user profile synchronization will pick the photo. But still we've to make the photo ready for SharePoint by executing Update-SPProfilePhotoStore cmdlet on schedule basis.

So, Its a good idea to schedule a script in Windows Task scheduler to run Update-spprofilephotostore cmdlet after completing FULL profile import. Say, You have the script in a file "SPProfilePhotoStore.ps1" under "D:\Scripts".  Schedule a PowerShell script in Windows task Scheduler and enter "c:\windows\system32\WindowsPowerShell\v1.0\powershell.exe "& 'D:\Scripts\Update-SPProfilePhotoStore.ps1'" in Program to execute.

 or in arguments box, you can directly enter: -NonInteractive -NoProfile -Command "& {Add-PSSnapin Microsoft.SharePoint.PowerShell;Update-SPProfilePhotoStore -MySiteHostLocation https://<My site Host URL> -CreateThumbnailsForImportedPhotos 1}"


You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


You might also like:

Related Posts Plugin for WordPress, Blogger...