Get SharePoint files with MSGraph2

How to Get SharePoint Files with MSGraph with PowerShell

With the newest MSGraph module one has the capability to get SharePoint files with MSGraph. I recently figured out, how to fetch them in a recursed manner. In this article I want to share with you how to get SharePoint files with MSGraph. You will need to get the files with MSGraph, if you are thinking about to do following things:

  • Read/ Write/ Delete Metadata of SharePoint Files
  • Obtain DriveItem IDs, if you want to upload files to specific folders
  • Download specific SharePoint files
  • Assess the storage of your SharePoint libraries

What do you need to get SharePoint Files with MSGraph

You need to fulfil two requirements, so that you can get SharePoint files with MSGraph recursedly.

  1. You need to configure an Azure App registration with read permission to the SharePoint sites, where you want to obtain the files from. If you have never done this, follow my article, where I explain how to configure your Azure App registration for MSGraph access.
    How to configure Azure App registration for MS Graph | SPO Scripts
  2. Install the MSGraph module for PowerShell
    Install the Microsoft Graph PowerShell SDK | Microsoft Learn

Demo Setup

In my demo setup I have a SharePoint Library, where I have stored some files and folders. I am showcasing you, so that you can understand what you can expect from the solution. I have also some files in a folder, which will show that the solution is able to fetch folder items.

Get SharePoint Files with MSGraph
SharePoint Subfolder

I have created an Azure App registration with the Sites Read All permission. The authentication will be done with a self signed certificate.

Azure App Registration with MSGraph permission

Azure App Registration with certificate for authentication

How to Get all SharePoint Files with MSGraph in PowerShell (recursively)

Below you can find the PowerShell script to get all SharePoint files. I have created the function List-MgDriveItem in order to list the drive items of a drive. A drive item is either a file or a folder within a SharePoint Library You can adjust the function, if you want to have different attributes.

function List-MgDriveItem
{
    [CmdletBinding()]
    param (
        [Parameter()]
        $Drive,
        [Parameter()]
        $DriveItem
    )

    Try
    {
        if ($DriveItem.folder)
        {
            # Recurse in the folder to get the childitems of the folder
            $ChildItems = (Get-MgDriveItem -DriveId $Drive.Id -DriveItemId $DriveItem.Id  -ExpandProperty Children ).Children

            if ($ChildItems.Count -gt 0)
            {
                <# Action to perform if the condition is true #>
                $ChildItems | ForEach-Object { 
                    List-MgDriveItem -Drive $Drive -DriveItem (Get-MgDriveItem -DriveId $Drive.Id -DriveItemId $($_.Id) ) 
                }
            }

        }

            $Result = New-Object psobject -Property @{
            DriveItemName = $DriveItem.name;
            DriveitemSize   = $DriveItem.Size
        }
        return $Result
    }
    catch
    {
        Return $Error[0]
    }

}

A sample output of a folder driveitem looks like this:

PS C:\Users\Serka\OneDrive\Desktop\PS> $driveitem | Select-Object *

webUrl               : https://m365x04995906.sharepoint.com/sites/Remoteliving/Shared%20Documents/General
id                   : 01NLC4VWP4YR6WIO6O6JFIFTARZGEQZMAL
createdBy            : {[user, System.Collections.Hashtable], [application, System.Collections.Hashtable]}
lastModifiedBy       : {[user, System.Collections.Hashtable], [application, System.Collections.Hashtable]}
lastModifiedDateTime : 31.07.2023 12:17:50
name                 : General
folder               : {[childCount, 3]}
size                 : 4505145
fileSystemInfo       : {[lastModifiedDateTime, 31.07.2023 12:17:50], [createdDateTime, 31.07.2023 12:17:50]}
createdDateTime      : 31.07.2023 12:17:50
parentReference      : {[id, 01NLC4VWN6Y2GOVW7725BZO354PWSELRRZ], [path, /drives/b!kJV0CniHeUeAiju7m8Gl4ZmfCOoRAXJNrYB9wjbkfZ-Vmuw3EELGQ7bZlNIfSaf4/root:], [driveType, documentLibrary], [driveId, b!kJV0CniHeUeAiju7m8Gl4ZmfCOoRAXJNrYB9wjbkfZ-Vmuw3EELGQ7bZlNIfSaf4]…}
eTag                 : "{647DC4FC-CE3B-4AF2-82CC-11C9890CB00B},2"
cTag                 : "c:{647DC4FC-CE3B-4AF2-82CC-11C9890CB00B},0"
shared               : {[scope, users]}

A sample output of a file driveitem looks like this:

PS C:\Users\Serka\OneDrive\Desktop\PS> $driveitem | select-object * |Format-list

createdDateTime              : 19.08.2023 20:56:39
cTag                         : "c:{6C722880-DCC4-45F4-B64C-96805B32D473},2"
lastModifiedBy               : {[user, System.Collections.Hashtable]}
@microsoft.graph.downloadUrl : https://m365x04995906.sharepoint.com/sites/Remoteliving/_layouts/15/download.aspx?UniqueId=6c722880-dcc4-45f4-b64c-96805b32d473&Translate=false&tempauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAvbTM2NXgwNDk5NTkwNi5zaGFyZXBvaW50LmNvbUAxZjc5NWU5NS1jMDZiLTQxMDktOTI0ZS0zNTY5ZmRkZjQ5OWYiLCJpc3MiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAiLCJuYmYiOiIxNjk0OTc0NTMzIiwiZXhwIjoiMTY5NDk3ODEzMyIsImVuZHBvaW50dXJsIjoib0dEUzI3bnFpOEtUSHd5NHRaQ1NYVzE1Mk1KVGFMVkpZZmh0VUhBTVUrUT0iLCJlbmRwb2ludHVybExlbmd0aCI6IjE0MyIsImlzbG9vcGJhY2siOiJUcnVlIiwiY2lkIjoiVWxYbUJaczF1MHU4d3ZpSTFwTGhudz09IiwidmVyIjoiaGFzaGVkcHJvb2Z0b2tlbiIsInNpdGVpZCI6Ik1HRTNORGsxT1RBdE9EYzNPQzAwTnpjNUxUZ3dPR0V0TTJKaVlqbGlZekZoTldVeCIsImFwcF9kaXNwbGF5bmFtZSI6IlNQX1NlbnNpdGl2aXR5X0xhYmVscyIsIm5hbWVpZCI6IjkwNzQ3OTI1LTU1MGMtNDY1OC04NTBmLWIxOWQyNmVkMWE0M0AxZjc5NWU5NS1jMDZiLTQxMDktOTI0ZS0zNTY5ZmRkZjQ5OWYiLCJyb2xlcyI6ImFsbHNpdGVzLndyaXRlIiwidHQiOiIxIiwiaXBhZGRyIjoiMjAuMTkwLjE5MC4xMDMifQ.knKrUliPCxeMF4NQ2-3_FSAkEYRBD5nlTOvAVurT_gQ&ApiVersion=2.0
file                         : {[mimeType, image/png], [hashes, System.Collections.Hashtable]}
photo                        : {}
name                         : 2023-06-25 00_18_51-Alfahosting.de® • Meine Rechnungen and 2 more pages - Personal - Microsoft​ Edge.png
fileSystemInfo               : {[lastModifiedDateTime, 19.08.2023 20:56:39], [createdDateTime, 19.08.2023 20:56:39]}
id                           : 01NLC4VWMAFBZGZRG46RC3MTEWQBNTFVDT
shared                       : {[scope, users]}
image                        : {[width, 868], [height, 406]}
createdBy                    : {[user, System.Collections.Hashtable]}
size                         : 23175
eTag                         : "{6C722880-DCC4-45F4-B64C-96805B32D473},1"
lastModifiedDateTime         : 19.08.2023 20:56:39
webUrl                       : https://m365x04995906.sharepoint.com/sites/Remoteliving/Shared%20Documents/2023-06-25%2000_18_51-Alfahosting.de%C2%AE%20%E2%80%A2%20Meine%20Rechnungen%20and%202%20more%20pages%20-%20Personal%20-%20Microsoft%E2%80%8B%20Edge.png
parentReference              : {[id, 01NLC4VWN6Y2GOVW7725BZO354PWSELRRZ], [path, /drives/b!kJV0CniHeUeAiju7m8Gl4ZmfCOoRAXJNrYB9wjbkfZ-Vmuw3EELGQ7bZlNIfSaf4/root:], [driveType, documentLibrary], [driveId, b!kJV0CniHeUeAiju7m8Gl4ZmfCOoRAXJNrYB9wjbkfZ-Vmuw3EELGQ7bZlNIfSaf4]…}

Here you can find the PowerShell script to get all SharePoint files with MSGraph. Keep in mind that you replace the param block with the values from your tenant, app etc.

Param (
    $AppID = "90747925-550c-4658-850f-b19d26ed1a43", # Replace with the App ID of your App registration
    $Tenant = "1f795e95-c06b-4109-924e-3569fddf499f", # Replace with the Tenant ID
    $SiteID = "0a749590-8778-4779-808a-3bbb9bc1a5e1", # Replace it with the SiteID of your SharePoint Site https://m365x04995906.sharepoint.com/sites/Remoteliving/_api/site/id
    $LibraryName = "Documents", # Replace with the list name,
    $CertificatePath = "C:\Users\Serka\OneDrive\Desktop\PS\SPSitesReadAll.pfx", # Replace with the path to your certificate,
    $CertificatePassword = "XXX" # Replace with the password of your certificate
)

function List-MgDriveItem {
    [CmdletBinding()]
    param (
        [Parameter()]
        $Drive,
        [Parameter()]
        $DriveItem
    )
    
    if ($DriveItem.folder) {
        <# Action to perform if the condition is true #>
        Write-Output "Folder $($DriveItem.Name), size $($DriveItem.Size) `n"

        # Recurse in the folder to get the childitems of the folder
        $ChildItems = $null
        $ChildItems = (Get-MgDriveItem -DriveId $Drive.id -DriveItemId $DriveItem.id  -ExpandProperty Children ).Children

        if ($ChildItems.Count -gt 0) {
            <# Action to perform if the condition is true #>
            $ChildItems | ForEach-Object { 
                List-MgDriveItem -Drive $Drive -DriveItem (Get-MgDriveItem -DriveId $Drive.ID -DriveItemId $($_.Id) ) 
            }
        }
        
    }   
    elseif ($null -ne $DriveItem.file) {
        <# Action when this condition is true #>
        Write-Output "File $($DriveItem.Name), size $($DriveItem.Size) `n"
    }
}

#region prerequistes
Import-Module microsoft.graph.authentication

# Load the certificate from file
$Certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath, $CertificatePassword)

# Authenticate
Connect-MgGraph -ClientID $AppID -TenantId $Tenant -CertificateThumbprint $Certificate.Thumbprint
#endregion

#region main
# Get drive
$Drive = Get-MgSite -SiteId $SiteID -Property Drives -ExpandProperty Drives | Select-Object Drives -ExpandProperty Drives | Where-Object { $_.Name -eq $LibraryName }

# Get drive item
$DriveItems = Invoke-MgGraphRequest -Uri "v1.0/drives/$($Drive.ID)/root/children"

foreach ($DriveItem in $DriveItems.Value) {

    #Get All drivitems below root
    List-MgDriveItem -Drive $Drive -DriveItem $DriveItem
}

#
#endregion

As you can see below, the script populates the space ocupation for each SharePoint file/ folder.

Output of get SharePoint files for MSGraph

How to get DriveItemIDs for SharePoint Files?

I have modified the script, so that you can get all driveItemIDs for all SharePoint Files in your library. Below you can find the script with certificate based authentication.

Param 
(
    $AppId = "90747925-550c-4658-850f-b19d26ed1a43", # Replace with the App Id of your App registration
    $Tenant = "1f795e95-c06b-4109-924e-3569fddf499f", # Replace with the Tenant prefix
    $SiteId = "0a749590-8778-4779-808a-3bbb9bc1a5e1", # Replace it with the SiteId of your SharePoint Site https://m365x04995906.sharepoint.com/sites/Remoteliving/_api/site/Id
    $LibraryName = "Documents", # Replace with the list name,
    $CertificatePath = "C:\Users\Serka\OneDrive\Desktop\PS\SPSitesReadAll.pfx", # Replace with the path to your certificate,
    $CertificatePasswordPath = "C:\Users\Serka\OneDrive\Desktop\PS\SPSitesReadAll.key" # Replace with the path to the password of your certificate,
)

function List-MgDriveItem
{
    [CmdletBinding()]
    param (
        [Parameter()]
        $Drive,
        [Parameter()]
        $DriveItem
    )

    Try
    {
        if ($DriveItem.folder)
        {
            # Recurse in the folder to get the childitems of the folder
            $ChildItems = (Get-MgDriveItem -DriveId $Drive.Id -DriveItemId $DriveItem.Id  -ExpandProperty Children ).Children

            if ($ChildItems.Count -gt 0)
            {
                <# Action to perform if the condition is true #>
                $ChildItems | ForEach-Object { 
                    List-MgDriveItem -Drive $Drive -DriveItem (Get-MgDriveItem -DriveId $Drive.Id -DriveItemId $($_.Id) ) 
                }
            }

        }

            $Result = New-Object psobject -Property @{
            DriveItemName = $DriveItem.name;
            DriveitemId   = $DriveItem.Id;
            DriveId       = $Drive.Id;
            DriveItemURL  = $DriveItem.webUrl
        }
        return $Result
    }
    catch
    {
        Return $Error[0]
    }

}


# Load required Modules
Import-Module Microsoft.Graph.Authentication, Microsoft.Graph.Files

# Load the certificate from file
$CertificatePassword = (Import-Clixml -Path $CertificatePasswordPath).getnetworkcredential().Password
$Certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath, $CertificatePassword)

# Authenticate
Connect-MgGraph -ClientId $AppId -TenantId $Tenant -CertificateThumbprint $Certificate.Thumbprint -NoWelcome
 
#region prepare export

# Get drive
$Drive = Get-MgSite -SiteId $SiteId -Property Drives -ExpandProperty Drives | Select-Object Drives -ExpandProperty Drives | Where-Object { $_.Name -eq $LibraryName }

# Get drive item
$DriveItems = Invoke-MgGraphRequest -Uri "v1.0/drives/$($Drive.Id)/root/children"

$ItemExportRaw = New-Object System.Collections.Generic.List[object]

foreach ($DriveItem in $DriveItems.Value)
{
    #Get All drivitems below root
    $ItemExportRaw.Add( $(List-MgDriveItem -Drive $Drive -DriveItem $DriveItem))
}

$ItemExport = New-Object System.Collections.Generic.List[object]


$ItemExportRaw |ForEach-Object {

        $_ | ForEach-Object {$ItemExport.add($_)}    
}

$ItemExport
#endregion

If you want to use app secrets instead of certificate based authentication, you can use following script

Param 
(
    $AppId = "13b20636-5165-402e-aedc-5e05eeb4a57f", # Replace with the App Id of your App registration
    $Tenant = "b7b0953d-d866-4606-9199-7642f06a0b2e", # Replace with the Tenant prefix
    $SiteId = "2dfd508f-98ab-46ad-839b-f0435730c79a", # Replace it with the SiteId of your SharePoint Site https://m365x04995906.sharepoint.com/sites/Remoteliving/_api/site/Id
    $LibraryName = "Documenten" # Replace with the list name,
)

function List-MgDriveItem
{
    [CmdletBinding()]
    param (
        [Parameter()]
        $Drive,
        [Parameter()]
        $DriveItem
    )

    Try
    {
        if ($DriveItem.folder)
        {
            # Recurse in the folder to get the childitems of the folder
            $ChildItems = (Get-MgDriveItem -DriveId $Drive.Id -DriveItemId $DriveItem.Id  -ExpandProperty Children ).Children

            if ($ChildItems.Count -gt 0)
            {
                <# Action to perform if the condition is true #>
                $ChildItems | ForEach-Object { 
                    List-MgDriveItem -Drive $Drive -DriveItem (Get-MgDriveItem -DriveId $Drive.Id -DriveItemId $($_.Id) ) 
                }
            }

        }

            $Result = New-Object psobject -Property @{
            DriveItemName = $DriveItem.name;
            DriveitemId   = $DriveItem.Id;
            DriveId       = $Drive.Id;
            DriveItemURL  = $DriveItem.webUrl
        }
        return $Result
    }
    catch
    {
        Return $Error[0]
    }

}


# Load required Modules
Import-Module Microsoft.Graph.Authentication, Microsoft.Graph.Files

# Complie Client Credential
$ClientSecretCredential = Get-Credential($AppID)

# Authenticate
Connect-MgGraph -TenantId $Tenant -ClientSecretCredential $ClientSecretCredential -NoWelcome

#region prepare export

# Get drive
$Drive = Get-MgSite -SiteId $SiteId -Property Drives -ExpandProperty Drives | Select-Object Drives -ExpandProperty Drives | Where-Object { $_.Name -eq $LibraryName }

# Get drive item
$DriveItems = Invoke-MgGraphRequest -Uri "v1.0/drives/$($Drive.Id)/root/children"

$ItemExportRaw = New-Object System.Collections.Generic.List[object]

foreach ($DriveItem in $DriveItems.Value)
{
    #Get All drivitems below root
    $ItemExportRaw.Add( $(List-MgDriveItem -Drive $Drive -DriveItem $DriveItem))
}

$ItemExport = New-Object System.Collections.Generic.List[object]


$ItemExportRaw |ForEach-Object {

        $_ | ForEach-Object {$ItemExport.add($_)}    
}

$ItemExport
#endregion

Once the script is exectued, all driveitems are shown like this:

Output of all driveitems

Further Reference

Here you can obtain the permission levels, which are required for your Azure App Registration:
Microsoft Graph permissions reference – Microsoft Graph | Microsoft Learn

Here you can find the cmdlet map for MS Graph module

Find Azure AD and MSOnline cmdlets in Microsoft Graph PowerShell | Microsoft Learn

3 thoughts on “How to Get SharePoint Files with MSGraph with PowerShell”

  1. Pingback: Assign Sensitivity Labels in SharePoint PowerShell Graph API

Leave a Comment