Thursday, 13 December 2018

Power Shell Script to Export all existing sitecollection URLs and its site's URL in a SharePoint Online tenant to XML file

try
{
    Add-Type -Path "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.dll"
    Add-Type -Path "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.Runtime.dll"
    Add-Type -Path "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.Online.SharePoint.Client.Tenant.dll"
}
catch
{
    Write-Host "Problem in loading CSOM DLLs : $_.Exception.Message" -foregroundcolor black -backgroundcolor Red
    return
}

# Initialize client context
$adminURL = Read-Host -Prompt "Enter Tenant Admin URL:"
$username = Read-Host -Prompt "Enter user name:"
$password = Read-Host -Prompt "Enter password:" -AsSecureString
#$sideLoadingGuid = new-object System.Guid "AE3A1339-61F5-4f8f-81A7-ABD2DA956A7D"


try{
        function Get-SPOWebs($webURL){
            #Get Web information and subsites
            $clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($webURL)
            $clientContext.Credentials = $credentials
            $Web = $clientContext.Web
            $clientContext.Load($Web)
            $clientContext.Load($Web.Webs)  
            $clientContext.executeQuery()
 
            #Do something with the current sub-site
            #Write-host $Web.URL
 
            #Iterate through each subsite in the current web
            foreach ($Subweb in $Web.Webs)
            {
                if($Subweb.AppInstanceId -eq [GUID]::Empty){
                
                    Write-Host 'Url:' $Subweb.url
                    # Append as child to an existing node
                    [System.XML.XMLElement]$newXmlSiteURLElement=$oXMLRoot.appendChild($xmlDoc.CreateElement("SiteURL"))
                    $newXmlNameTextNode = $newXmlSiteURLElement.AppendChild($xmlDoc.CreateTextNode($Subweb.url));                    
           

                    #Call the function recursively to process all subsites underneaththe current web
                    Get-SPOWebs($Subweb.url)
                }
            }
        }
}
catch{
    Write-Host "$_.Exception.Message" -foregroundcolor black -backgroundcolor Red
    return
}

try
{
  # connect/authenticate to SharePoint Online and get ClientContext object.. 
  $clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($adminURL) 
  $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password) 
  $clientContext.Credentials = $credentials 
  
  # Enumerate all site collections
  $tenant = New-Object Microsoft.Online.SharePoint.TenantAdministration.Tenant($clientContext)  
  $props = $tenant.GetSiteProperties(0, $true)
  $clientContext.Load($props)
  $clientContext.ExecuteQuery()
   

        # Create a new XML File with sites root node
        [System.XML.XMLDocument]$xmlDoc=New-Object System.XML.XMLDocument        
        [System.XML.XMLElement]$oXMLRoot=$xmlDoc.CreateElement("sites")
        $xmlDoc.appendChild($oXMLRoot)                       

  foreach($sp in $props)
  {
            Write-Host 'Url:' $sp.Url

            # Append as child to an existing node
            [System.XML.XMLElement]$newXmlSiteURLElement=$oXMLRoot.appendChild($xmlDoc.CreateElement("SiteURL"))
            $newXmlNameTextNode = $newXmlSiteURLElement.AppendChild($xmlDoc.CreateTextNode($sp.Url));
                    
            #$sp.Url | out-file "C:\SiteCollectionList.xml"
   
            Get-SPOWebs($sp.Url)
  }                

        # Save File
        $xmlDoc.Save("c:\config1.xml")
}
catch
{
    Write-Host "$_.Exception.Message" -foregroundcolor black -backgroundcolor Red
    return
}

Switching Between New And Classic SharePoint Document Library Experiences

Applies To: SharePoint Online , SharePoint Online admin center

You may notice a change in the look and navigation of your document libraries and lists. This new experience is faster, has additional phone and tablet features, and simpler navigation. As a document library or list owner, site owner, or administrator, you may want to switch the default experience back to the previous (classic view) for a time. Keep in mind that users can change the experience in specific libraries or sites back to new if they choose.

Following are the Steps to change the New Library experience to classic mode:

1.Copy the following code and paste it into a text editor, such as Notepad.

Add-Type -Path "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.Runtime.dll"
$MyCredentials = Get-Credential 
#Connect-SPOService -Url https://prakashinfotech-admin.sharepoint.com -credential $MyCredentials
$webUrl = 'https://prakashinfotech.sharepoint.com/sites/Form10/'
Write-Host "Press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
[Microsoft.SharePoint.Client.ClientContext]$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($webUrl)
$clientContext.Credentials =  New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($MyCredentials.UserName,$MyCredentials.Password)
$site = $clientContext.Site;
$clientContext.load($site);
$sitefeatureguid = new-object System.Guid "E3540C7D-6BEA-403C-A224-1A12EAFEE4C4"
$site.Features.Add($sitefeatureguid, $true, [Microsoft.SharePoint.Client.FeatureDefinitionScope]::None);
$clientContext.ExecuteQuery();

2. Save the file, naming it CustomActions.ps1.

NOTE: You can use a different file name, but you must save the file as an ANSI-encoded text file whose extension is .ps1

3.Change to the directory where you saved the file.

4 .At the Windows PowerShell command prompt, type the following command:

  ./CustomActions.ps1


Following are the Steps to change the  classic mode Library experience to New Library experience:

1.Copy the following code and paste it into a text editor, such as Notepad.


#set-executionpolicy unrestricted
Add-Type -Path "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.Runtime.dll"
$MyCredentials = Get-Credential 
Connect-SPOService -Url https://prakashinfotech-admin.sharepoint.com -credential $MyCredentials
$webUrl = 'https://prakashinfotech.sharepoint.com/sites/ProviderhostedappsRnd/'
[Microsoft.SharePoint.Client.ClientContext]$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($webUrl)
$clientContext.Credentials =  New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($MyCredentials.UserName,$MyCredentials.Password)
$site = $clientContext.Site;
$clientContext.load($site);
$sitefeatureguid = new-object System.Guid "E3540C7D-6BEA-403C-A224-1A12EAFEE4C4"
$site.Features.Remove($sitefeatureguid, $true);
$clientContext.ExecuteQuery();
#set-executionpolicy restricted

2. Save the file, naming it CustomActions.ps1.

NOTE: You can use a different file name, but you must save the file as an ANSI-encoded text file whose extension is .ps1

3.Change to the directory where you saved the file.

4 .At the Windows PowerShell command prompt, type the following command:

  ./CustomActions.ps1

Sunday, 11 February 2018

Steps to install SharePoint Provider Hosted Add-in on multiple sites automatically

Automating add-in/app installation:

Pre-requisites:

  • Add-in/app which being installed has to request tenant level permissions, which is the reason why this is not suitable model for store add-ins/apps
  • Add-in/app which being installed has to be instantiated or specifically trusted by the tenant administrator once before it can be pushed to sites
  • When you install add-in/app to the site, you will need to enable so called site loading feature.
  • SharePoint hosted Add-in/app will not work, this must be provider hosted Add-in/app.

Following are the steps:

  1. Add app in app catalog.
  2. Install App in one of the site collection and grant permission (can be app catalog site also) so that same App can be installed on all other site collection programmatically without need of granting permissions on each.
  3. Run power shell script(script is given below ) to install app on each of needed site in site collection. For new sites created, script has to run again for that specific new site.
  4. Now run the power shell script.(script is given below)
  5. Now give the following information:·         
  6. Enter URL: <Url of your site collection>
  7. Enter User Name: <Valid User name the sitecollection>
  8. Enter Password: <Password>
  9. Enter app file’s Path: <Location of the app file where it is stored on your machine>
  10. Enter app config file’s Path: <Location of the app configfile where it is stored on your machine> it is xml file which contains the List of site’s relative Urls on where you want to install the app. Format for this file is shown below.
                    Name of this file: AppConfig.xml


Power Shell Script:


try
{
    $loadInfo1 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
    $loadInfo2 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
}
catch
{
    Write-Host "Problem in loading CSOM DLLs : $_.Exception.Message" -foregroundcolor black -backgroundcolor Red
    return
}

$url = Read-Host -Prompt "Enter URL:"
$username = Read-Host -Prompt "Enter user name:"
$password = Read-Host -Prompt "Enter password:" -AsSecureString 
$appfilepath = Read-Host -Prompt "Enter app file's Path:"
$ConfigXmlPath = Read-Host -Prompt "Enter app config file's Path:"
$productId = New-Object Guid("<Replce this text with your app's product ID>") 
$Update = Read-Host -Prompt "Do you want to update the app if already installed? Enter [yes or no]:"
$sideLoadingGuid = new-object System.Guid "AE3A1339-61F5-4f8f-81A7-ABD2DA956A7D"
try
{
    Write-Host "Authenticate tenant site $url and get ClientContext object" -foregroundcolor black -backgroundcolor yellow
    $context = New-Object Microsoft.SharePoint.Client.ClientContext($url)
    $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)
    $context.Credentials = $credentials
    $web = $context.Web
    $site = $context.Site
    $context.Load($site)
 $context.ExecuteQuery()
 $site.Features.Add($sideLoadingGuid, $true, [Microsoft.SharePoint.Client.FeatureDefinitionScope]::None);
    $context.Load($web)
 $context.ExecuteQuery()
    Write-Host "Authentication to online site $url and 
 get ClientContext DLLS succeeful" -foregroundcolor black -backgroundcolor Green
}
catch
{
    Write-Host "Unable to authenticate to online site. Error : $_.Exception.Message" -foregroundcolor black -backgroundcolor Red
    return
}

try
{
 Write-Host "Reading the Config Values..." -ForegroundColor Green 
    # Get the Content of the Config Xml
    [Xml]$SiteConfig = Get-Content $ConfigXmlPath   
 #$site.Features.Add($sideLoadingGuid, $true, [Microsoft.SharePoint.Client.FeatureDefinitionScope]::None);  
  
 foreach( $SiteUrl in $SiteConfig.Sites.SiteURL) 
 { 
        try
        {
            $appIoStream = New-Object IO.FileStream($appfilepath,[System.IO.FileMode]::Open)
      $site = $context.Site
      $context.Load($site)
      $context.ExecuteQuery()
         $oweb = $context.Site.OpenWeb($SiteUrl)
      $context.Load($oweb)
            Write-Host "Processing is started on site :: $SiteUrl" 
      $context.ExecuteQuery()
      $appInstance = $oweb.LoadAndInstallApp($appIoStream)
      $context.Load($appInstance)
      $context.ExecuteQuery()
      #Write-Host $appInstance.Id 
            Write-Host "Installation started..." -ForegroundColor Green 
            
            $loopon = $true
            do
            {
                Start-Sleep -s 10
                $context.Load($AppInstance)
                $context.ExecuteQuery()
                
                if($AppInstance.Status -eq "Installed")
                {
                    $loopon = $false
                }
            }
            while ($loopon)
            Write-Host "Installed successfully." -ForegroundColor Green
        }
        catch [System.Management.Automation.MethodInvocationException]
        {
            #handle app already installed error
         #$appIoStream.Dispose()
            if($_.Exception.Message -match "An instance of this App already exists at the specified location.")
            {
                Write-Host "An instance of this app is already exists." -foregroundcolor yellow                
                if($Update -eq "Yes")
                {                    
                    $appinstances = [Microsoft.SharePoint.Client.AppCatalog]::GetAppInstances($Context,$oweb)
                    $Context.Load($appinstances) 
                    $Context.ExecuteQuery() 
                    foreach($instance in $appinstances) 
                    {
                        if($productId -eq $instance.ProductId) 
                        {
                            $AppInstanceId=$instance.Id
                            $appInst = $oweb.GetAppInstanceById($AppInstanceId)
                            Write-Host "Uninstallation of this app is started..." -ForegroundColor Green
                            $appInst.Uninstall()                                                   
                            try
                            {
                                $context.Load($appInst)
                                $context.ExecuteQuery()
                                $loopon = $true                                                                
                                do
                                {
                                    try{
                                        Start-Sleep -s 10
                                        $context.Load($appInst)
                                        $context.ExecuteQuery()  
                                    }
                                    catch [System.Management.Automation.MethodInvocationException]
                                    {
                                        $loopon = $false
                                    }                                                                                       
                                }
                                while ($loopon)
                                 Write-Host "Uninstalled successfully." -ForegroundColor Green
                            }
                            catch [Net.WebException] 
                            {
                                Write-Host "Failed to uninstall the app" $_.Exception.Message.ToString() -ForegroundColor Red
                            }                            
                            $appIoStream = New-Object IO.FileStream($appfilepath,[System.IO.FileMode]::Open)
                            $appInstance = $oweb.LoadAndInstallApp($appIoStream)    
                      $context.Load($appInstance)
                      $context.ExecuteQuery()                     
                            Write-Host "Installation is started..." -ForegroundColor Green             
                            $loopon = $true
                            do
                            {
                                Start-Sleep -s 10
                                $context.Load($AppInstance)
                                $context.ExecuteQuery()
                
                                if($AppInstance.Status -eq "Installed")
                                {
                                    $loopon = $false
                                }
                            }
                            while ($loopon)
                            Write-Host "Installed successfully." -ForegroundColor Green
                                
                        }
                    }                 
                }
            }
   else
   {
    Write-Host "Unable to Install App Error : $_.Exception.Message"
   }
        }
        catch
        {
                Write-Host "Unable to Install App Error : $_.Exception.Message"
        }
 }
    Write-Host "Installation process is done on all sites listed in XML file."
 $appIoStream.close()
 $appIoStream.Dispose()
}
catch
{
 $appIoStream.Dispose()
    Write-Host "Unable to Install App Error : $_.Exception.Message" -foregroundcolor black -backgroundcolor Red
    return
}