none
need Powershell script to check for Broken Links in multiple sites RRS feed

  • Question

  • I have been searching trying to find some way to check multiple sites at a time to see if they have broken links.


    I found this script (below), but it isn't not working .. I get an error at line #138  the  foreach  item is throwing an error, but this will only search 1  site at a time, I need to search  multiple sites at 1 time, and I do not need it to create a file. An on screen report would work.  Just something I can trigger quickly to verify that the sites in the site collection are ok.

    I am not a Powershell programmer, any assistance with this to solve would be great.

    Code:

    # This script will print out a list of all links in the Quick Launch, Links Lists, and default
    # page for each SPWeb object to a text file located in the directory specified in the variables section.
    #
    # Author: Henry Ong
    ######################## Start Variables ########################
    $siteURL = "http://alvhong2" #URL to any site in the web application.
    $filePath = "C:\PowerShellScripts\Links.csv"
    $PublishingFeatureGUID = "94c94ca6-b32f-4da9-a9e3-1f3d343d7ecb"
    ######################## End Variables ########################
    if(Test-Path $filePath)
    {
     Remove-Item $filePath
    }
    Clear-Host
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Publishing")
    [System.Reflection.Assembly]::LoadWithPartialName("System.Net.WebClient")
    
    # Creates an object that represents an SPWeb's Title and URL
    function CreateNewWebObject
    {
     $linkObject = New-Object system.Object
     $linkObject | Add-Member -type NoteProperty -Name WebTitle -Value $web.Title
     $linkObject | Add-Member -type NoteProperty -Name WebURL -Value $web.URL
    
     return $linkObject
    }
    # Creates an object that represents the header links of the Quick Launch
    function CreateNewLinkHeaderObject
    {
     $linkObject = New-Object system.Object
     $linkObject | Add-Member -type NoteProperty -Name WebTitle -Value $prevWebTitle
     $linkObject | Add-Member -type NoteProperty -Name WebURL -Value $prevWebURL  
     $linkObject | Add-Member -type NoteProperty -Name QLHeaderTitle -Value $node.Title
     $linkObject | Add-Member -type NoteProperty -Name QLHeaderLink -Value $node.Url
     return $linkObject
    }
    # Creates an object that represents to the links in the Top Link bar
    function CreateNewTopLinkObject
    {
     $linkObject = New-Object system.Object
     $linkObject | Add-Member -type NoteProperty -Name WebTitle -Value $prevWebTitle
     $linkObject | Add-Member -type NoteProperty -Name WebURL -Value $prevWebURL  
     $linkObject | Add-Member -type NoteProperty -Name TopLinkTitle -Value $node.Title
     $linkObject | Add-Member -type NoteProperty -Name TopLinkURL -Value $node.Url
     $linkObject | Add-Member -type NoteProperty -Name TopNavLink -Value $true
     return $linkObject
    }
    # Creates an object that represents the links of in the Quick Launch (underneath the headers)
    function CreateNewLinkChildObject
    {
     $linkObject = New-Object system.Object
     $linkObject | Add-Member -type NoteProperty -Name WebTitle -Value $prevWebTitle
     $linkObject | Add-Member -type NoteProperty -Name WebURL -Value $prevWebURL
     $linkObject | Add-Member -type NoteProperty -Name QLHeaderTitle -Value $prevHeaderTitle
     $linkObject | Add-Member -type NoteProperty -Name QLHeaderLink -Value $prevHeaderLink
     $linkObject | Add-Member -type NoteProperty -Name QLChildLinkTitle -Value $childNode.Title
     $linkObject | Add-Member -type NoteProperty -Name QLChildLink -Value $childNode.URL
     return $linkObject
    }
    ## Creates an object that represents items in a Links list.
    function CreateNewLinkItemObject
    {
     $linkObject = New-Object system.Object
     $linkObject | Add-Member -type NoteProperty -Name WebTitle -Value $prevWebTitle
     $linkObject | Add-Member -type NoteProperty -Name WebURL -Value $prevWebURL
     $linkObject | Add-Member -type NoteProperty -Name ListName -Value $list.Title
    
     $spFieldURLValue = New-Object microsoft.sharepoint.spfieldurlvalue($item["URL"])
    
     $linkObject | Add-Member -type NoteProperty -Name ItemTitle -Value $spFieldURLValue.Description
     $linkObject | Add-Member -type NoteProperty -Name ItemURL -Value $spFieldURLValue.Url
     return $linkObject
    }
    # Determines whether or not the passed in Feature is activated on the site or not.
    function FeatureIsActivated
    {param($FeatureID, $Web)
     return $web.Features[$FeatureID] -ne $null
    }
    # Creates an object that represents a link within the body of a content page.
    function CreateNewPageContentLinkObject
    {
     $linkObject = New-Object system.Object
     $linkObject | Add-Member -type NoteProperty -Name WebTitle -Value $prevWebTitle
     $linkObject | Add-Member -type NoteProperty -Name WebURL -Value $prevWebURL
     $linkObject | Add-Member -type NoteProperty -Name PageContentLink -Value $link
    
     return $linkObject
    }
    $wc = New-Object System.Net.WebClient
    $wc.UseDefaultCredentials = $true
    $pattern = "(((f|ht){1}tp://)[-a-zA-Z0-9@:%_\+.~#?&//=]+)"
    $site = new-object microsoft.sharepoint.spsite($siteURL)
    $webApp = $site.webapplication
    $allSites = $webApp.sites
    $customLinkObjects =@()foreach  ("error is here at the foreach"  any ideas?)
    ($site in $allSites)
    {
     $allWebs = $site.AllWebs
    
     foreach ($web in $allWebs)
     {
      ## If the web has the publishing feature turned OFF, use this method
      if((FeatureIsActivated $PublishingFeatureGUID $web) -ne $true)
      {
       $quickLaunch = $web.Navigation.QuickLaunch
       $customLinkObject = CreateNewWebObject
       $customLinkObjects += $customLinkObject
    
       $prevWebTitle = $customLinkObject.WebTitle
       $prevWebURL = $customLinkObject.WebURL
    
       # First level of the Quick Launch (Headers)
       foreach ($node in $quickLaunch)
       {
        $customLinkObject = CreateNewLinkHeaderObject
    
        $customLinkObjects += $customLinkObject
    
        $prevHeaderTitle = $node.Title
        $prevHeaderLink = $node.Url
    
        # Second level of the Quick Launch (Links)
        foreach ($childNode in $node.Children)
        {
         $customLinkObject = CreateNewLinkChildObject
    
         $customLinkObjects += $customLinkObject
        }
       }
    
       # Get all the links in the Top Link bar
       $topLinks = $web.Navigation.TopNavigationBar
       foreach ($node in $topLinks)
       {
        $customLinkObject = CreateNewTopLinkObject
    
        $customLinkObjects += $customLinkObject
    
        $prevHeaderTitle = $node.Title
        $prevHeaderLink = $node.Url    
       }
      }
    
      ## If the web has the publishing feature turned ON, use this method
      else
      {
       $publishingWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)
       $quickLaunch = $publishingWeb.CurrentNavigationNodes
       $customLinkObject = CreateNewWebObject
       $customLinkObjects += $customLinkObject
    
       $prevWebTitle = $customLinkObject.WebTitle
       $prevWebURL = $customLinkObject.WebURL
    
       # First level of the Quick Launch (Headers)
       foreach ($node in $quickLaunch)
       {
        $customLinkObject = CreateNewLinkHeaderObject
    
        $customLinkObjects += $customLinkObject
    
        $prevHeaderTitle = $node.Title
        $prevHeaderLink = $node.Url
    
        # Second level of the Quick Launch (Links)
        foreach ($childNode in $node.Children)
        {
         $customLinkObject = CreateNewLinkChildObject
    
         $customLinkObjects += $customLinkObject
        }
       }
    
       # Get all the links in the Top Link bar
       $topLinks = $web.Navigation.TopNavigationBar
       foreach ($node in $topLinks)
       {
        $customLinkObject = CreateNewTopLinkObject
    
        $customLinkObjects += $customLinkObject
    
        $prevHeaderTitle = $node.Title
        $prevHeaderLink = $node.Url    
       }   
    
      }
    
      #Looking for lists of type Links
      $lists = $web.Lists
      foreach ($list in $lists)
      {
       if($list.BaseTemplate -eq "Links")
       {
        $prevWebTitle = $customLinkObject.WebTitle
        $prevWebURL = $customLinkObject.WebURL
    
        # Going through all the links in a Links List
        foreach ($item in $list.Items)
        {
         $customLinkObject = CreateNewLinkItemObject
    
         $customLinkObjects += $customLinkObject     
        }
    
    Write-Host $list.Title
       }  
      }
    
      #Looking at the default page for each web for links embedded within the content areas
      $htmlContent = $wc.DownloadString($web.URL)
      $result = $htmlContent | Select-String -Pattern $pattern -AllMatches
      $links = $result.Matches | ForEach-Object {$_.Groups[1].Value}
      foreach ($link in $links)
      {
       $customLinkObject = CreateNewPageContentLinkObject
       $customLinkObjects += $customLinkObject
      }
    
    Write-Host $web.Title
      $web.Dispose()
     }
    $site.dispose()
    }
    # Exporting the data to a CSV file
    $customLinkObjects | Select-Object WebTitle,WebURL,TopNavLink,TopLinkTitle,TopLinkURL,QLHeaderTitle,QLHeaderLink,QLChildLinkTitle,QLChildLink,ListName,ItemTitle,ItemURL,PageContentLink | Export-Csv $filePath
    write-host "Done"

    Tuesday, June 30, 2020 6:17 PM

All replies

  • Hi,

    Update the script you shared to iterate all site collections of SharePoint, it's easy to develop PowerShell script if you know how to debug it(Power GUI Script Editor or Visual code).

    https://docs.microsoft.com/en-us/powershell/scripting/dev-cross-plat/vscode/using-vscode?view=powershell-7

    As you have got the script to check whether a link is broken in your previous thread, so you need add the logic to below script.

    https://social.technet.microsoft.com/Forums/en-US/34237b5c-fd2b-4ccc-b290-b434d91a7dde/is-there-a-tool-or-code-that-can-tell-me-if-sharepoint-sites-and-pages-are-operational-or-if-they?forum=sharepointadmin

    # This script will print out a list of all links in the Quick Launch, Links Lists, and default
    # page for each SPWeb object to a text file located in the directory specified in the variables section.
    #
    # Author: Henry Ong
    ######################## Start Variables ########################
    #$siteURL = "http://alvhong2" #URL to any site in the web application.
    $filePath = "C:\Lee\Script\Links.csv"
    $PublishingFeatureGUID = "94c94ca6-b32f-4da9-a9e3-1f3d343d7ecb"
    ######################## End Variables ########################
    if(Test-Path $filePath)
    {
     Remove-Item $filePath
    }
    Clear-Host
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Publishing")
    [System.Reflection.Assembly]::LoadWithPartialName("System.Net.WebClient")
    
    # Creates an object that represents an SPWeb's Title and URL
    function CreateNewWebObject
    {
     $linkObject = New-Object system.Object
     $linkObject | Add-Member -type NoteProperty -Name WebTitle -Value $web.Title
     $linkObject | Add-Member -type NoteProperty -Name WebURL -Value $web.URL
    
     return $linkObject
    }
    # Creates an object that represents the header links of the Quick Launch
    function CreateNewLinkHeaderObject
    {
     $linkObject = New-Object system.Object
     $linkObject | Add-Member -type NoteProperty -Name WebTitle -Value $prevWebTitle
     $linkObject | Add-Member -type NoteProperty -Name WebURL -Value $prevWebURL  
     $linkObject | Add-Member -type NoteProperty -Name QLHeaderTitle -Value $node.Title
     $linkObject | Add-Member -type NoteProperty -Name QLHeaderLink -Value $node.Url
     return $linkObject
    }
    # Creates an object that represents to the links in the Top Link bar
    function CreateNewTopLinkObject
    {
     $linkObject = New-Object system.Object
     $linkObject | Add-Member -type NoteProperty -Name WebTitle -Value $prevWebTitle
     $linkObject | Add-Member -type NoteProperty -Name WebURL -Value $prevWebURL  
     $linkObject | Add-Member -type NoteProperty -Name TopLinkTitle -Value $node.Title
     $linkObject | Add-Member -type NoteProperty -Name TopLinkURL -Value $node.Url
     $linkObject | Add-Member -type NoteProperty -Name TopNavLink -Value $true
     return $linkObject
    }
    # Creates an object that represents the links of in the Quick Launch (underneath the headers)
    function CreateNewLinkChildObject
    {
     $linkObject = New-Object system.Object
     $linkObject | Add-Member -type NoteProperty -Name WebTitle -Value $prevWebTitle
     $linkObject | Add-Member -type NoteProperty -Name WebURL -Value $prevWebURL
     $linkObject | Add-Member -type NoteProperty -Name QLHeaderTitle -Value $prevHeaderTitle
     $linkObject | Add-Member -type NoteProperty -Name QLHeaderLink -Value $prevHeaderLink
     $linkObject | Add-Member -type NoteProperty -Name QLChildLinkTitle -Value $childNode.Title
     $linkObject | Add-Member -type NoteProperty -Name QLChildLink -Value $childNode.URL
     return $linkObject
    }
    ## Creates an object that represents items in a Links list.
    function CreateNewLinkItemObject
    {
     $linkObject = New-Object system.Object
     $linkObject | Add-Member -type NoteProperty -Name WebTitle -Value $prevWebTitle
     $linkObject | Add-Member -type NoteProperty -Name WebURL -Value $prevWebURL
     $linkObject | Add-Member -type NoteProperty -Name ListName -Value $list.Title
    
     $spFieldURLValue = New-Object microsoft.sharepoint.spfieldurlvalue($item["URL"])
    
     $linkObject | Add-Member -type NoteProperty -Name ItemTitle -Value $spFieldURLValue.Description
     $linkObject | Add-Member -type NoteProperty -Name ItemURL -Value $spFieldURLValue.Url
     return $linkObject
    }
    # Determines whether or not the passed in Feature is activated on the site or not.
    function FeatureIsActivated
    {param($FeatureID, $Web)
     return $web.Features[$FeatureID] -ne $null
    }
    # Creates an object that represents a link within the body of a content page.
    function CreateNewPageContentLinkObject
    {
     $linkObject = New-Object system.Object
     $linkObject | Add-Member -type NoteProperty -Name WebTitle -Value $prevWebTitle
     $linkObject | Add-Member -type NoteProperty -Name WebURL -Value $prevWebURL
     $linkObject | Add-Member -type NoteProperty -Name PageContentLink -Value $link
    
     return $linkObject
    }
    
    if ((Get-PSSnapin 'Microsoft.SharePoint.PowerShell' -ErrorAction SilentlyContinue) -eq $null) {
      Add-PSSnapin 'Microsoft.SharePoint.PowerShell'
    }
    
    
    $wc = New-Object System.Net.WebClient
    $wc.UseDefaultCredentials = $true
    $pattern = "(((f|ht){1}tp://)[-a-zA-Z0-9@:%_\+.~#?&//=]+)"
    #$site = new-object microsoft.sharepoint.spsite($siteURL)
    #$webApp = $site.webapplication
    #$allSites = $webApp.sites
    $customLinkObjects =@()
    $WebApps=Get-SPWebApplication
    foreach($webApp in $WebApps) {
    	foreach ($site in $webApp.Sites) {
    		 $allWebs = $site.AllWebs
    
    		 foreach ($web in $allWebs)
    		 {
    		  ## If the web has the publishing feature turned OFF, use this method
    		  if((FeatureIsActivated $PublishingFeatureGUID $web) -ne $true)
    		  {
    		   $quickLaunch = $web.Navigation.QuickLaunch
    		   $customLinkObject = CreateNewWebObject
    		   $customLinkObjects += $customLinkObject
    
    		   $prevWebTitle = $customLinkObject.WebTitle
    		   $prevWebURL = $customLinkObject.WebURL
    
    		   # First level of the Quick Launch (Headers)
    		   foreach ($node in $quickLaunch)
    		   {
    		    $customLinkObject = CreateNewLinkHeaderObject
    
    		    $customLinkObjects += $customLinkObject
    
    		    $prevHeaderTitle = $node.Title
    		    $prevHeaderLink = $node.Url
    
    		    # Second level of the Quick Launch (Links)
    		    foreach ($childNode in $node.Children)
    		    {
    		     $customLinkObject = CreateNewLinkChildObject
    
    		     $customLinkObjects += $customLinkObject
    		    }
    		   }
    
    		   # Get all the links in the Top Link bar
    		   $topLinks = $web.Navigation.TopNavigationBar
    		   foreach ($node in $topLinks)
    		   {
    		    $customLinkObject = CreateNewTopLinkObject
    
    		    $customLinkObjects += $customLinkObject
    
    		    $prevHeaderTitle = $node.Title
    		    $prevHeaderLink = $node.Url    
    		   }
    		  }
    
    		  ## If the web has the publishing feature turned ON, use this method
    		  else
    		  {
    		   $publishingWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)
    		   $quickLaunch = $publishingWeb.CurrentNavigationNodes
    		   $customLinkObject = CreateNewWebObject
    		   $customLinkObjects += $customLinkObject
    
    		   $prevWebTitle = $customLinkObject.WebTitle
    		   $prevWebURL = $customLinkObject.WebURL
    
    		   # First level of the Quick Launch (Headers)
    		   foreach ($node in $quickLaunch)
    		   {
    		    $customLinkObject = CreateNewLinkHeaderObject
    
    		    $customLinkObjects += $customLinkObject
    
    		    $prevHeaderTitle = $node.Title
    		    $prevHeaderLink = $node.Url
    
    		    # Second level of the Quick Launch (Links)
    		    foreach ($childNode in $node.Children)
    		    {
    		     $customLinkObject = CreateNewLinkChildObject
    
    		     $customLinkObjects += $customLinkObject
    		    }
    		   }
    
    		   # Get all the links in the Top Link bar
    		   $topLinks = $web.Navigation.TopNavigationBar
    		   foreach ($node in $topLinks)
    		   {
    		    $customLinkObject = CreateNewTopLinkObject
    
    		    $customLinkObjects += $customLinkObject
    
    		    $prevHeaderTitle = $node.Title
    		    $prevHeaderLink = $node.Url    
    		   }   
    
    		  }
    
    		  #Looking for lists of type Links
    		  $lists = $web.Lists
    		  foreach ($list in $lists)
    		  {
    		   if($list.BaseTemplate -eq "Links")
    		   {
    		    $prevWebTitle = $customLinkObject.WebTitle
    		    $prevWebURL = $customLinkObject.WebURL
    
    		    # Going through all the links in a Links List
    		    foreach ($item in $list.Items)
    		    {
    		     $customLinkObject = CreateNewLinkItemObject
    
    		     $customLinkObjects += $customLinkObject     
    		    }
    
    		Write-Host $list.Title
    		   }  
    		  }
    
    		  #Looking at the default page for each web for links embedded within the content areas
    		  $htmlContent = $wc.DownloadString($web.URL)
    		  $result = $htmlContent | Select-String -Pattern $pattern -AllMatches
    		  $links = $result.Matches | ForEach-Object {$_.Groups[1].Value}
    		  foreach ($link in $links)
    		  {
    		   $customLinkObject = CreateNewPageContentLinkObject
    		   $customLinkObjects += $customLinkObject
    		  }
    
    		Write-Host $web.Title
    		  $web.Dispose()
    		 }
    		$site.Dispose()
    		}
    }
    #foreach($site in $allSites)
    
    # Exporting the data to a CSV file
    $customLinkObjects | Select-Object WebTitle,WebURL,TopNavLink,TopLinkTitle,TopLinkURL,QLHeaderTitle,QLHeaderLink,QLChildLinkTitle,QLChildLink,ListName,ItemTitle,ItemURL,PageContentLink | Export-Csv $filePath
    write-host "Done"

    Best Regards,

    Lee


    Please remember to mark the replies as answers if they helped. If you have feedback for TechNet Subscriber Support, contact tnmff@microsoft.com.

    SharePoint Server 2019 has been released, you can click here to download it.
    Click here to learn new features. Visit the dedicated forum to share, explore and talk to experts about SharePoint Server 2019.

    Wednesday, July 1, 2020 2:49 AM