Wednesday, August 26, 2020

Importance of "Everyone", "NT Authority\Authenticated Users", "Active Users" in the site collections

 Hi folks,

I've gone through an issue user is not able to create a new page even if all the mandatory fields belonging to the page are filled.

Actually, there are some fields of type "Managed Metadata" who value got wiped off till the page is checked in or metadata is saved.

On troubleshooting, I got to know that the permissions of hidden list (TaxonomyHiddenList) for managed terms got broken. As I deleted "Everyone" at site collection level, it is removed from every where. Hence, managed terms are not accessible and whenever user is trying to check-in the page an error of - "You must fill out all the required properties before completing this action."


I navigated to "TaxonomyHiddenList" and granted 'Everyone' group read permissions to the list.


Thanks,

Kunal

Monday, May 25, 2020

Console application to read all the sites used in last 6 months

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Data;
using System.Globalization;
using System.Threading.Tasks;
using System.Collections;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Client;

namespace RecentUsedSites
{
    
    public static class Program
    {
        

        public static DataTable table = new DataTable();
        

        static void Main(string[] args)
        {
            
            List<string> Sites;
            table.Columns.Add("Site Title");
            table.Columns.Add("Site Url");
            table.Columns.Add("List Title");
            table.Columns.Add("List Item Title");
            table.Columns.Add("List Item Modified");
            using (var reader = new StreamReader(@"D:\Kunal\Global Investors\Automation\RecentUsedSites\RecentUsedSites\Data\Sites.csv"))
            {
                Sites = new List<string>();
                
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();
                    var values = line.Split(';');
                    Console.WriteLine(values[0]);
                    Sites.Add(values[0]);                    
                }
                Sites.RemoveAt(0);
            }

            foreach (var _siteUrl in Sites) 
            {
                string _userName = @"<Username>";
                string _passWord = "<Password>";
                GetAllSubWebs(_siteUrl, _userName, _passWord);
            }

            ToCSV(table, @"D:\Kunal\Global Investors\Automation\RecentUsedSites\RecentUsedSites\Reports\Results.csv");
            
            
            
            //Console.WriteLine("Enter your password");
            //_passWord = Console.ReadLine();
            
            Console.Read();
        }
        public static int GetMonthDifference(DateTime startDate, DateTime endDate)
        {
            int monthsApart = 12 * (startDate.Year - endDate.Year) + startDate.Month - endDate.Month;
            return Math.Abs(monthsApart);
        }
        public static void GetAllSubWebs(string path, string username, string password)
        {
            try 
            {
                using (ClientContext context = new ClientContext(path))
                {
                    context.Credentials = new NetworkCredential(username, password);
                    Web _web = context.Web;
                    context.Load(_web, website => website.Webs, website => website.Title, website => website.Url);
                    context.ExecuteQuery();
                    Console.WriteLine("Site is " + _web.Title);
                    Console.WriteLine("---------------------------------------------------------------------------------");
                    ListCollection _lists = _web.Lists;
                    context.Load(_lists);
                    context.ExecuteQuery();

                    foreach (List list in _lists)
                    {
                        CamlQuery query = new CamlQuery();
                        context.Load(list);
                        context.ExecuteQuery();
                        Console.WriteLine("List is " + list.Title + " with Item Count is " + list.ItemCount);
                        CamlQuery camlQuery = new CamlQuery();
                        camlQuery.ViewXml = "<View><Query><OrderBy><FieldRef Ascending='False' Name='ID'/></OrderBy></Query><RowLimit>1</RowLimit></View>";
                        ListItemCollection lastItems = list.GetItems(camlQuery);
                        context.Load(lastItems, it => it.Include(item => item["ID"], item => item.Id));
                        context.ExecuteQuery();

                        int maxId = 0;
                        foreach (ListItem Item in lastItems)
                        {
                            //Console.WriteLine("Max ID:"+Item.Id);
                            maxId = Item.Id;
                        }

                        int lastId = 0;

                        while (lastId <= maxId)
                        {
                            query.ViewXml = "<View Scope='Recursive'><Query><Where><Gt><FieldRef Name='ID'/>" + "<Value Type='Number'>" +
                                            lastId + "</Value></Gt></Where></Query><RowLimit>1000</RowLimit></View>";

                            ListItemCollection items = list.GetItems(query);
                            context.Load(items);
                            context.ExecuteQuery();

                            if (items.Count == 0)
                            {
                                break;
                            }
                            foreach (ListItem item in items)
                            {
                                var parameterDate = (DateTime)item["Modified"];



                                DateTime today = DateTime.Now;



                                int monthDiff = GetMonthDifference(today, parameterDate);


                                if (monthDiff < 6)
                                {
                                    Console.WriteLine("ITEM TITLE " + item["Title"] + " ITEM MODIFIED " + item["Modified"]);
                                    var itemName = (string)item["Title"];
                                    var Url = (string)_web.Url;
                                    //var modifiedDate = (string)item["Modified"];
                                    //siteTitle.Add(_web.Title);
                                    //siteUrl.Add(_web.Url);
                                    //listTitle.Add(list.Title);
                                    //listItemTitle.Add(itemName);
                                    //listItemModified.Add(modifiedDate);
                                    table.Rows.Add(_web.Title, _web.Url, list.Title, itemName, parameterDate);
                                    continue;
                                }

                            }
                            if (items.Count > 0)
                            {
                                lastId = items.Last().Id;
                            }
                        }
                    }

                    Console.WriteLine("#####################################################################");
                    foreach (Web subweb in _web.Webs)
                    {
                        string newPath = subweb.Url;
                        GetAllSubWebs(newPath, username, password);
                    }
                }//End of Using
            }
            catch (Exception ex) 
            {
                Console.WriteLine(ex.Message);
            }
            
        }

        public static void ToCSV(this DataTable dtDataTable, string strFilePath)
        {
            StreamWriter sw = new StreamWriter(strFilePath, false);
            //headers  
            for (int i = 0; i < dtDataTable.Columns.Count; i++)
            {
                sw.Write(dtDataTable.Columns[i]);
                if (i < dtDataTable.Columns.Count - 1)
                {
                    sw.Write(",");
                }
            }
            sw.Write(sw.NewLine);
            foreach (DataRow dr in dtDataTable.Rows)
            {
                for (int i = 0; i < dtDataTable.Columns.Count; i++)
                {
                    if (!Convert.IsDBNull(dr[i]))
                    {
                        string value = dr[i].ToString();
                        if (value.Contains(','))
                        {
                            value = String.Format("\"{0}\"", value);
                            sw.Write(value);
                        }
                        else
                        {
                            sw.Write(dr[i].ToString());
                        }
                    }
                    if (i < dtDataTable.Columns.Count - 1)
                    {
                        sw.Write(",");
                    }
                }
                sw.Write(sw.NewLine);
            }
            sw.Close();
        }  
    }
}

Friday, May 8, 2020

PowerShell script to return the sites not used in last 6 months

Hi All,

I've worked on a PowerShell script to read the site Urls from .CSV file and return the sites which are being used in last 6 months. I've faced many challenges as I had go through the sub-sites and list. For each list, I had to iterate through each item's Modified Date to check whether the item is modified or not in last 6 months.
It was very difficult for the lists who item count exceeds list view threshold i.e. 5000 items. For those lists, I had to run in batches to overcome this error.

Please see the script below.


Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"  
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"  

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

#$siteURL = "https://uat-intranet.cbreglobalinvestors.com"  
$userId = "US\KBasu"  
$pwd = Read-Host -Prompt "Enter password" -AsSecureString

$siteUrls =@()

##Global variable used
$global:count = 0

$siteTitle = New-Object System.Collections.Generic.List[System.Object]
$siteLinks = New-Object System.Collections.Generic.List[System.Object]
$listTitle = New-Object System.Collections.Generic.List[System.Object]
$listItemTitle = New-Object System.Collections.Generic.List[System.Object]
$listItemModified = New-Object System.Collections.Generic.List[System.Object]


try{ 
    

     Function GetWebs($siteUrl){
        $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteURL);
        $context.Credentials = New-Object System.Net.NetworkCredential($userId, $pwd);

        $web = $context.Web
        $context.Load($web)
       
        
        #Get Immediate sub-webs in site collection
        $webs = $web.Webs
        $context.Load($webs)
        $context.ExecuteQuery()

        Write-Host "Processing web : "$web.Url -ForegroundColor Magenta
        
        $lists = $web.Lists
        $context.Load($lists)
        $context.executeQuery() 

        Foreach($list in $web.Lists){
            Write-Host "Processing list : " $list.Title -ForegroundColor Yellow
            $context.Load($list)
            $context.ExecuteQuery()
            Write-Host "List items count :" $list.ItemCount
            
            Write-Host "---------------------------------------------------------------------------------------------------"
            
            ##Process List Items in Batches to Fix SharePoint Online List View Threshold Issue in PowerShell     
            $BatchSize = 500
            $Query = New-Object Microsoft.SharePoint.Client.CamlQuery
            $Query.ViewXml = "<View Scope='RecursiveAll'><Query><OrderBy><FieldRef Name='ID' Ascending='TRUE'/></OrderBy></Query><RowLimit Paged='TRUE'>$BatchSize</RowLimit></View>"
            
            ##$ListItems = $list.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())
            $ListItems = $list.GetItems($Query)
            $context.Load($ListItems)
            $context.ExecuteQuery();

            
            
            Foreach($listItem in $ListItems){
                

            
                if($listItem["Modified"] -gt $dateCheck){   
                    $global:count = $global:count + 1
                                  
                    $siteTitle.Add($context.Web.Title)
                    $siteLinks.Add($context.Web.Url)
                    $listTitle.Add($list.Title)
                    $listItemTitle.Add($listItem["Title"])
                    $listItemModified.Add($listItem["Modified"])
                    
                    Continue
                }
                else{
                    Break
                }
            }


        }
    

        Foreach($subweb in $webs){
            
            GetWebs($subweb.Url)
            Write-Host "########################################################################################"
        }
        
    }


     
     $dateCheck = [DateTime]::Now.AddMonths(-6)
    
    
    $csv = Import-Csv "D:\Kunal\Global Investors\Automation\Sites.csv"
    $csv | ForEach-Object {
        $siteUrls += $_."SiteUrl"
        
    }
    
    foreach($siteUrl in $siteUrls){
        Write-Host "Processing URL: " $siteUrl -ForegroundColor DarkMagenta
        GetWebs($siteUrl)
    }
    Write-Host "Count: "$global:count
    

    $results = @()
    for($i=0; $i -le $count; $i++){
        $ExportItem = New-Object PSObject
        $ExportItem | Add-Member -MemberType NoteProperty -name "Site" -value $siteTitle[$i]
        $ExportItem | Add-Member -MemberType NoteProperty -Name "Site Url" -value $siteLinks[$i]
        $ExportItem | Add-Member -MemberType NoteProperty -name "List Name" -value $listTitle[$i]
        $ExportItem | Add-Member -MemberType NoteProperty -name "ListItem Title" -value $listItemTitle[$i]
        $ExportItem | Add-Member -MemberType NoteProperty -name "ListItem Modified" -value $listItemModified[$i]
        $results += $ExportItem
    }
    $results | Export-Csv "D:\Kunal\Global Investors\Automation\Reports.csv" -NoTypeInformation
     
}  
catch{  
    write-host "$($_.Exception.Message)" -foregroundcolor red  
}