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

        }

        

        $allSites = Get-PnPTenantSite

        Write-Host ("Found {0} sites" -f $allSites.Count)

        

        foreach($site in $allSites){

            $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(!(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

Powered by Zendesk