<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>SharePoint Gen</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/chandru/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/chandru/feed.xml</link>
    <description>The official blog of Chandrasekar, Microsoft SharePoint Consultant</description>
    <lastBuildDate>Tue, 30 Aug 2016 17:05:39 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>SharePoint Online - Site Collection External Sharing Settings App</title>
      <link>https://docs.microsoft.com/archive/blogs/chandru/sharepoint-online-site-collection-external-sharing-settings-app</link>
      <pubDate>Tue, 30 Aug 2016 07:38:05 GMT</pubDate>
      <dc:creator><![CDATA[ChandrasekarN]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chandru/?p=1525</guid>
      <description><![CDATA[Summary
SharePoint Online provides an ability to share contents to external users. This is a great...]]></description>
      <content:encoded><![CDATA[<h3>Summary</h3>
SharePoint Online provides an ability to share contents to external users. This is a great feature for collaboration with your partners. However, the External Sharing can be enabled/disabled only in SharePoint Admin Portal or PowerShell which requires the user to be part of SharePoint Online administrators group. This creates a dependency on Tenant Administrators every time a Site Owner/Site Collection Administrator wants to either allow or disallow external sharing in their site collection. This application gives the privilege for a Site Owner and Site Collection administrators to change the external sharing settings from a site collection itself.
<h3>Features</h3>
<ul>
 	<li>Empowers Site Owner and Site Collection Administrators to change external sharing settings.</li>
 	<li>Display banner if the site is externally shared</li>
 	<li>File system logging</li>
</ul>
<h3><strong> </strong></h3>
<h1>Solution Components</h1>
The solution consists of two parts;
<ol>
 	<li>A link to access a page in remote web application to change external sharing settings</li>
 	<li>The web application that hosts a page for changing external sharing settings.</li>
</ol>
<h3>External Sharing Link</h3>
Only users who have site collection manage permission will be able to use this application. Users with manage site collection permission can go to site settings of a site collection and they will see a link called “External Sharing” under “Site Collection Administration”.

<img src="https://i.imgur.com/7MIROCT.png" />
<h3>Remote web application</h3>
When the user clicks on the “External Sharing” link, they will be redirected to a page hosted in an IIS server On-Prem or Azure. This page provides the users with the options to change external sharing settings.

<img src="https://i.imgur.com/F489vY5.png" />
<h1>Solution configuration and setup</h1>
<h3>External Sharing Link</h3>
The link to change External sharing will be available under site settings -&gt; Site collection administration of each site collection. This link will be added automatically when the site is provisioned using Site Provisioning App.

<img src="https://i.imgur.com/jBEGuhK.png" />
<h3>Remote web application setup</h3>
For the External Sharing Web Application to interact with SharePoint Online, we need to create App Principals which is registered with Microsoft Azure Access Control Service (ACS).
<h4>Add-in Registration and Permissions</h4>
External Sharing Application requests permissions at Tenant, Site Collection, and User Profile level. Also, the application uses App-only Policy as all Site Owners or Site Collection Administrators will not have permission at Tenant and User Profile level.

<img src="https://i.imgur.com/w4u9pQv.png" />
<h3>Web configuration file</h3>
Enter the Client ID and Secret values in External Sharing Web Application’s web.cofig file. For security purpose, the values will be encrypted using Add-in Security tool – See section "Securing Add-in Principals" on how to use the tool.

The web.config of the application contains encrypted ClientID, encrypted ClientSecret, Tenant Admin URL, and JavaScript file that contains the code for displaying the banner.
<h1>Application walkthrough</h1>
<h3>External Sharing page</h3>
External Sharing page is used for changing the settings of external sharing of a site collection.

The page displays the following;
<ul>
 	<li>Top navigation with current logged in user name</li>
 	<li>Top level Site Settings navigation option to go back to the site collection’s site settings page</li>
 	<li>The URL of the site collection</li>
 	<li>Options to change the settings of external sharing</li>
 	<li>Ok button to submit the change or cancel button to go back to site settings page.</li>
</ul>
<h3>External Sharing settings</h3>
There are 2 settings available;
<ol>
 	<li>Allow external sharing</li>
 	<li>Don’t allow external sharing</li>
</ol>
By default, the current external sharing settings for the site collection will be selected. Only when the user opts to change the settings, the Ok button will be enabled.
<h4>Allow external sharing</h4>
To enable external sharing, users need to choose the option “Allow external users who accept sharing invitations and sign in as authenticated users”.

<img src="https://i.imgur.com/F489vY5.png" />

When the user chooses to allow external sharing, two things happen;
<ul>
 	<li>The site collection will be shared externally At the tenant level, the option to allow external users who accept sharing invitations and sign in as authenticated users will be enabled.</li>
 	<li>A banner will be displayed in the Site collection and sites informing the users that this site can be shared with people outside of Contoso. We make use of SharePoint Online's OOB status banner to display custom message. Refer externalsharing.js located under scripts folder. Since this js will be used across site collections, deploy this file in CDN or at any root site collection level.</li>
</ul>
<img src="https://i.imgur.com/qUeCQGp.png" />
<h4>Don’t allow external sharing</h4>
To disable external sharing, users need to choose the option “Don’t allow sharing outside your organization”. When the user chooses not to share the site externally, a message will be displayed (see picture below) informing about the details if the stop external sharing of the site collection.

<img src="https://i.imgur.com/0nNsGn3.png" />

When the user clicks Ok, two things happen;
<ol>
 	<li>The site collection will not be shared externally - At the tenant level, the option to disallow external sharing will be enabled.</li>
 	<li>The banner will be removed from the site collection.</li>
</ol>
<h1>Securing Add-in Principals</h1>
To protect the Add-in principles, most importantly the Client ID and Client Secret, we encrypt their values and store the encrypted values in the respective configuration files. The application handles the decryption of the values. DPAPI functions encrypt and decrypt data using the Triple-DES algorithm. In addition to encryption and decryption, DPAPI handles key generation and protection. DPAPI can generate encryption keys that are unique either for a user making the call or the computer on which the program making the call runs. The encryption can be scoped at machine or user level. Using the encrypted value generated in one machine we can't decrypted the value in another machine, it has to be decrypted in the same machine. When an application calls the DPAPI encryption routine, it can specify an optional secondary entropy ("secret" bytes) that will have to be provided by an application attempting to decrypt data.

<img src="https://i.imgur.com/oBMuD3X.png" />

Please look at Governance.AddInSecurity application in PNP Github for the source code - https://github.com/OfficeDev/PnP/tree/master/Solutions/Governance.AddInSecurity<strong> </strong>

The entire solution for External Sharing Settings Add-In can be found here - https://github.com/OfficeDev/PnP/tree/master/Solutions/Governance.ExternalSharing

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>SharePoint Online - Change Site Collection Ownership App</title>
      <link>https://docs.microsoft.com/archive/blogs/chandru/sharepoint-online-change-site-collection-ownership-app</link>
      <pubDate>Tue, 30 Aug 2016 07:34:14 GMT</pubDate>
      <dc:creator><![CDATA[ChandrasekarN]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chandru/?p=1515</guid>
      <description><![CDATA[Summary
The Change Site Collection Owner application is used for changing the Site Owner of a site...]]></description>
      <content:encoded><![CDATA[<h3>Summary</h3>
The Change Site Collection Owner application is used for changing the Site Owner of a site collection in SharePoint Online by the current site owner or any site collection administrator. Out of the box in SharePoint Online, the Site Owner can only be changed in SharePoint Admin Center or PowerShell which requires the user to be part of SharePoint Online administrators group. This application gives the privilege for a Site Owner and Site Collection administrators to change the site collection ownership from a site collection itself.
<h3>Features</h3>
<ul>
 	<li>Empowers Site Owner and Site Collection Administrators to change current site owner</li>
 	<li>Choose site owner from only supported certain domain (for e.g. disallow external users from being a site owner)</li>
 	<li>Multiple option to choose a site owner. Sample has the options to choose
<ul>
 	<li>Assign to myself</li>
 	<li>Assign to my manager</li>
 	<li>Assign to another site collection administrators</li>
</ul>
</li>
 	<li>Automatically set the new site owner's email in Access Request Settings for the site.</li>
 	<li>Email notification to Site Owner and Site Collection Administrators when any change happens</li>
 	<li>File system logging</li>
</ul>
&nbsp;
<h1>Solution Components</h1>
The solution consists of two parts;
<ol>
 	<li>A link to access a page in remote web application to change site collection ownership</li>
 	<li>The web application that hosts a page for changing the site ownership.</li>
</ol>
<h3>Change Site Collection Ownership Link</h3>
Only users who have site collection manage permission will be able to use this application. Users with manage site collection permission can go to site settings of a site collection and they will see a link called “Change Site Collection Ownership” under “Site Collection Administration”.

<img src="https://i.imgur.com/NRz4eGh.png" />
<h3>Remote web application</h3>
When users click on the “Change Site Collection Ownership” link, they will be redirected to a page hosted in an IIS server On-Prem or Azure. This page provides an interface with the options to choose a new site owner.

<img src="https://i.imgur.com/KKSWdpH.png" />
<h1>Solution configuration and setup</h1>
<h3>Change Site Collection Ownership Link</h3>
The link to change site collection ownership will be available under site settings -&gt; Site collection administration of each site collection. This link will be added automatically when the site is provisioned using Site Provisioning App.

<img src="https://i.imgur.com/I3LLSvH.png" />
<h3>Remote web application setup</h3>
For the Change Owner Web Application to interact with SharePoint Online, we need to create App Principals which is registered with Microsoft Azure Access Control Service (ACS).
<h4>Add-in Registration and Permissions</h4>
Change Owner Application requests permissions at Tenant, Site Collection, and User Profile level. Also, the application uses App-only Policy as all Site Owners or Site Collection Administrators will not have permission at Tenant and User Profile level.

<img src="https://i.imgur.com/w4u9pQv.png" />
<h3>Web configuration file</h3>
Enter the Client ID and Secret values in Change Owner Web Application’s web.cofig file. For security purpose, the values will be encrypted using Add-in Security tool – See section "Securing Add-in Principals" on how to use the tool.

The web.config of the application contains encrypted ClientID, encrypted ClientSecret, Email template file location, Supported Domains and email settings. You can add multiple supported domains separated by comma (for e.g. value="contoso.com,contosotest.onmicrosoft.com”)
<h1>Application walkthrough</h1>
<h3>Change Site Collection Ownership Page</h3>
Change Site Collection Ownership page is used for choosing a new site owner.

The page displays the following;
<ul>
 	<li>Top navigation with current logged in user name</li>
 	<li>Top level Site Settings navigation option to go back to the site collection’s site settings page</li>
 	<li>Left navigation to browse through site collection giving great end user experience.</li>
 	<li>The URL of the site collection</li>
 	<li>Current site owner</li>
 	<li>Options to choose new site owner</li>
 	<li>Add site collection administrators</li>
 	<li>Ok button to submit the change or cancel button to go back to site settings page.</li>
</ul>
<h3>Choosing a new site owner</h3>
There are 3 different options to choose a new site owner. By default none of the options is choose and the “Ok” button will be disabled. Only when the user chooses a new site owner, the user will be able to submit.
<h4>Assign to myself</h4>
In this option, the user can choose themselves as a site owner. When this option is chosen, it will display current user’s name which will be grayed out. In case, the current owner is the same person as the logged in user, this option will be grayed out.

<img src="https://i.imgur.com/KKSWdpH.png" />
<h4>Assign to my manager</h4>
This provides an option to choose user’s manager as a site owner. If the user does not have any manager assigned in user profile, it will be grayed out – The user can’t select this option.

<img src="https://i.imgur.com/eDdfikJ.png" />
<h4>Assign to another site collection administrator</h4>
You can opt to choose one of the existing site collection administrators as a new site owner. Choosing this option, displays a dropdown box that shows all current site collection administrators. It doesn’t display any service accounts though. The users will be shown only if their accounts belong to supported domains configured in web.config file, for e.g. you can restrict external/partners from being a site owner.

If there aren’t any site collection administrators available, then the page displays a message asking users to add site collection administrators using Add Site Collection Administrators link.

<img src="https://i.imgur.com/vCMJgT1.png" />
<h3>Site Collection Administrators</h3>
The page also provides an option to add site collection administrators.
<h2>Submission</h2>
When a new owner is selected and submitted for change, few things takes place;
<ul>
 	<li>The selected person will be assigned as a new site owner for this site collection</li>
 	<li>In the Access Request settings section of the site collection, the newly selected owner's email address will be updated.</li>
 	<li>An Email notification will be sent to new owner, old owner, and all Site Collection administrators informing them about the change in ownership.</li>
</ul>
<img src="https://i.imgur.com/zMAWksp.png" />
<h1>Securing Add-in Principals</h1>
To protect the Add-in principles, most importantly the Client ID and Client Secret, we encrypt their values and store the encrypted values in the respective configuration files. The application handles the decryption of the values. DPAPI functions encrypt and decrypt data using the Triple-DES algorithm. In addition to encryption and decryption, DPAPI handles key generation and protection. DPAPI can generate encryption keys that are unique either for a user making the call or the computer on which the program making the call runs. The encryption can be scoped at machine or user level. Using the encrypted value generated in one machine we can't decrypted the value in another machine, it has to be decrypted in the same machine. When an application calls the DPAPI encryption routine, it can specify an optional secondary entropy ("secret" bytes) that will have to be provided by an application attempting to decrypt data.

<img src="https://i.imgur.com/oBMuD3X.png" />

Please look at Governance.AddInSecurity application in PNP Github for the source code - https://github.com/OfficeDev/PnP/tree/master/Solutions/Governance.AddInSecurity<strong> </strong>

The entire solution for Change Site Ownership can be found here - https://github.com/OfficeDev/PnP/tree/master/Solutions/Governance.ChangeOwnership

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>SharePoint Online : Securing Add-in Principals</title>
      <link>https://docs.microsoft.com/archive/blogs/chandru/sharepoint-online-securing-add-in-principals-2</link>
      <pubDate>Sat, 27 Aug 2016 15:27:45 GMT</pubDate>
      <dc:creator><![CDATA[ChandrasekarN]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chandru/?p=1465</guid>
      <description><![CDATA[For the remote components of a provider-hosted SharePoint Add-in to interact with SharePoint using...]]></description>
      <content:encoded><![CDATA[For the remote components of a provider-hosted SharePoint Add-in to interact with SharePoint using OAuth, the add-in must first register with the Azure ACS cloud-based service and the SharePoint App Management Service of the tenancy. The registration involves creating new Client ID/Secret and other add-in specific details. After you register your add-in, it has an add-in identity and is a security principal, referred to as an add-in principal. When you install your add-in, SharePoint administrators can retrieve information about that particular add-in principal. The Client ID/Secret values need to be entered in configuration file of the application. Anyone who has access to the file system of the config file location can read these values. Using these values, they can build their own application and do anything in the SharePoint they want to (though its only restricted to app permissions defined for the app principal). This can become a big security threat especially if the app is given app-only policy permission.

This is a governance problem. Any organization need to have well defined governance on the deployment process, person responsible in making the changes in the configuration file and so on. If the config file is not well protected enough, it can become a problem. To address this scenario, we need to secure the app principle itself, so that even if someone gets access to these principles they shouldn't be able to do anything with it. The idea is to encrypt the key values using Triple-DES algorithm at Machine level. Using the encrypted value generated in one machine we can't decrypted the value in another machine, it has to be decrypted in the same machine. When an application calls the DPAPI encryption routine, it can specify an optional secondary entropy ("secret" bytes) that will have to be provided by an application attempting to decrypt data.

The solutions consists of 2 parts - Encryption (Generated using an Exe application) and Decryption (Used in the actual add-in application);
<h1>Encryption</h1>
<ul>
 	<li>Enter the Client ID or the Secret value in Client ID/Secret text box.</li>
 	<li>Entropy key is optional field.</li>
 	<li>Choose the scope as Local Machine (this is the default value)</li>
 	<li>Click Encrypt button to get the encrypted text value and hit copy text to copy the values.</li>
</ul>
<img src="https://i.imgur.com/dWBFuZP.png" />

<img src="https://i.imgur.com/bhGB5Rg.png" />
<h3>Validation</h3>
To validate the encrypted text, without altering any values, click the Decrypt button and you should see the original value of the ID/Secret given.

<img src="https://i.imgur.com/S8WciiJ.png" />

If the value is tampered or if you try to use the encrypted text value in a different machine, the decryption will fail.

<img src="https://i.imgur.com/HHWKQ5d.png" />

&nbsp;
<h1>Decryption</h1>
The encrypted value is stored in the configuration file.  The add-in application uses EncryptionUtility class DecryptStringWithDPAPI method to get the decrypted value.  For e.g. in the TokenHelper.cs of an Add-In application, to get the actual value of Client Secret, here is the code;

private static SecureString stringClientSecret = EncryptionUtility.DecryptStringWithDPAPI(WebConfigurationManager.AppSettings.Get("ClientSecret")) ;

private static readonly string ClientSecret = EncryptionUtility.ToInsecureString(stringClientSecret);

The complete solution can be downloaded here - https://github.com/OfficeDev/PnP/tree/master/Solutions/Governance.AddInSecurity

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>SPO : PowerShell to get Custom Actions in a Site Collection</title>
      <link>https://docs.microsoft.com/archive/blogs/chandru/spo-powershell-to-get-custom-actions-in-a-site-collection</link>
      <pubDate>Sat, 27 Aug 2016 15:13:30 GMT</pubDate>
      <dc:creator><![CDATA[ChandrasekarN]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chandru/?p=1445</guid>
      <description><![CDATA[[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection...]]></description>
      <content:encoded><![CDATA[[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")

$siteUrl = Read-Host -Prompt "Enter sitecollection url"
$username = Read-Host -Prompt "Enter user login name"
$password = Read-Host -Prompt "Enter user login password" -AsSecureString
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)

# SharePoint Online
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)
$ctx.Credentials = $credentials

$rootWeb = $ctx.Site
$ctx.Load($rootWeb)
$ctx.ExecuteQuery()
$caColl = $rootWeb.get_userCustomActions()
$ctx.Load($caColl)
$ctx.ExecuteQuery()

Write-Host
Write-Host 'Total number of custom actions: '$caColl.Count
$count = 1
$caColl | ForEach-Object {
Write-Host $count')'  $_.Name
$count++
}]]></content:encoded>
    </item>
    <item>
      <title>SPO : PowerShell Script to get report of all subsites for a given site collection</title>
      <link>https://docs.microsoft.com/archive/blogs/chandru/spo-powershell-script-to-get-report-of-all-subsites-for-a-given-site-collection</link>
      <pubDate>Tue, 23 Aug 2016 14:36:58 GMT</pubDate>
      <dc:creator><![CDATA[ChandrasekarN]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chandru/?p=1435</guid>
      <description><![CDATA[In SharePoint Online, most of the times, a Site Owner would like to get subsites report of their...]]></description>
      <content:encoded><![CDATA[<span style="font-size: medium">In SharePoint Online, most of the times, a Site Owner would like to get subsites report of their site collection.  Here is a sample PowerShell script which uses CSOM to get all users with Full control permission in all the subsites (recursively) under the given Site Collection and outputs in an Excel sheet.  The script can be modified as needed to get other properties of a subsite.</span>

&nbsp;

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"

&nbsp;

$siteURL = Read-Host -Prompt "Enter Site Collection URL"

$username = Read-Host -Prompt "Enter User Name"

$password = Read-Host -Prompt "Password for $username" -AsSecureString

[Microsoft.SharePoint.Client.ClientContext]$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($siteURL)

$clientContext.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)

&nbsp;

$excel = New-Object -ComObject Excel.Application

$excel.Visible = $true

$workbook = $excel.Workbooks.Add()

$sheet = $workbook.ActiveSheet

$counter = 1

$sheet.cells.Item($counter,1) = 'Site URL'

$sheet.cells.Item($counter,2) = 'Unique Permission'

$sheet.cells.Item($counter,3) = 'Users with Full Control Permission'

$sheet.cells.Item($counter,1).font.bold = $True

$sheet.cells.Item($counter,2).font.bold = $True

$sheet.cells.Item($counter,3).font.bold = $True

$sheet.cells.Item($counter,1).Interior.ColorIndex = 8

$sheet.cells.Item($counter,2).Interior.ColorIndex = 8

$sheet.cells.Item($counter,3).Interior.ColorIndex = 8

&nbsp;

Function Invoke-LoadMethod() {

param(

[Microsoft.SharePoint.Client.ClientObject]$Object = $(throw "Please provide a Client Object"),

[string]$PropertyName

)

$ctx = $Object.Context

$load = [Microsoft.SharePoint.Client.ClientContext].GetMethod("Load")

$type = $Object.GetType()

$clientLoad = $load.MakeGenericMethod($type)

$Parameter = [System.Linq.Expressions.Expression]::Parameter(($type), $type.Name)

$Expression = [System.Linq.Expressions.Expression]::Lambda(

[System.Linq.Expressions.Expression]::Convert(

[System.Linq.Expressions.Expression]::PropertyOrField($Parameter,$PropertyName),

[System.Object]

),

$($Parameter)

)

$ExpressionArray = [System.Array]::CreateInstance($Expression.GetType(), 1)

$ExpressionArray.SetValue($Expression, 0)

$clientLoad.Invoke($ctx,@($Object,$ExpressionArray))

}

function Get-SPOWebs(){

param(

$Url = $(throw "Please provide a Site Collection Url"),

$Credential = $(throw "Please provide a Credentials")

)

$context = New-Object Microsoft.SharePoint.Client.ClientContext($Url)

$context.Credentials = $Credential

$web = $context.Web

$context.Load($web)

$context.Load($web.Webs)

$context.ExecuteQuery()

foreach($web in $web.Webs)

{

Get-SPOWebs -Url $web.Url -Credential $Credential

Invoke-LoadMethod -Object $web -PropertyName "HasUniqueRoleAssignments"

$context.ExecuteQuery()

$outputString = ''

$siteGroups = $web.SiteGroups

$context.Load($web.AssociatedOwnerGroup)

$context.ExecuteQuery()

$ownersGroup = $siteGroups.GetByName($web.AssociatedOwnerGroup.Title)

$context.Load($ownersGroup)

$context.ExecuteQuery()

$ownersGroupUsers = $ownersGroup.Users

$context.Load($ownersGroupUsers)

$context.ExecuteQuery()

$ownersGroupUsers | ForEach-Object {$outputString += $_.Email + ';' }

$rows = $sheet.UsedRange.Rows.Count + 1

$sheet.cells.Item($rows ,1) = $web.Url

$sheet.cells.Item($rows ,2) = $web.HasUniqueRoleAssignments.ToString()

$sheet.cells.Item($rows ,3) = $outputString

$outputString = ''

}

}

Get-SPOWebs -Url $siteURL -Credential $clientContext.Credentials

&nbsp;

<span style="font-size: medium"></span>]]></content:encoded>
    </item>
    <item>
      <title>SharePoint Online - Setting custom home page in Site Collection and in Sub-Sites</title>
      <link>https://docs.microsoft.com/archive/blogs/chandru/sharepoint-online-setting-custom-home-page-in-site-collection-and-in-sub-sites</link>
      <pubDate>Wed, 03 Aug 2016 18:11:05 GMT</pubDate>
      <dc:creator><![CDATA[ChandrasekarN]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chandru/?p=1373</guid>
      <description><![CDATA[In SharePoint Online, using PNP’s Remote Site Provisioning approach you can request and create...]]></description>
      <content:encoded><![CDATA[<span style="font-size: medium">In SharePoint Online, using PNP’s <a href="https://github.com/OfficeDev/PnP/tree/dev/Solutions/Provisioning.Framework.Cloud.Async">Remote Site Provisioning</a> approach you can request and create customized site collections.  As part of site collection creation process, one of the option could be to upload custom page and set it as default welcome page for the Site Collection.  As part of site provisioning, if you have sub-sites created as well, you may want to set the same custom page as your sub-sites welcome page.  </span>

&nbsp;

<strong><span style="text-decoration: underline">Setting  SiteCollection’s Welcome Page</span></strong>
<div class="csharpcode">
<pre class="alt"><span style="font-family: Calibri;font-size: medium">var wikiPages = web.Lists.GetByTitle(<span class="str">"Pages"</span>);</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">web.Context.Load(wikiPages);</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">web.Context.ExecuteQuery();</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">Microsoft.SharePoint.Client.File wikiFile = wikiPages.RootFolder.GetFile(<span class="str">"CustomDefault-page.aspx"</span>);</span></pre>
<pre class="alt"><span style="font-family: Calibri"><span style="font-size: medium"><span class="kwrd">if</span> (wikiFile.CheckOutType == CheckOutType.None)</span></span></pre>
<pre><span style="font-family: Calibri;font-size: medium">   wikiFile.CheckOut();</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium"> web.Context.Load(wikiFile);</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">web.Context.ExecuteQuery();</span><span style="font-family: Calibri;font-size: medium"> </span></pre>
<pre><span style="font-family: Calibri;font-size: medium"> var wikiPage = wikiFile.ListItemAllFields;</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium"> web.Context.Load(wikiPage);</span></pre>
<pre><span style="font-family: Calibri;font-size: medium"> web.Context.ExecuteQuery();</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium"> wikiPage[<span class="str">"PublishingPageLayout"</span>] = web.ServerRelativeUrl + <span class="str">"/_catalogs/masterpage/PageFromDocLayout.aspx, Body only"</span>;</span></pre>
<pre><span style="font-family: Calibri;font-size: medium"> wikiPage.Update();</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium"> </span><span style="font-family: Calibri;font-size: medium"> wikiFile.CheckIn(<span class="kwrd">string</span>.Empty, CheckinType.MajorCheckIn);</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium"> web.Context.Load(wikiFile);</span></pre>
<pre><span style="font-family: Calibri;font-size: medium"> web.Context.ExecuteQuery();</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium"> </span><span style="font-family: Calibri"><span style="font-size: medium"> <span class="rem">//Set Welcome Home Page</span></span></span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium"> var rootFolder = web.RootFolder;</span></pre>
<pre><span style="font-family: Calibri;font-size: medium"> rootFolder.WelcomePage = <span class="str">"Pages/CustomDefault-page.aspx"</span>;</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium"> rootFolder.Update();</span></pre>
<pre><span style="font-family: Calibri;font-size: medium"> web.Context.ExecuteQuery();


</span></pre>
</div>
<strong><span style="text-decoration: underline">Setting  Sub-Site’s Welcome Page</span></strong>
<div class="csharpcode">
<pre class="alt"><span style="font-family: Calibri;font-size: medium"> FileCreationInformation newFile = <span class="kwrd">new</span> FileCreationInformation();</span></pre>
<pre><span style="font-family: Calibri;font-size: medium"> ctx.Load(hostWeb);</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium"> ctx.ExecuteQuery();</span></pre>
<pre><span style="font-family: Calibri;font-size: medium"> Microsoft.SharePoint.Client.File file = hostWeb.GetFileByServerRelativeUrl(hostWeb.ServerRelativeUrl + <span class="str">"/Pages/CustomDefault-page.aspx"</span>);</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium"> ClientResult&lt;Stream&gt; data = file.OpenBinaryStream();</span></pre>
<pre><span style="font-family: Calibri;font-size: medium"> hostWeb.Context.Load(file);</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium"> hostWeb.Context.ExecuteQuery();</span></pre>
<pre><span style="font-family: Calibri;font-size: medium"> <span class="kwrd">if</span> (data != <span class="kwrd">null</span>)</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium"> {</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">     <span class="kwrd">using</span> (var memory = <span class="kwrd">new</span> MemoryStream())</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">      {
</span><span style="font-family: Calibri;font-size: medium">          <span class="kwrd">byte</span>[] buffer = <span class="kwrd">new</span> <span class="kwrd">byte</span>[file.Length];</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">          <span class="kwrd">int</span> nread = 0;</span><span style="font-family: Calibri;font-size: medium"> </span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">          <span class="kwrd">while</span> ((nread = data.Value.Read(buffer, 0, buffer.Length)) &gt; 0)
</span><span style="font-family: Calibri;font-size: medium">          {
</span><span style="font-family: Calibri;font-size: medium">              memory.Write(buffer, 0, nread);
</span><span style="font-family: Calibri;font-size: medium">          }</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">           memory.Seek(0, SeekOrigin.Begin);</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">           StreamReader fsReader = <span class="kwrd">new</span> StreamReader(memory);</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">           <span class="kwrd">byte</span>[] contents = <span class="kwrd">null</span>;</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">           <span class="kwrd">using</span> (Stream fStream = fsReader.BaseStream)</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">            {</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">                contents = <span class="kwrd">new</span> <span class="kwrd">byte</span>[fStream.Length];</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">                fStream.Read(contents, 0, (<span class="kwrd">int</span>)fStream.Length);</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">                 fStream.Close();</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">               }</span><span style="font-family: Calibri;font-size: medium"> </span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">              newFile.Content = contents;</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">              newFile.Url = <span class="str">"CustomDefault-page.aspx"</span>;</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">              newFile.Overwrite = <span class="kwrd">true</span>;</span><span style="font-family: Calibri;font-size: medium"> </span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">              var wikiPages = newWeb.Lists.GetByTitle(<span class="str">"Pages"</span>);</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">              newWeb.Context.Load(wikiPages);</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">              newWeb.Context.ExecuteQuery();</span><span style="font-family: Calibri;font-size: medium"> </span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">              Microsoft.SharePoint.Client.File wikiFile = wikiPages.RootFolder.Files.Add(newFile);</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">              newWeb.Context.Load(wikiFile);</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">              newWeb.Context.ExecuteQuery();</span><span style="font-family: Calibri;font-size: medium"> </span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">              wikiFile.CheckIn(<span class="kwrd">string</span>.Empty, CheckinType.MajorCheckIn);</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">              newWeb.Context.Load(wikiFile);</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">              newWeb.Context.ExecuteQuery();</span><span style="font-family: Calibri;font-size: medium"> </span></pre>
<pre class="alt"><span style="font-family: Calibri"><span style="font-size: medium">              <span class="rem">//Set Welcome Home Page</span></span></span></pre>
<pre><span style="font-family: Calibri;font-size: medium">              var rootFolder = newWeb.RootFolder;</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">              rootFolder.WelcomePage = <span class="str">"Pages/CustomDefault-page.aspx"</span>;</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">              rootFolder.Update();</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">              newWeb.Context.ExecuteQuery();</span></pre>
<pre><span style="font-family: Calibri;font-size: medium">       }</span></pre>
<pre class="alt"><span style="font-family: Calibri;font-size: medium">    }</span></pre>
</div>]]></content:encoded>
    </item>
    <item>
      <title>SharePoint Online - Securing Add-in Principals</title>
      <link>https://docs.microsoft.com/archive/blogs/chandru/sharepoint-online-securing-add-in-principals</link>
      <pubDate>Thu, 03 Mar 2016 18:50:08 GMT</pubDate>
      <dc:creator><![CDATA[ChandrasekarN]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chandru/?p=1391</guid>
      <description><![CDATA[For the remote components of a provider-hosted SharePoint Add-in to interact with SharePoint using...]]></description>
      <content:encoded><![CDATA[For the remote components of a provider-hosted SharePoint Add-in to interact with SharePoint using OAuth, the add-in must first register with the Azure ACS cloud-based service and the SharePoint App Management Service of the tenancy. The registration involves creating new Client ID/Secret and other add-in specific details. After you register your add-in, it has an add-in identity and is a security principal, referred to as an add-in principal. When you install your add-in, SharePoint administrators can retrieve information about that particular add-in principal. The Client ID/Secret values need to be entered in configuration file of the application. Anyone who has access to the file system of the config file location can read these values. Using these values, they can build their own application and do anything in the SharePoint they want to (though its only restricted to app permissions defined for the app principal). This can become a big security threat especially if the app is given app-only policy permission.

This is a governance problem. Organization needs to have well defined governance on the deployment process, person responsible in making the changes in the configuration file and so on. If the config file is not well protected enough, it can become a problem. To address this scenario, we need to secure the app principle itself, so that even if someone gets access to these principles they shouldn't be able to do anything with it. The idea is to encrypt the key values using Triple-DES algorithm at Machine level. Using the encrypted value generated in one machine we can't decrypt the value in another machine, it has to be decrypted in the same machine. When an application calls the DPAPI encryption routine, it can specify an optional secondary entropy ("secret" bytes) that will have to be provided by an application attempting to decrypt data.
<h3>Encryption</h3>
<ul>
	<li>Enter the Client ID or the Secret value in Client ID/Secret text box.</li>
	<li>Entropy key is optional field.</li>
	<li>Choose the scope as Local Machine (this is the default value)</li>
	<li>Click Encrypt button to get the encrypted text value and hit copy text to copy the values.</li>
</ul>
<a href="https://msdnshared.blob.core.windows.net/media/2016/03/115.png"><img class="alignnone size-full wp-image-1411" src="https://msdnshared.blob.core.windows.net/media/2016/03/115.png" alt="1" width="571" height="353" /></a>

&nbsp;
<h3>Validation</h3>
To validate the encrypted text, without altering any values, click the Decrypt button and you should see the original value of the ID/Secret given.

<a href="https://msdnshared.blob.core.windows.net/media/2016/03/32.png"><img class="alignnone size-full wp-image-1422" src="https://msdnshared.blob.core.windows.net/media/2016/03/32.png" alt="3" width="572" height="358" /></a>

<span class="Apple-style-span" style="color: #000000;text-indent: 0px;letter-spacing: normal;border-collapse: separate"><span class="Apple-style-span">If the value is tampered or if you try to use the encrypted text value in a different machine, the decryption will fail.</span></span>

<a href="https://msdnshared.blob.core.windows.net/media/2016/03/43.png"><img class="alignnone size-full wp-image-1431" src="https://msdnshared.blob.core.windows.net/media/2016/03/43.png" alt="4" width="570" height="353" /></a>

The encrypted values has to be entered in configuration file of the add-in application.  In the Tokenhelper class file, the encrypted values has to be decrypted.

<span style="text-decoration: underline">Sample code in Tokenhelper.cs</span>

private static SecureString stringClientSecret = EncryptionUtility.DecryptStringWithDPAPI(WebConfigurationManager.AppSettings.Get("ClientSecret"));

private static readonly string ClientSecret = EncryptionUtility.ToInsecureString(stringClientSecret);

&nbsp;

Download complete solution - <a href="https://msdnshared.blob.core.windows.net/media/2016/03/Governance.AddInSecurity.zip">Governance.AddInSecurity</a>

&nbsp;

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>SharePoint Online–CSOM Change Access Requests Settings</title>
      <link>https://docs.microsoft.com/archive/blogs/chandru/sharepoint-onlinecsom-change-access-requests-settings</link>
      <pubDate>Thu, 31 Dec 2015 18:06:19 GMT</pubDate>
      <dc:creator><![CDATA[ChandrasekarN]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chandru/2015/12/31/sharepoint-onlinecsom-change-access-requests-settings/</guid>
      <description><![CDATA[The Access Request in the Site settings &gt; Site permissions is a feature which allows people to...]]></description>
      <content:encoded><![CDATA[<p>The Access Request in the Site settings &gt; Site permissions is a feature which allows people to request access to content that they do not currently have permission to see. The setting that allows members to share the site and individual files and folders doesn’t overwrite the &quot;Manage permissions&quot; permission level, it works with permission level.&#160; When you select the &quot;Allow members to share the site and individual files and folders&quot; setting, the site members can send an invitation to the other users who have no permission, but this invitation will not take effect until the site owner approve it. As a site owner, you can go to Site settings &gt; Access requests and invitations to approve or reject the invitation. </p>  <p><strong><font size="3">Default setting:</font></strong></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/4810.image_3BA05F2F.png"><font size="3"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/4760.image_thumb_2957986D.png" width="662" height="177" /></font></a></p>  <p>&#160;</p>  <p>You can change these settings programmatically using CSOM.&#160; </p>  <p>To uncheck <em>Allow Members to share the site and invite others</em>, use this code;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </p>  <p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // web is Microsoft.SharePoint.Client.Web object</p>  <p><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; web.Context.Load(web, w =&gt; w.MembersCanShare);&#160;&#160; </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; web.Context.ExecuteQuery(); </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; web.MembersCanShare = false; </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; web.Update(); </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; web.Context.Load(web, w =&gt; w.MembersCanShare); </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; web.Context.ExecuteQuery();</strong></p>  <p><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; web.Context.Load(web, w =&gt; w.AssociatedMemberGroup.AllowMembersEditMembership); </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; web.Context.ExecuteQuery(); </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; web.AssociatedMemberGroup.AllowMembersEditMembership = false; </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; web.AssociatedMemberGroup.Update(); </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; web.Context.Load(web, w =&gt; w.AssociatedMemberGroup.AllowMembersEditMembership); </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; web.Context.ExecuteQuery();</strong></p>  <p>To set a custom email address for <em>Allow Access Requests</em>, for e.g. email address of Site Owner, use this code;&#160; <em>RequestAccessEmail</em> property is available from Version <strong>16.1.4727.1200 </strong>onwards<strong>.&#160; </strong>You can find the latest CSOM package for SharePoint online from the <a href="https://www.nuget.org/packages/Microsoft.SharePointOnline.CSOM">NuGet gallery</a> with an id of Microsoft.SharePointOnline.CSOM</p>  <p><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; clientContext.Load(clientContext.Web, w =&gt; w.RequestAccessEmail); </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; clientContext.ExecuteQuery(); </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; clientContext.Web.RequestAccessEmail = clientContext.Site.Owner.Email; </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; clientContext.Web.Update(); </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; clientContext.Load(clientContext.Web, w =&gt; w.RequestAccessEmail); </strong><b>     <br /></b><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; clientContext.ExecuteQuery();</strong></p>  <p>&#160;</p>  <p><strong><font size="3">Custom setting using CSOM:</font></strong></p>  <p><strong><font size="3"></font></strong></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/8267.image8_17376E77.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;padding-right: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/7206.image8_thumb_02487CB5.png" width="663" height="172" /></a></p>]]></content:encoded>
    </item>
    <item>
      <title>SP 2013 – PowerShell to Modify Help Setting on Site Collection</title>
      <link>https://docs.microsoft.com/archive/blogs/chandru/sp-2013-powershell-to-modify-help-setting-on-site-collection</link>
      <pubDate>Sat, 14 Jun 2014 19:52:11 GMT</pubDate>
      <dc:creator><![CDATA[ChandrasekarN]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chandru/2014/06/14/sp-2013-powershell-to-modify-help-setting-on-site-collection/</guid>
      <description><![CDATA[Let’s say we want to enable/disable any of the help collection options available under Site...]]></description>
      <content:encoded><![CDATA[<p><font size="3" face="Calibri"></font></p>  <p><font size="3" face="Calibri">Let’s say we want to enable/disable any of the help collection options available under Site Collection Administration settings.&#160; This can be done using <a href="https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.help.spsiteextension(v=office.15).aspx" target="_blank">SPSiteExtension</a> class which contains all help related extension methods for the SPSite object. </font></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/2746.image_2B231A36.png"><font color="#000000" size="3" face="Calibri"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/1856.image_42512565.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/5635.image_thumb_6A10A0B8.png" width="642" height="278" /></a></font></a><font size="3" face="Calibri"> </font></p>  <p><font size="3" face="Calibri">Here is a simple script to disable Central Administration help</font></p>  <p><strong><font size="3" face="Calibri">[System.Reflection.Assembly]::LoadWithPartialName(&quot;Microsoft.SharePoint.Help&quot;)       <br />$site = Get-SPSite </font><font size="3" face="Calibri"><font color="#000000">https://2013-SP</font> </font>      <br /><font size="3" face="Calibri">[Microsoft.SharePoint.Help.SPSiteExtension]::DeactivateHelpCollection($site, &quot;WSSCentralAdmin&quot;)</font></strong></p>  <p><font size="3" face="Calibri">To activate and deactivate use <a href="https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.help.spsiteextension.activatehelpcollection(v=office.15).aspx" target="_blank">ActivateHelpCollection</a> and <a href="https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.help.spsiteextension.deactivatehelpcollection(v=office.15).aspx" target="_blank">DeactivateHelpCollection</a> method respectively. </font></p>  <p><font size="3" face="Calibri">To get the internal names of all those help collection properties, use the cmdlet&#160; </font><font size="3" face="Calibri"><a href="https://technet.microsoft.com/en-us/library/ff607790(v=office.15).aspx" target="_blank">Get-SPHelpCollection</a></font></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/7384.clip_image001_308D90C1.png"><img title="clip_image001" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="clip_image001" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/6305.clip_image001_thumb_131B3FB5.png" width="638" height="234" /></a></p>  <p><font size="3" face="Calibri"></font></p>  <p><font size="3" face="Calibri"></font></p>  <p><font size="3" face="Calibri">&#160;</font></p>  <p><font size="3" face="Calibri"></font></p>]]></content:encoded>
    </item>
    <item>
      <title>SharePoint 2013 : Manage Other User Profiles</title>
      <link>https://docs.microsoft.com/archive/blogs/chandru/sharepoint-2013-manage-other-user-profiles</link>
      <pubDate>Tue, 10 Dec 2013 13:05:32 GMT</pubDate>
      <dc:creator><![CDATA[ChandrasekarN]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/chandru/2013/12/10/sharepoint-2013-manage-other-user-profiles/</guid>
      <description><![CDATA[SharePoint gives an option in UPSA to manage the user profiles of other users (like editing basic...]]></description>
      <content:encoded><![CDATA[<p><font size="3" face="Calibri"></font></p>  <p><font size="3" face="Calibri">SharePoint gives an option in UPSA to manage the user profiles of other users (like editing basic or contact information) in their mysite.&#160; To edit other users profile, we need to first give “Manage Profiles” permission to a user (who wants to manage) under UPSA.</font></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/6371.image_07CAD791.png"><font size="3" face="Calibri"></font></a></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/6371.image_07CAD791.png"><font size="3" face="Calibri"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/7875.image_0E11AE1F.png"><img title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/7607.image_thumb_124085B9.png" width="501" height="319" /></a></font></a></p>  <p>&#160;</p>  <p>&#160;</p>  <p><font size="3" face="Calibri"></font></p>  <p><font size="3" face="Calibri">Sometimes you might get UserNotFoundException when you access the user’s EditProfile.aspx page even though you have Manage Profiles permission.</font></p>  <p><font size="3" face="Calibri"></font></p>  <p><font size="3" face="Calibri"></font></p>  <p><font size="3" face="Calibri"></font></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/7028.image_4A12C9DC.png"><img title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/6038.image_thumb_459C4915.png" width="559" height="46" /></a></p>  <p>&#160;</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/5554.image_493A63F2.png"><img title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/05/31/metablogapi/1261.image_thumb_6F9C473D.png" width="557" height="138" /></a></p>    <p><font size="3" face="Calibri"></font></p>  <p><font size="3" face="Calibri">You get this error if the user information is not found in UserInfo Table.&#160; If the user has never logged in before then there won’t be any reference in the UserInfo table.&#160; So the profile can be edited by other user <strong><em>only if the actual user had logged into the site at least once</em></strong>.</font></p>]]></content:encoded>
    </item>
  </channel>
</rss>