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  
}