powershell script to get site info including sub sub sites

 //Load SharePoint CSOM Assemblies

Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.WorkflowServices.dll"






//Variables for Processing
$SiteUrl = "Your Site Collection URL"


$separator = "sites"
$tempD = $SiteUrl -split $separator




$Domain = $tempD[0] -replace ".$"


Try {
    //Function to Get all lists from the web
    Function Get-SPOList($Web) {


    
        //Extract List data
        $ListCollection = @()
        $results = @() 
        $WorkflowInventory = @()


      
        $WorkflowServicesManager = New-Object Microsoft.SharePoint.Client.WorkflowServices.WorkflowServicesManager($Context, $Context.Web)




        //Get All Lists from the web
        $Lists = $Web.Lists
        $Context.Load($Lists)
        $Context.ExecuteQuery()


        //Get all lists from the web  
        ForEach ($List in $Lists) {
            //Get the List Name
            //Write-host $List.Title


            if ($List.Hidden -or $List.IsCatalog -or $List.Title.ToLower().Contains("workflow") -or $List.Title.ToLower().Contains("tasks")) {
            }
            else {


       




                $ListData = New-Object -TypeName PSObject


                $ListData | Add-Member -MemberType NoteProperty -Name "SiteURL" -Value $Web.Url
                $ListData | Add-Member -MemberType NoteProperty -Name "Title" -Value $List.Title
                $ListData | Add-Member -MemberType NoteProperty -Name "Itemcount" -Value $List.Itemcount
                //$ListData | Add-Member -MemberType NoteProperty -Name "BaseTemplate" -Value $List.BaseTemplate
                //$ListData | Add-Member -MemberType NoteProperty -Name "BaseType" -Value $List.BaseType
                //$ListData | Add-Member -MemberType NoteProperty -Name "Created" -Value $List.Created.ToShortDateString()
                $ListData | Add-Member -MemberType NoteProperty -Name "Last List Modified Date" -Value $List.LastItemModifiedDate.ToShortDateString()






                //Define the CAML Query
                $Query = New-Object Microsoft.SharePoint.Client.CamlQuery
                $Query.ViewXml = @"
    <View Scope='Recursive'>
  <Query>
   <OrderBy>
      <FieldRef Name='Modified' Ascending='False' />
   </OrderBy>
</Query>
  <RowLimit>1</RowLimit>
</View>
"@






                $ListItems = $list.GetItems($Query)
                $Context.Load($ListItems)
                $Context.ExecuteQuery()




                //Write-host "Total Number of Items: "$ListItems.count


      
                //Loop through Each Item
                ForEach ($Item in $ListItems) {
                    //Do something
                    //Write-host  $Item.FieldValues["FileRef"] 


                    if ($List.BaseType -eq "DocumentLibrary") {
                        $DocUrl = $Domain + $Item.FieldValues["FileRef"]
                        $ListData | Add-Member -MemberType NoteProperty -Name "Item URL" -Value $DocUrl 
                    }
                    else {


                        $ItemURL = $SiteURL + "Lists/" + $List.Title.ToString() + "/dispform.aspx?id=" + $Item.Id 
                        $ListData | Add-Member -MemberType NoteProperty -Name "Item URL" -Value $ItemURL
                    }


                    //$temp =$Item.FieldValues["Modified"].ToString().Trim()
                    $ModifiedDate = [DateTime]::ParseExact($Item.FieldValues["Modified"].ToString().Trim(), 'yyyy/MM/dd hh:mm tt', [CultureInfo]::InvariantCulture)
                    //$InvoiceDate = $InvoiceDate.ToShortDateString()






                    $ListData | Add-Member -MemberType NoteProperty -Name "Last Item Modified Date" -Value $ModifiedDate.ToShortDateString()
                    // $ListData | Add-Member -MemberType NoteProperty -Name "Last Item Modified Name" -Value $Item.FieldValues["Modified_x0020_By"]
                    //"Created By" = $item["Author"]
                    $ListData | Add-Member -MemberType NoteProperty -Name "Last Item Modified Name" -Value $Item["Editor"].LookupValue


                    $Context.Load($List.ContentTypes)
                    $Context.ExecuteQuery()
                    if ($List.ContentTypes[0].EditFormUrl.Contains("editifs.aspx")) {
                        $ListData | Add-Member -MemberType NoteProperty -Name "Is Infopath List" -Value "Yes"
                    }
                    else {
                        $ListData | Add-Member -MemberType NoteProperty -Name "Is Infopath List" -Value ""
                    }
                }


                try {


                    //$itemURL = $List.Title + "/dispform.aspx?id=" + $id
       
                    //$ListURL = $List.RootFolder.Url
                    //Write-host $ListURL




                    //Get SharePoint 2013 Workflows Associated with the List   
                    $WorkflowSubscriptionService = $workflowServicesManager.GetWorkflowSubscriptionService()
                    $WorkflowAssociations = $WorkflowSubscriptionService.EnumerateSubscriptionsByList($List.Id)
                    $Context.Load($WorkflowAssociations)
                    $Context.ExecuteQuery()
                    
                    $2013WF = ""
                    $2010WF = ""
                    


                    //Loop through each workflow associated with the List
                    Foreach ($Association in $WorkflowAssociations | Where { $_.Name -notlike "*Previous Version*" }) {
                        $WorkflowData = New-Object PSObject
                
                        $WorkflowData | Add-Member NoteProperty SiteURL($List.ParentWebUrl)
                        $WorkflowData | Add-Member NoteProperty ListName($List.Title)
                        $WorkflowData | Add-Member NoteProperty WorkflowName($Association.Name)
                        Write-host -f Green "`t Found Workflow '$($Association.Name)' in list '$($List.Title)'"
                        $WorkflowInventory += $WorkflowData


                        $2013WF += $Association.Name + ";"
                    }


                    //Get SharePoint 2010 Workflows Associated
                    $WorkflowAssociations = $List.WorkflowAssociations
                    $Context.Load($WorkflowAssociations)
                    $Context.ExecuteQuery()
                    ForEach ($Association2010 in $WorkflowAssociations | Where { $_.Name -notlike "*Previous Version*" }) {
                        $WorkflowData = New-Object PSObject
                
                        $WorkflowData | Add-Member NoteProperty SiteURL($List.ParentWebUrl)
                        //$WorkflowData | Add-Member NoteProperty ListURL($ListURL)
                        $WorkflowData | Add-Member NoteProperty ListName($List.Title)
                        $WorkflowData | Add-Member NoteProperty WorkflowName($Association.Name)
                        Write-host -f Green "`t Found Workflow '$($Association2010.Name)' in list '$($List.Title)'"
                        $WorkflowInventory += $WorkflowData


                        $2010WF += $Association2010.Name + ";"
                    }


                    $2013WF = $2013WF -replace ".$"
                    $2010WF = $2010WF -replace ".$"
                    $workflows = ""


                    if ($2013WF -ne "") {
                        //$workflows += "2013 - " + $2013WF
                        $ListData | Add-Member -MemberType NoteProperty -Name "2013 Workflows" -Value $2013WF
                    }
                    else {
                        $ListData | Add-Member -MemberType NoteProperty -Name "2013 Workflows" -Value ""
                    }


                    if ($2010WF -ne "") {
                        //$workflows += "2010 - " + $2010WF
                        $ListData | Add-Member -MemberType NoteProperty -Name "2010 Workflows" -Value $2010WF
                    }
                    else {
                        $ListData | Add-Member -MemberType NoteProperty -Name "2010 Workflows" -Value ""
                    }




                    //if($workflows -eq "")
                    //{
                    //    $ListData | Add-Member -MemberType NoteProperty -Name "Workflows" -Value ""
                    //}
                    //else
                    //{
                    //    $ListData | Add-Member -MemberType NoteProperty -Name "Workflows" -Value $workflows
                    //}


                }
                catch {
                    Write-Output $_
                }


                // try {
                //     if ($List.BaseTemplate -eq 115) {
                //         Write-host -f Green "`t Found Infopath in list '$($List.Title)'"
                //     }


                //     $Context.Load($List.ContentTypes)
                //     //$Context.Load($List.ContentTypes[0].ResourceFolder.Properties["_ipfs_infopathenabled"])
                //     $Context.ExecuteQuery()


                //     foreach ($ContentType in $List.ContentTypes) {


                //         if ($ContentType.ResourceFolder.Properties["_ipfs_infopathenabled"] -eq $true) {
                //             Write-host -f Green "`t Found Infopath in list '$($List.Title)'"
                //         }
                //     }




        
                // }
                // catch {
                // } 


                $ListCollection += $ListData
        
            }








        }




        $ListReportFile = "C:\Temp\" + $Web.Title + " - list-inventory.csv"
        $WorkflowReportFile = "C:\Temp\" + $Web.Title + " - workflows-inventory.csv"




        //Export List Inventory to CSV
        $ListCollection | Export-csv -Path $ListReportFile -NoTypeInformation


        //if($WorkflowInventory.Count -ge 1)
        //{
        //$WorkflowInventory | Export-csv -Path $WorkflowReportFile -NoTypeInformation
        //}


    }






    //Function to get all webs from given URL
    Function Get-SPOWeb($WebURL) {
        //Set up the context
        $Context = New-Object Microsoft.SharePoint.Client.ClientContext($WebURL)
        //$Context.Credentials = $Credentials


        $Web = $context.Web
        $Context.Load($web)
        //Get all immediate subsites of the site
        $Context.Load($web.Webs) 
        $Context.executeQuery()


        //Call the function to Get Lists of the web
        Write-host "Processing Web :"$Web.URL
        Get-SPOList $Web


        //Iterate through each subsite in the current web
        foreach ($Subweb in $web.Webs) {
            //Call the function recursively to process all subsites underneaththe current web
            Get-SPOWeb($SubWeb.URL)
        }
    }


    //Call the function to get all sites
    Get-SPOWeb $SiteUrl
}
catch {
    write-host "Error: $($_.Exception.Message)" -foregroundcolor Red
} 

Comments