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  
}

Thursday, October 3, 2019

Run JavaScript Object Model in HTML Page

Hi All,

I had issues in running JavaScript Object model in HTML page. Since it is not SharePoint page so referring only 'sp.js' won't help. I googled several things and later I got to know that I've to add all the below references to make the JSOM works in an HTML page.

<script type="text/javascript" src="https://uat-intranet.cbreglobalinvestors.com/_catalogs/masterpage/Unite/Scripts/jquery-1.9.1.min.js"></script>

<script src="https://uat-intranet.cbreglobalinvestors.com/_layouts/1033/init.js"></script>

<script src="https://uat-intranet.cbreglobalinvestors.com/_layouts/MicrosoftAjax.js"></script>

<script src="https://uat-intranet.cbreglobalinvestors.com/_layouts/sp.core.js"></script>

<script src="https://uat-intranet.cbreglobalinvestors.com/_layouts/15/sp.runtime.js"></script>

<script src="https://uat-intranet.cbreglobalinvestors.com/_layouts/15/sp.js"></script>

Thanks,
Kunal

Wednesday, May 8, 2019

Deny - Add and customize issue for a user

Hi Folks,

I've received a incident ticket where user shared his concern regarding unable to add/customize pages. We have checked on the ticket and got to know that user do has Full Control access to the SharePoint site. But there is also other thing spotted in permissions check which shows "Deny  -  Add anc Customize Pages".


SharePoint Permissions Issue

We analyzed the issue and observed that Custom Script is disabled for the site.
  • It was very strange to get this type of error as I was logged-in with the Admin account and still getting access denied to certain things and getting no permission to add or customize pages. Therefore, to correct this issue, I checked the Office 365 Admin Portal settings. For this,
    1. Sign in to Office 365 Admin Portal with your admin account.
    2. Go to the SharePoint Admin Centre.
    3. Select Settings.

      Look for “Custom Script” option. In my case, client IT Administrator unknowingly disabled the option, as shown below.

      SharePoint Permissions Issue
  • Now, the solution - Enable or Allow the Custom Script option.

    NOTEAny change to the scripting setting made through the SharePoint Online Admin Centre may take up to 24 hours to take effect.

    SharePoint Permissions Issue
  • After doing the above setting, I waited for 24 hours, and Voila! Now, I am not getting any “Access Denied” error while checking-out the file in SharePoint Designer.

    SharePoint Permissions Issue

    You can use PowerShell command (Set-SPOSite -Identity https://<yourdomain>.sharepoint.com -DenyAddAndCustomizePages $false) also to make the above change, however, just make sure the scripting setting in the admin portal matches what you set using PowerShell.



Thanks,
Kunal

Wednesday, April 17, 2019

Edit page issues with Full control permissions

Hi All,

I was struggling with an issue where the user couldn't able to edit the home page of the site despite having full control permissions to the site via. Owners group. For the meanwhile, I've added user to Site Collection Admin group. But that is not a proper solution to the issue.

I deep dive through internet to identify the root cause. After lot of research, I got to know that if there are no permissions for 'Master Pages and Page Layouts' library then other than site collection administrator no one can edit the pages.

I checked the same to the site and observed that there are unique permissions for 'Master Pages and Page Layouts' library and no one other than site collection administrator can see its content. I made the library inherit permissions from parent and removed the user from site collection admin group as I did earlier. Luckily, it worked and user can able to edit the page without having herself to get added in site collection administrator's group. :)

Thanks,
Kunal Basu

Tuesday, April 2, 2019

Your account is in a bad state - issue

Hi All,

I was facing couple of issues in my project. Here are the following-


  1. User is unable to open the SharePoint Online site in SharePoint Designer. The moment user is trying with his credentials, he received the error message - "Your account is in bad state".
  2. User is trying to update in InfoPath list form by making changes in template.xsn file for that list. He made the changes but when he's trying to publish the form - he get's the error: "Your account is in bad state".

While analyzing the issue, I got to know that legacy authentication is disabled for SharePoint online sites. Hence, modern authentication is enabled. While SharePoint Designer wasn’t natively designed to work with Modern Authentication (ADAL) there are updates available that allow it to work.Most Office 2013 applications will be able to successfully use modern authentication once the EnableADAL=1 registry key has been set. See the below link for the article.



You can refer to the below link for InfoPath related issue as the root cause is same for both SPD and InfoPath Designer.



Thanks,
Kunal