Summary
The PnP PowerShell command Get-PnPTenantSite to get all sites from the tenant takes longer time. Additionally, it does not have asynchronous ways to get the information in the Azure Durable Function.
This article uses the MS Graph API List Sites to get the sites. To use this API the following Application API permissions required for the Azure AD app.
Sites.Read.All, Sites.ReadWrite.All
Script
$StartMs = (Get-Date).Millisecond
# You will need Azure AD app with the following API permissions.
# Application Sites.Read.All
#
$ClientId = "TODO"
$ClientSecret = "TODO"
$tenantid = "TODO"
$path2File = 'C:\temp\test.txt' # Change this as you like.
## Get Auth Token ##
$headersAuth = @{
"Content-Type" = "application/x-www-form-urlencoded"
'Accept' = '*/*'
}
$body = $("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default" -f $ClientId, $ClientSecret)
$outhTokenUrl = $("https://login.microsoftonline.com/{0}/oauth2/v2.0/token" -f $tenantid)
$response = Invoke-RestMethod $outhTokenUrl -Method 'POST' -Headers $headersAuth -Body $body
$response | ConvertTo-Json
$tokenExpiryTime = (get-date).AddSeconds($response.expires_in)
##
## Make the first call with $filer to your tenant name ##
##
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Content-Type", "application/json")
$headers.Add("SdkVersion", "postman-graph/v1.0")
$headers.Add("Prefer", "apiversion=2.1")
$headers.Add("Authorization", $("Bearer {0}" -f $response.access_token) )
$response = Invoke-RestMethod 'https://graph.microsoft.com/v1.0/sites?$filter=siteCollection/hostname eq ''{CHANGE TO YOUR TENANT NAME}.sharepoint.com''' -Method 'GET' -Headers $headers
$response | ConvertTo-Json
## Check if there are more sites to fetch...
while ( $response.'@odata.nextLink' -ne $null )
{
## iterate on the response and write the site url to the file.
foreach ( $val in $response.Value )
{
Write-Output $("{0}" -f $val.webUrl)
Add-Content -Path $path2File -Value $val.webUrl
}
# check if the token expired, if it did get a new one.
if ( (get-date) -gt $tokenExpiryTime )
{
$response = Invoke-RestMethod "https://login.microsoftonline.com/$($tenantid)/oauth2/v2.0/token" -Method 'POST' -Headers $headers -Body $body
$response | ConvertTo-Json
$tokenExpiryTime = (get-date).AddSeconds($response.expires_in)
# modify header with the new token
$headers = @{
"Content-Type" = "application/json"
"Authorization" = $("Bearer {0}" -f $response.access_token)
}
}
# first store the data of Web URL to the file.
$response = Invoke-RestMethod $response.'@odata.nextLink' -Method 'GET' -Headers $headers
$response | ConvertTo-Json
}
$EndMs = (Get-Date).Millisecond
WriteHost "This script took $($EndMs - $StartMs) milliseconds to run."
Conclusion
Using MS Graph API you can overcome to get the list of all sites within your tenant. This can be done using the Get-PnPTenantSite but it has overheads if you just want the site urls of all sites.