Reset unique permission for SharePoint document library and files

Sometime we need to reset the unique permission for document library, sub folders and files. If the document library has only 1-2 documents then we can handle it manually, but if you have thousands of files and folder so its quite difficult to reset it for all one by one. Below piece of code can help to reset unique permission for document library and its content. This script will take the top level permission from document library.


function ResetUniquePermission {
Param(
[Parameter(Mandatory = $true, HelpMessage="Enter the site url")][ValidateNotNullorEmpty()][string] $SiteURL ,
[Parameter(Mandatory = $true, HelpMessage="Enter the library name")][ValidateNotNullorEmpty()][string] $LibraryName,
[Parameter(Mandatory = $true, HelpMessage="Total number of files")][ValidateNotNullorEmpty()][int] $TotalFiles

)

$Web = Get-SPWeb $SiteURL 
$List= $Web.Lists[$LibraryName]
$Query = New-Object Microsoft.SharePoint.SPQuery
$Query.ViewXml =  @"
<View Scope="RecursiveAll">
    <Query>
        <OrderBy><FieldRef Name='ID' Ascending='TRUE'/></OrderBy>
    </Query>
    <RowLimit Paged="TRUE">$TotalFiles</RowLimit>
</View>
"@;

$Items = $List.GetItems($Query)
for($j=0;$j -lt $Items.Count ;$j++)
{
    $Items[$j].ResetRoleInheritance()
    Write-Host "Permission reset done for file "$Items[$j]["Title"] -ForegroundColor Green
}
}

Create modern page using defined template

SharePoint onprem and SharePoint online updates never been same.Most of required feature which are available in SPOnline is not available in SharePoint On-prem. One of them is template based page creation.As of today you can create page with provided template in communication site but not available in Team site. So here is the small solution, by using we can provide plenty of predefined template to end users for their easiness.
Lets start:

Step 1: Create a empty page, just add your columns and widgets into into , like I have created. Refer below screenshot.

So here I have added few widget and created a blank page page, once you page created just save that page.

Step 2: After saving the page just run below script to get the Canvas content of the page.

$templatePageName= "demo-page.aspx"
$oWeb = Get-SPWeb "&lt;Site URL&gt;"
$pageLibrary = $oWeb.Lists["Site Pages"]
$page = $pageLibrary.GetItems() | select Name, ID | where { $_.Name -eq $templatePageName }
if ($null -ne $page.ID) {
    $canvasContent = $pageLibrary.GetItemByID($page.ID)["CanvasContent1"]
    $canvasContent | Out-File -FilePath C:\canvasContent.txt
}
else { Write-Host "Page Id not found" -ForegroundColor DarkCyan }

Step 3: After running above script you will find the Canvas content text in text file with name “canvasContent.txt” which is generated in C drive of your machine.Now copy that text and pass it to “CanvasContent1” property.

Step 4: Refer article Create Modern page using C# in SharePoint’19 on-prem and pass text of canvasContent.txt file to “CanvasContent1” property.

That’s it, like this you can provide functionality to create page with your own template.

SharePoint Installation Error: Windows cannot find e:\prerequisiteinstaller.exe

To install SharePoint we attaching SharePoint setup ISO. It seems due to the same after installation complete, it is looping this error after login to server.

This issue I face in SharePoint 2013 to SharePoint 2019 and the solution will work for all the version mentioned. So just run the below powershell script it will delete the .CMD file from startup and after that command popup won’t appear after login to server.

$path="C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup"
$file= Get-ChildItem $path -Recurse -Force -Filter SharePointServerPreparationToolStartup* | Where-Object {!$_.PSIsContainer}
if($file -ne $null) 
{
	$file | Remove-Item
	Write-Host "File $($file.Name) removed successfully" -ForegroundColor green
}
else
{
   Write-Host "File not found" -ForegroundColor red
}

Daily consolidated email alert before expiry

Most of the time we are getting requirement for a consolidated email alert for before expiring the important documents like Employee contracts, Lease agreements and many other documents which need continuous monitoring to avoid financial impact on the company.

So here I am showing you for Employee contracts expiry, an alert will trigger automatically before 10 days of expiry date which we have entered in our document Library

My Library which I used for this blog:

My email output will show as below :

Let’s start :

Open your power automated home page > Now click on the “Create” button from the left navigation and click on the “Scheduled flow” option.

Once you click on the “Scheduled flow” option, then on the next screen enter the flow name and schedule information. In my case flow name is “Contract Expiry Alert” and the schedule is daily 10:00 AM.

Now add New Step:- First initialize the variable, here I am initializing a variable to calculate the date and which is 10 days later from the day when scheduler ran. To get the items that are going to expire in the next 10days.

Click on “Add an action” and search for Initialize variable, once you will click on it just set the variable name and expression like below

Expression : addDays(utcNow(),10,’yyyy-MM-ddT00:00:00′)

Click on New step and add action “Get files (properties only)” and configure like below

*To get the alert for an item which is expiring in the next 10 days, you need to use a filter query. It’s the same as the OData query which you are using in rest. So in the previous step, we have calculated the date and in this step, we are filtering the list item based on the date which we have calculated.

Limit Column by view, if you have many columns and only a few you wanted to display then simply create a view in SharePoint List and select the same view.

Filter query: ContractEndDate eq datetime'<Varible>’

Now add a new step and initialize one more variable to store the filter item result in the required format. We have to set the default value to null.

Add a new step and search for action “Apply to each” and configure like below,

So here total 3 actions we are doing,

  • Select an output from the previous step
  • Composing the HTML table content
  • Append to a string: Use to append the string

Add a new step and check null for the variable which set in the previous step.

And add “Send an email notification” action to the “Yes” section and configure like below

You need to enter the target email id, subject, and configurable body.

Source code for the email body:

<style>
    table.emailtbl {
        background-color: #EEEEEE;
        width: 100%;
        text-align: left;
        border-collapse: collapse;
    }

    table.emailtbl td,
    table.emailtbl th {
        border: 1px solid #AAAAAA;
        padding: 3px 2px;
    }

    table.emailtbl tbody td {
        font-size: 13px;
    }

    table.emailtbl thead {
        background: #1C6EA4;
        color: white;
    }

    table.emailtbl thead th {
        font-weight: bold;
    }
</style>
<hr>
<p>Greetings, </p>
<p>Please find below the list of contract expiring shortly. Please do the needful.</p>
<br />
<table class="emailtbl">
    <thead>
        <tr>
            <th>Employee Name</th>
            <th>Employee No</th>
            <th>Contract Start Date</th>
            <th>Contract Expiry Date</th>
        </tr>
    </thead>
    <tbody>
        @{variables('htmlTable')}
    </tbody>
</table>
<br />
<hr>

and that’s it, flow is ready. You can run and test the flow.

Bulk update resource level custom field in Project Server

There are plenty of blogs available about the same, I am writing it again because I found most of the code is not working else throwing the error, here I have tested these code with Project Server online and Project Server on-prem version, and it works like charm.

This is a very common scenario where every project server developer needed once a time in his career.

So this is the solution, just need to replace site URL, username, and password and custom field which you wanted to update.

<# Below is CSV sample which I am using for this code. First Column is headers. #>;
<#
ResourceName,ResourceEmailAddress,EmpRate
Kuldeep, kuldeep.verma@xyz.com, 10000
Rajdeep, rajdeep.sardesai@xyz.com, 20000
Jaydeep, Jaydeep.prajapat@xyz.com, 40000
#>

#Download and install Microsoft Client Component from https://www.microsoft.com/en-in/download/details.aspx?id=42038
#Microsoft SharePoint Client Component is mandatory to move further.
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.ProjectServer.Client.dll"

#replace CSV path
$csvpath="C:\FakePath\FileName.csv"
$siteURL = "{Site URL}"
$loginname = "{UserName}"
$pwd = "{Password}"
$securePassword = ConvertTo-SecureString $pwd -AsPlainText -Force
$creds = New-Object System.Management.Automation.PsCredential $loginname,$securePassword
$projContext = New-Object Microsoft.ProjectServer.Client.ProjectContext($siteURL)
$projContext.Credentials = $creds
$customfields = $projContext.CustomFields
$projContext.Load($customfields)
$projContext.ExecuteQuery()

And if you don’t know the Internal Name of the field then simply use the below script after running the above code.

#get custom field by anem
$customfield = $customfields | select InternalName, Name | WHERE {$_.Name -eq "&lt;Field display name&gt;"}

If you wanted to list down all custom fields then you can simply use the below piece of code.

#get all custom field
$customfields | select InternalName, Name, IsRequired

Below I am comparing the resource email and updating the custom field, you can use the Resource Name also for comparison.

Import-Csv $csvpath | ForEach-Object {
Try {
Write-Host "Updateding Resource $($_.ResourceName)..." -ForegroundColor Green
$resourceEmail = $_.ResourceEmailAddress
$resource = $projContext.EnterpriseResources | select Id, Name, Email, UserPrincipalName | where { $_.Email -eq $resourceEmail }
if ($resource -ne $null) {
$res = $projContext.EnterpriseResources.GetByGuid($resource.Id)
#update $_.Value with your field name of CSV and Change the Internal field name
$res["{Internal Field Name}"] = $_.EmpRate
$projContext.EnterpriseResources.Update()
$projContext.ExecuteQuery()
Write-Host "Updated Resource $($_.ResourceName) successfully!" -ForegroundColor Green
}
else {
Write-Host "Resource $($_.ResourceName) not found!" -ForegroundColor DarkCyan
}
}
catch {
$_ | select -expandproperty invocationinfo
Write-Host "Error occurred while updating $($_.ResourceName)..." -ForegroundColor Red
write-host "$($_.Exception.Message)" -foregroundcolor DarkRed
}
}
Write-Host "Script executed successfully" -ForegroundColor Yellow

Download complete source code from GitHub

“Sign as different user” for SharePoint site

By default, you won’t find “Sign as different user” option in SharePoint, but most of them as a developer or superuser need to log in with different users to see the content rendering based on different permission and role. So there are two ways to open the SharePoint site in different users.

Method-1

You need to just append “_layouts/closeConnection.aspx?loginasanotheruser=true”  to your Site Absolute Url and just hit enter, it will show you the pop up for credentials. There is no browser restriction for the same.

URL: _layouts/closeConnection.aspx?loginasanotheruser=true

Method-2

This method is only applicable in the SharePoint on-prem site.

The second method is to run a user browser to “Run as different user” mode. So to open any browser as the different user just simply press shift and right-click on the browser exe file, it will show you the option “Run as different user”, select this option and it will pop up for credentials. Enter the credentials for the user which you trying to log in and open your SharePoint site.

 

Get error line number powershell program

If someone wrote a PowerShell program, with multiple lines and without caring the coding standard and you got stuck to find where the error is, so very simplest way which I am thinking is just use below piece of code which saves your time and let you know about a line which is having an issue.

InvocationInfo can provide information about how and where this command was invoked

So just use simple try-catch like below

try {
    #&lt;replace with your code&gt;
}
catch {
    $_ |select -expandproperty invocationinfo
    write-host "$($_.Exception.Message)" -foregroundcolor red  
    break;
}

Create Modern page using C# in SharePoint’19 on-prem

Here I am just demonstrating to you, how we can create a page using the server object model in SharePoint’19 on-prem. There are many things we control through C# while creating the Pages like disable comment, publish the page, custom templates, embedded pre-defined web part, and many more.

There are three types of Page Layout available, so you can choose based on your requirement. By default, you can only create Article Page from UI, but after doing some customization you can do much more on pages.

  • Home
  • Article

Another parameter is “PromotedState”, if you pass 2 then your page is a news page and 0 generic pages.

We can also use customize canvas or we can say multiple page templates to create the Modern page. By default on the team site, the Page template option is not available so you can achieve it through us this small customization.

Refer article: Create modern page using defined template

string PageLibName = "Site Pages";
string PageName = "demo-page.aspx";
SPUser PageAuthor = "&lt;Pass SPUser Object&gt;";
string SiteURL = "&lt;Pass Site URL&gt;";
using (SPSite oSPsite = new SPSite(SiteURL))
{
    using (SPWeb oWeb = oSPsite.OpenWeb())
    {
        SPList oList = oWeb.Lists[PageLibName];
        SPListItem oItem = oList.RootFolder.Files.Add(String.Format("{0}/{1}", oList.RootFolder.ServerRelativeUrl, PageName), SPTemplateFileType.ClientSidePage).ListItemAllFields;
        oItem["Title"] = System.IO.Path.GetFileNameWithoutExtension(PageName);
        oItem["ContentTypeId"] = "0x0101009D1CB255DA76424F860D91F20E6C4118";
        oItem["ClientSideApplicationId"] = "b6917cb1-93a0-4b97-a84d-7cf49975d4ec";
        
        //Home
        oItem["PageLayoutType"] = "Article";

        //Promoted State 2 is for News and 0 for Generic Page
        oItem["PromotedState"] = 2;

        //comment below if you don't want to change page author or editor -- Created by and Modfied by field
        oItem[SPBuiltInFieldId.Author] = oWeb.EnsureUser(PageAuthor.LoginName);
        oItem[SPBuiltInFieldId.Editor] = oWeb.EnsureUser(PageAuthor.LoginName);
        
        //this is also key factor while create the page , you can change it if you want custom page layout. 
        oItem["CanvasContent1"] = "&lt;div&gt; &lt;/div&gt;";

        //False to enable comment and True if you wanted to disable the comment 
        oItem.SetCommentsDisabled(false);
        oItem.Update();
    }
}

Publish multiple pages in SharePoint

As a SharePoint admin most of the time we are getting requirement to publish pages or while working on migration for some cases we would require to publish pages. Here is the small piece of code which can help to publish single page or multiple pages using Powershell.

This piece of code is required for both

$LibraryTitle = "<Replace with Page Library Name>"
$SiteURL = "<Replace with your site URL>"
$oWEb = Get-SPWeb $SiteURL
$PublishingComment ="Published using powershell"

Use below block if you wanted to publish a single page, replace with your page url.

<# Single page publish #>
$pageURL = "https://digiboek.net/sites/demo/SitePages/Sample.aspx"
$file = $oWEb.GetFile($pageURL)
$file.Publish($PublishingComment);

If you wanted to publish multiple pages then use below piece of code

<# Publish all pages from library #>
$oLib = $oWEb.GetFolder($LibraryTitle)
$files = $oLib.Files | select Name, Url
foreach ($file in $files) {
    $ofileURL = $SiteURL + "/" + $file.Url
    $oFile = $oWEb.GetFile($ofileURL)
    if ($oFile.Exists -eq $true) {
        $oFile.Publish($PublishingComment);
        Write-Host $file.Name" Page published successfully..." -foreground Green
    }
}

Happy Coding 😊

Manage date format in MS Flow

While working with MS Flows, we are getting dates in UTC format and most of the time we need to convert it to our local time zone. So, here are some most common date formats which most of the people required.

Click here to get the Microsoft Time Zone IDs

https://docs.microsoft.com/en-us/previous-versions/windows/embedded/gg154758(v=winembedded.80)

In this example, I am using ‘Arabian Standard Time’ to get them for our local time zone. Additionally, we will use only two functions to get the required date one is “convertFromUtc()” and utcNow() functions.

 

In simple language  “convertFromUtc()” function can help you to convert the dates in your local time zone. It requires three properties and utcNow() function can provide the DateTime stamp on the instance.

In my scenario I have initialized a variable (my variable name is dtNow), Variable type is “String” then undervalues select the expression and enter any of the expression as your need.

 

 

For example, Today’s timestamp 10 August 2019 15:02:56, so these are the sample of expression and output.

Date time format

Expression

Output

d

convertFromUtc(utcNow(),’Arabian Standard Time’,’d’)

8/4/2019

dd-MM-yy

convertFromUtc(utcNow(),’Arabian Standard Time’,’dd-MM-yy’)

04-08-19

dd/MM/yy

convertFromUtc(utcNow(),’Arabian Standard Time’,’dd/MM/yy’)

04/08/19

MMddyyyyHHmmss

convertFromUtc(utcNow(),’Arabian Standard Time’,’MMddyyyyHHmmss’)

08042019150256

yyyy-MM-dd-HH:mm:ss

convertFromUtc(utcNow(),’Arabian Standard Time’,’yyyy-MM-dd-HH:mm:ss’)

2019-08-04-15:02:56

yyyy/MM/dd-HH:mm:ss

convertFromUtc(utcNow(),’Arabian Standard Time’,’yyyy/MM/dd-HH:mm:ss’)

2019/08/04-15:02:56

dd/MM/yyyy-HH:mm:ss

convertFromUtc(utcNow(),’Arabian Standard Time’,’dd/MM/yyyy-HH:mm:ss’)

04/08/2019-15:02:56

dd-MM-yyyy

convertFromUtc(utcNow(),’Arabian Standard Time’,’dd-MM-yyyy’)

04-08-2019

dd-MMM-yyyy

convertFromUtc(utcNow(),’Arabian Standard Time’,’dd-MMM-yyyy’)

04-Aug-2019

dd/MMM/yyyy

convertFromUtc(utcNow(),’Arabian Standard Time’,’dd/MMM/yyyy’)

04/Aug/2019