Update-InstalledModule.ps1

function Update-InstalledModule {
  <#
      .SYNOPSIS
      This function updates one or more modules that were installed from the PowerShell gallery if newer versions are available. It accepts pipeline input for the module name as well as an array of names.
 
      It wraps the PowerShellGet function Update-Module and works way faster.
 
      .DESCRIPTION
      Updating modules from the Powershell Gallery can be done via calling Update-Module. This can even be used in a pipeline with Get-InstalledModule | Update-Module. But that's a quite slow command - so this workaround was created. Update-InstalledModule checks the module's download URL for the most current version number, and it calls the original Update-Module only if the local version is older.
 
      For modules that are installed for all users, it obviously requires an elevated session to work - unlike the original Update-Module function, this wrapper does not check where the module is installed and whether admin rights are required or not.
 
      The main reason for the original Update-Module slowness are its connectivity checks to various web sites via ping or http get requests. The helper function Get-PublishedModuleVersion omits all of these checks and only sends a single http get. The response is then parsed for the location which contains the version number. This check is performed for all modules passed in, and finally all modules that need to be updated are passed to Update-Module.
 
      .PARAMETER Name
      The name of the module(s) to update. Can also be a module object returned from Get-Module or Get-InstalledModule. If the module name is omitted, all installed modules are checked.
 
      .PARAMETER Force
      Updates the module even if the currently installed version is up to date.
 
      .EXAMPLE
      Update-InstalledModule
      Checks if newer versions for any installed module are available.
 
      .EXAMPLE
      Update-InstalledModule Foo -Force
      Updates the module Foo regardless of the current version.
 
      .EXAMPLE
      Update-InstalledModule -Name ScriptCop,EzOut
      Checks if newer versions are available for ScriptCop and EzOut.
 
      .LINK
      http://powertheshell.com
      https://evilgpo.blogspot.com
 
      .INPUTS
      System.String
      System.Management.Automation.PSModuleInfo
 
      .OUTPUTS
      None
  #>


  [CmdletBinding(SupportsShouldProcess=$True)]
  param
  (
    [Parameter( Position = 0,
    ValueFromPipelineByPropertyName = $true )]
    [String[]]
    $Name,

    [Parameter()]
    [ValidateSet( 'AllUsers', 'CurrentUser')]
    [String]$Scope,

    [Switch]
    $Force
  )

  begin {

    # ModulesToUpdate keeps track of all modules that need to be updated.
    # These are then finally passed to the original Update-Module in order
    # to speed up processing if more than one module needs updates.
    
    $ModulesToUpdate = @()

    # The -verbose switch cannot properly be passed down to called functions/scripts,
    # so we determine the VerbosePreference value and create an appropriate bool.

    If ( $VerbosePreference -eq "Continue" ) {
      $Verbose = $True
    } else {
      $Verbose = $False
    }
  }
  
  process {

    # ModulesToVerify keeps track of all modules that need to be verified.
    # This can be one or more modules passed on the commandline,
    # or if no modules are passed, we grab all of them for checking.

    If ( $Scope ) {
      If ( $Name ) {
        $ModulesToVerify = ( Get-InstalledModule -Name $Name )
      } else {
        Write-Verbose -Message 'No module name specified, checking all installed modules'
        $ModulesToVerify = ( Get-InstalledModule )
      }
    } Else {
      If ( $Name ) {
        $ModulesToVerify = ( Get-InstalledModule -Name $Name -Scope $Scope )
      } else {
        Write-Verbose -Message 'No module name specified, checking all installed modules'
        $ModulesToVerify = ( Get-InstalledModule -Scope $Scope )
      }
    }
       
    ForEach ( $CurrentModule in $ModulesToVerify ) {
    
      # Get the version of the currently installed module. If it is not installed,
      # Get-InstalledModule will throw a non-terminating error

      Write-Verbose -Message ( 'Trying to check module version for {0}...' -f $CurrentModule.Name )
      $CurrentModuleVersion = $CurrentModule.Version

      If ( $CurrentModuleVersion -eq $null ) {
        Write-Verbose -Message 'Module is not installed or has no version number, skipping...'
        Continue 
      }

      Write-Verbose -Message ( 'Found installed version : {0}' -f $CurrentModuleVersion.ToString() )

      # Get the version that is available in the powershell gallery. If it is not in the gallery,
      # Get-PublishedModuleVersion will throw a warning

      Write-Host ( 'Checking current {0} version {1} for updates...' -f $CurrentModule.Name, $CurrentModuleVersion )
      $AvailableModuleVersion = ( Get-PublishedModuleVersion -Name $( $CurrentModule.Name ) -Verbose:$Verbose ).Version

      If ( $AvailableModuleVersion -eq $null ) { 
        Write-Verbose -Message 'Module version not found in the gallery, skipping...'
        Continue
      }

      Write-Verbose -Message ( 'Latest available version: {0}' -f $AvailableModuleVersion.ToString() )

      # Check if versions already match. Since we use [version] types,
      # we don't care if the version has 2, 3 or 4 parts.

      If ( $CurrentModuleVersion -ge $AvailableModuleVersion )
      {
        If ( $Force ) { 
          Write-Verbose -Message ( '{0} version is up to date, but -Force specified - updating anyway...' -f $CurrentModule.Name )
        } else {
          Write-Host ( '{0} version is already up to date.' -f $CurrentModule.Name ) -ForegroundColor Green
        }
      }

      # check if versions do not match

      If ( ( $CurrentModuleVersion -lt $AvailableModuleVersion ) -or $Force )
      { 
        Write-Host ( '{0} will be updated to version {1}...' -f $CurrentModule.Name, $AvailableModuleVersion ) -ForegroundColor Yellow
        $ModulesToUpdate += $CurrentModule
      }

    }
  }
  
  end {

    # finally update all modules in one call to Update-Module to speed up things...
    If ( $ModulesToUpdate -and $PSCmdlet.ShouldProcess( $ModulesToUpdate.Name ) )
    {
      If ( $Scope ) {
        Update-Module -Name ( $ModulesToUpdate.Name ) -Force:$Force -ErrorAction SilentlyContinue -Verbose:$Verbose -Scope $Scope
      } Else {
        Update-Module -Name ( $ModulesToUpdate.Name ) -Force:$Force -ErrorAction SilentlyContinue -Verbose:$Verbose
      }
    }
    
  }
}