Discover where are your BindTuning products installed

In some instances you may want to verify where, on your tenant,  you have installed any BindTuning products, comprising both the Design (themes) and Build (web part) features. 

Being that accessing each site collection and verifying its correspondent associated solutions, can be a daunting process, BindTuning has devised a PowerShell script that will allow you to loop through all your pre-existing site collections automatically, listing the concrete number of BindTuning products installed on your environment. 

Note: This same script was devised to work with SharePoint Online tenants. 

Before we begin

Before running the PowerShell script below, note that some pre-requisites may be appliable:

  • Windows PowerShell v4.0 (or above)
  • SharePoint PnP cmdlets; 
  • Windows Management Framework.

If, however, the pre-requisites are not fulfilled, the provided script will prompt you to proceed with the corresponding modules installation and/or version upgrade. 

Likewise, and considering the script to access your SharePoint Administration Center, be sure to run it utilizing a SharePoint (Tenant) Admin account.

Running the script

After all the dependencies have been sorted out, proceed to copy the PowerShell script below, pasting it on a newly created file with the .ps1 extension, so as to create a file with the following naming convention myScriptName.ps1.

cls

pushd (Split-Path -Path $MyInvocation.MyCommand.Definition -Parent)

$ErrorActionPreference = "Stop"
$pnpRequiredVersion = [Version]"3.25.2009.1"
$PnPBinFolder = "{0}\BTResources\" -f $env:temp
$today = [DateTime]::UtcNow
$reportsFolder = ".\Reports";

if(!(Test-Path $reportsFolder)) { New-Item -Path ".\Reports" -ItemType Directory | Out-Null }

$fileReportPath = Join-Path $reportsFolder ("TENANT APP CATALOG_{0:yyyyMMdd-HHmmss}.log" -f $today)

function Main(){

    try{
        checkPnPCmdlets    

        #connecto to -admin
        $tenantName = Read-Host ("`nPlease enter the SharePoint Tenant name (https://[TENANT].sharepoint.com")
        $loginUrl = ("https://{0}-admin.sharepoint.com/" -f $tenantName)        

        connectTo $loginUrl

        $webInfo = Get-PnPWeb
        $tenantApps = Get-PnPApp -Scope Tenant

        if($tenantApps.Count){
            "***** Tenant App Catalog *****" | Out-File -FilePath $fileReportPath -Append -NoClobber
            $tenantApps.ForEach({[PSCustomObject]$_}) | Format-Table -AutoSize -Property Title, AppCatalogVersion | Out-File -FilePath $fileReportPath -Append -NoClobber
        }    

        [System.Collections.ArrayList]$allSitesList = Get-PnPTenantSite
        $allSites = New-Object System.Collections.ArrayList
		$allSitesList | Where-Object { $_.Url -match $tenantName } | %{
			$allSites.Add($_) | Out-Null
		}
				
        Write-Host ("Found {0} sites" -f $allSites.Count)      

        foreach($site in $allSites){
			Write-Host ($site.Url)
			
            $fileReportPath = Join-Path $reportsFolder ("{0}_{1:yyyyMMdd-HHmmss}.log" -f ($site.Url -replace "https://","" -replace "/","_"), $today)	
			
			#connect on each site
            connectTo $site.Url
			
            try {
                $siteApps = Get-PnPApp -Scope Site
                Write-Host (" # {0} apps found" -f $siteApps.Count)

                if($siteApps.Count){
                    "-> Modern Apps <-" | Out-File -FilePath $fileReportPath -Append -NoClobber
                    $siteApps.ForEach({[PSCustomObject]$_}) | Format-Table -AutoSize -Property Title, AppCatalogVersion | Out-File -FilePath $fileReportPath -Append -NoClobber
                }
            } catch {
                #no app catalog
				if($_.ErrorDetails.Message -match "Attempted to perform an unauthorized operation.") {
					Write-Host (" # Unauthorized - The user does not have permissions to the site collection {0}" -f $site.Url)
				} else {
					Write-Host (" # No App Catalog found")
				}
            }

            if(!(isModern $site.Template)) {
                # get solutions
                $siteSolutions = $null
                $listPath = "/_catalogs/solutions/"
                $fieldsArr = @("FileLeafRef","SolutionId","Status","Created","Modified","SolutionTitle")

                try{
                    $siteSolutions = Get-PNPListItem -List $listPath -fields $fieldsArr
                    Write-Host (" # {0} solutions found" -f $siteSolutions.Count)

                    if($siteSolutions.Count){
                        "-> Classic Solutions <-" | Out-File -FilePath $fileReportPath -Append -NoClobber
                        $siteSolutions.FieldValues.FileLeafRef | Format-Table -AutoSize | Out-File -FilePath $fileReportPath -Append -NoClobber
                    }
                } catch { }
            }
        }               
    } catch {
        errorMessage $_
        closeWindow
    }

    Write-Host "`nProcess completed."
    closeWindow
}

function connectTo($loginUrl){
    Write-Host ("- Connecting to: {0} ... " -f $loginUrl) -NoNewline    

    #- Connect to site
    try{
        $wpref = $WarningPreference
        $WarningPreference = 'SilentlyContinue'        

        #check if was already connected

        if(isSharePointOnline $loginUrl){
            Connect-PnPOnline -Url $loginUrl -NoTelemetry -useWebLogin
        }else{
            try{ $connection = Get-PnPConnection } catch {}
                    
            if($connection){
                $loginUsername = $connection.PSCredential.UserName
                $secpasswd = $connection.PSCredential.Password
                $userCreds = New-Object System.Management.Automation.PSCredential ($loginUsername, $secpasswd)

                Connect-PnPOnline -Url $loginUrl -Credentials $userCreds -NoTelemetry
            } else {
                Connect-PnPOnline -Url $loginUrl -Credentials (Get-Credential) -NoTelemetry
            }
        }

        $WarningPreference = $wpref

    } catch {
        errorMessage "Unable to connect."
    }

    successMessage "Done"
}

function checkPnPCmdlets(){
    $showPNPMenu = $false
    
    #check powershell version
    $PSversion = $PSVersionTable.PSVersion

    if(!$PSVersion){
        cls
        errorMessage "`n* Unable to check installed PowerShell version (Requires Windows Management Framework v4.0 installed)."
        errorMessage ("`n* Use option 5 to download it and install.")
		
        $showPNPMenu = $true
    } elseif($PSVersion.Major -lt 4) { 
        cls
        errorMessage ("`n* The installed PowerShell version is lower than the requirement (required: 4 or above , installed: {0})." -f $PSVersion)
        errorMessage ("`n* Use option 5 to download it and update.")

        $showPNPMenu = $true
    }

    #Check PnP Cmdlets
    if(!(Test-Path $PnPBinFolder)){ New-Item -Path $PnPBinFolder -Name "SharePointPnPPowerShellOnline" -ItemType "directory" | Out-Null }
    
    $PnPModule = ("{0}\SharePointPnPPowerShellOnline\{1}\SharePointPnPPowerShellOnline.psd1" -f $PnPBinFolder, $pnpRequiredVersion)

    if(Test-Path $PnPModule){
        Import-Module -Name $PnPModule -Force -Verbose:$false -DisableNameChecking -WarningAction SilentlyContinue
    }

    $PNPCmdlets = Get-Module SharePointPnPPowerShellOnline

    if(!$PNPCmdlets){
        cls
        errorMessage ("`n* SharePoint Patterns and Practices PowerShell Online (v$pnpRequiredVersion) Cmdlets not found to run this script.")
        errorMessage ("`n* Use option 1 to download them.")

        $showPNPMenu = $true
    } else {
        #check version
        if($PNPCmdlets[0].Version -lt $pnpRequiredVersion){
            errorMessage ("`n* SharePoint Patterns and Practices (PnP) Cmdlets installed are not at the required version to run this script.")
            Write-Host ("`n* Latest version installed: {0}" -f ($PNPCmdlets[0].Version).ToString())
            Write-Host ("* Required version: {0}" -f $pnpRequiredVersion.ToString())

            [string] $option="0"

            if(($option = Read-Host "Proceed with the update? (Y)es or (N)o") -match 'y') {
                try{
                    Write-Host "`n* Downloading 'SharePointPnPPowerShellOnline' (v$pnpRequiredVersion) module ... "
                    Save-Module SharePointPnPPowerShellOnline -path $PnPBinFolder -RequiredVersion $pnpRequiredVersion

                    Menu
                } catch {
                    throw $_
                }
            } else {
                closeWindow
            }
        }
    }

    if($showPNPMenu){
        errorMessage ("`nPlease, check the requirements before proceding with the installation.")

        # Menu
        Write-Host ("`n#--- Requirements ---#`n") 
        Write-Host ("1 - Download SharePoint PnP PowerShell Online (v{0}) Cmdlets  " -f $pnpRequiredVersion) -NoNewline 
        Write-Host "(Required)" -BackgroundColor Yellow -ForegroundColor Black
        Write-Host ""
        Write-Host "2 - Open Windows Management Framework v4.0 download page  " -NoNewline
        Write-Host "(Prerequisites - PowerShell version 4 or above )" -BackgroundColor Yellow -ForegroundColor Black
        Write-Host ""
        Write-Host "0 - Exit"

        [string] $option="0"
        $option = Read-Host "`nSelect option"

        switch($option){
            "1" { 
                Write-Host "`n* Downloading 'SharePointPnPPowerShellOnline' (v$pnpRequiredVersion) module ... "
                Save-Module SharePointPnPPowerShellOnline -path $PnPBinFolder -RequiredVersion $pnpRequiredVersion
                break
            }
            "2" { (New-Object -Com Shell.Application).Open('https://www.microsoft.com/en-us/download/details.aspx?id=40855'); checkPnPCmdlets; break }
            "0" { exit }
            default { cls }
        }
    }
}

function successMessage($message){
    Write-Host $message -BackgroundColor Green -ForegroundColor Black
}

function errorMessage($message){
    Write-Host $message -ForegroundColor Red
}

function warningMessage($message){
    Write-Host $message -BackgroundColor Yellow -ForegroundColor Black
}

function isModern($webTemplate){
    return (@("GROUP#0","SITEPAGEPUBLISHING#0","STS#3") -contains $webTemplate)
}

function isSharePointOnline($url){
    return $url -match ".+?\.sharepoint.com"
}

function closeWindow(){
    try{
        Write-Host "Press any key to close this window."
        $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
    } catch {}

    exit
}

& Main
  

While running the script, the only input necessary corresponds to your SharePoint tenant name. When prompted, provide the necessary information.

Considering a scenario where your tenant URL is similar to https://myTenant.sharepoint.com, be sure to input myTenant as the parameter.

mceclip0.png

The script will proceed to run automatically, listing all the present site collections, and their correlative number of installed BindTuning applications. 

run-script.png

 

 

Have more questions? Submit a request

Comments

BindTuning logo
Copyright Ⓒ 2021 Bind.
All rights reserved.
Privacy Policy
Cookie Policy
BindTuning
              Linkedin BindTuning Twitter BindTuning YouTube BindTuning Instagram BindTuning
              Facebook
Powered by Zendesk