winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

MSFT_PSModule.psm1 (38882B)


      1 #
      2 # Copyright (c) Microsoft Corporation.
      3 #
      4 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      5 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      6 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      7 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      8 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      9 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     10 # THE SOFTWARE.
     11 #
     12 
     13 $resourceModuleRoot = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent
     14 
     15 # Import localization helper functions.
     16 $helperName = 'PowerShellGet.LocalizationHelper'
     17 $dscResourcesFolderFilePath = Join-Path -Path $resourceModuleRoot -ChildPath "Modules\$helperName\$helperName.psm1"
     18 Import-Module -Name $dscResourcesFolderFilePath
     19 
     20 $script:localizedData = Get-LocalizedData -ResourceName 'MSFT_PSModule' -ScriptRoot $PSScriptRoot
     21 
     22 # Import resource helper functions.
     23 $helperName = 'PowerShellGet.ResourceHelper'
     24 $dscResourcesFolderFilePath = Join-Path -Path $resourceModuleRoot -ChildPath "Modules\$helperName\$helperName.psm1"
     25 Import-Module -Name $dscResourcesFolderFilePath
     26 
     27 <#
     28     .SYNOPSIS
     29         This DSC resource provides a mechanism to download PowerShell modules from the PowerShell
     30         Gallery and install it on your computer.
     31 
     32         Get-TargetResource returns the current state of the resource.
     33 
     34     .PARAMETER Name
     35         Specifies the name of the PowerShell module to be installed or uninstalled.
     36 
     37     .PARAMETER Repository
     38         Specifies the name of the module source repository where the module can be found.
     39 
     40     .PARAMETER RequiredVersion
     41         Provides the version of the module you want to install or uninstall.
     42 
     43     .PARAMETER MaximumVersion
     44         Provides the maximum version of the module you want to install or uninstall.
     45 
     46     .PARAMETER MinimumVersion
     47         Provides the minimum version of the module you want to install or uninstall.
     48 
     49     .PARAMETER Force
     50         Forces the installation of modules. If a module of the same name and version already exists on the computer,
     51         this parameter overwrites the existing module with one of the same name that was found by the command.
     52 
     53     .PARAMETER AllowClobber
     54         Allows the installation of modules regardless of if other existing module on the computer have cmdlets
     55         of the same name.
     56 
     57     .PARAMETER SkipPublisherCheck
     58         Allows the installation of modules that have not been catalog signed.
     59 #>
     60 function Get-TargetResource {
     61     <#
     62         These suppressions are added because this repository have other Visual Studio Code workspace
     63         settings than those in DscResource.Tests DSC test framework.
     64         Only those suppression that contradict this repository guideline is added here.
     65     #>
     66     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-ForEachStatement', '')]
     67     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-FunctionBlockBraces', '')]
     68     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-IfStatement', '')]
     69     [CmdletBinding()]
     70     [OutputType([System.Collections.Hashtable])]
     71     param
     72     (
     73         [Parameter(Mandatory = $true)]
     74         [System.String]
     75         $Name,
     76 
     77         [Parameter()]
     78         [System.String]
     79         $Repository = 'PSGallery',
     80 
     81         [Parameter()]
     82         [System.String]
     83         $RequiredVersion,
     84 
     85         [Parameter()]
     86         [System.String]
     87         $MaximumVersion,
     88 
     89         [Parameter()]
     90         [System.String]
     91         $MinimumVersion,
     92 
     93         [Parameter()]
     94         [System.Boolean]
     95         $Force,
     96 
     97         [Parameter()]
     98         [System.Boolean]
     99         $AllowClobber,
    100 
    101         [Parameter()]
    102         [System.Boolean]
    103         $SkipPublisherCheck
    104     )
    105 
    106     $returnValue = @{
    107         Ensure             = 'Absent'
    108         Name               = $Name
    109         Repository         = $Repository
    110         Description        = $null
    111         Guid               = $null
    112         ModuleBase         = $null
    113         ModuleType         = $null
    114         Author             = $null
    115         InstalledVersion   = $null
    116         RequiredVersion    = $RequiredVersion
    117         MinimumVersion     = $MinimumVersion
    118         MaximumVersion     = $MaximumVersion
    119         Force              = $Force
    120         AllowClobber       = $AllowClobber
    121         SkipPublisherCheck = $SkipPublisherCheck
    122         InstallationPolicy = $null
    123     }
    124 
    125     Write-Verbose -Message ($localizedData.GetTargetResourceMessage -f $Name)
    126 
    127     $extractedArguments = New-SplatParameterHashTable -FunctionBoundParameters $PSBoundParameters `
    128         -ArgumentNames ('Name', 'Repository', 'MinimumVersion', 'MaximumVersion', 'RequiredVersion')
    129 
    130     # Get the module with the right version and repository properties.
    131     $modules = Get-RightModule @extractedArguments -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
    132 
    133     # If the module is found, the count > 0
    134     if ($modules.Count -gt 0) {
    135         Write-Verbose -Message ($localizedData.ModuleFound -f $Name)
    136 
    137         # Find a module with the latest version and return its properties.
    138         $latestModule = $modules[0]
    139 
    140         foreach ($module in $modules) {
    141             if ($module.Version -gt $latestModule.Version) {
    142                 $latestModule = $module
    143             }
    144         }
    145 
    146         # Check if the repository matches.
    147         $repositoryName = Get-ModuleRepositoryName -Module $latestModule -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
    148 
    149         if ($repositoryName) {
    150             $installationPolicy = Get-InstallationPolicy -RepositoryName $repositoryName -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
    151         }
    152 
    153         if ($installationPolicy) {
    154             $installationPolicyReturnValue = 'Trusted'
    155         }
    156         else {
    157             $installationPolicyReturnValue = 'Untrusted'
    158         }
    159 
    160         $returnValue.Ensure = 'Present'
    161         $returnValue.Repository = $repositoryName
    162         $returnValue.Description = $latestModule.Description
    163         $returnValue.Guid = $latestModule.Guid
    164         $returnValue.ModuleBase = $latestModule.ModuleBase
    165         $returnValue.ModuleType = $latestModule.ModuleType
    166         $returnValue.Author = $latestModule.Author
    167         $returnValue.InstalledVersion = $latestModule.Version
    168         $returnValue.InstallationPolicy = $installationPolicyReturnValue
    169     }
    170     else {
    171         Write-Verbose -Message ($localizedData.ModuleNotFound -f $Name)
    172     }
    173 
    174     return $returnValue
    175 }
    176 
    177 <#
    178     .SYNOPSIS
    179         This DSC resource provides a mechanism to download PowerShell modules from the PowerShell
    180         Gallery and install it on your computer.
    181 
    182         Test-TargetResource validates whether the resource is currently in the desired state.
    183 
    184     .PARAMETER Ensure
    185         Determines whether the module to be installed or uninstalled.
    186 
    187     .PARAMETER Name
    188         Specifies the name of the PowerShell module to be installed or uninstalled.
    189 
    190     .PARAMETER Repository
    191         Specifies the name of the module source repository where the module can be found.
    192 
    193     .PARAMETER InstallationPolicy
    194         Determines whether you trust the source repository where the module resides.
    195 
    196     .PARAMETER RequiredVersion
    197         Provides the version of the module you want to install or uninstall.
    198 
    199     .PARAMETER MaximumVersion
    200         Provides the maximum version of the module you want to install or uninstall.
    201 
    202     .PARAMETER MinimumVersion
    203         Provides the minimum version of the module you want to install or uninstall.
    204 
    205     .PARAMETER Force
    206         Forces the installation of modules. If a module of the same name and version already exists on the computer,
    207         this parameter overwrites the existing module with one of the same name that was found by the command.
    208 
    209     .PARAMETER AllowClobber
    210         Allows the installation of modules regardless of if other existing module on the computer have cmdlets
    211         of the same name.
    212 
    213     .PARAMETER SkipPublisherCheck
    214         Allows the installation of modules that have not been catalog signed.
    215 #>
    216 function Test-TargetResource {
    217     <#
    218         These suppressions are added because this repository have other Visual Studio Code workspace
    219         settings than those in DscResource.Tests DSC test framework.
    220         Only those suppression that contradict this repository guideline is added here.
    221     #>
    222     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-FunctionBlockBraces', '')]
    223     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-IfStatement', '')]
    224     [CmdletBinding()]
    225     [OutputType([System.Boolean])]
    226     param
    227     (
    228         [Parameter()]
    229         [ValidateSet('Present', 'Absent')]
    230         [System.String]
    231         $Ensure = 'Present',
    232 
    233         [Parameter(Mandatory = $true)]
    234         [System.String]
    235         $Name,
    236 
    237         [Parameter()]
    238         [System.String]
    239         $Repository = 'PSGallery',
    240 
    241         [Parameter()]
    242         [ValidateSet('Trusted', 'Untrusted')]
    243         [System.String]
    244         $InstallationPolicy = 'Untrusted',
    245 
    246         [Parameter()]
    247         [System.String]
    248         $RequiredVersion,
    249 
    250         [Parameter()]
    251         [System.String]
    252         $MaximumVersion,
    253 
    254         [Parameter()]
    255         [System.String]
    256         $MinimumVersion,
    257 
    258         [Parameter()]
    259         [System.Boolean]
    260         $Force,
    261 
    262         [Parameter()]
    263         [System.Boolean]
    264         $AllowClobber,
    265 
    266         [Parameter()]
    267         [System.Boolean]
    268         $SkipPublisherCheck
    269     )
    270 
    271     Write-Verbose -Message ($localizedData.TestTargetResourceMessage -f $Name)
    272 
    273     $extractedArguments = New-SplatParameterHashTable -FunctionBoundParameters $PSBoundParameters `
    274         -ArgumentNames ('Name', 'Repository', 'MinimumVersion', 'MaximumVersion', 'RequiredVersion')
    275 
    276     $status = Get-TargetResource @extractedArguments
    277 
    278     # The ensure returned from Get-TargetResource is not equal to the desired $Ensure.
    279     if ($status.Ensure -ieq $Ensure) {
    280         Write-Verbose -Message ($localizedData.InDesiredState -f $Name)
    281         return $true
    282     }
    283     else {
    284         Write-Verbose -Message ($localizedData.NotInDesiredState -f $Name)
    285         return $false
    286     }
    287 }
    288 
    289 <#
    290     .SYNOPSIS
    291         This DSC resource provides a mechanism to download PowerShell modules from the PowerShell
    292         Gallery and install it on your computer.
    293 
    294         Set-TargetResource sets the resource to the desired state. "Make it so".
    295 
    296     .PARAMETER Ensure
    297         Determines whether the module to be installed or uninstalled.
    298 
    299     .PARAMETER Name
    300         Specifies the name of the PowerShell module to be installed or uninstalled.
    301 
    302     .PARAMETER Repository
    303         Specifies the name of the module source repository where the module can be found.
    304 
    305     .PARAMETER InstallationPolicy
    306         Determines whether you trust the source repository where the module resides.
    307 
    308     .PARAMETER RequiredVersion
    309         Provides the version of the module you want to install or uninstall.
    310 
    311     .PARAMETER MaximumVersion
    312         Provides the maximum version of the module you want to install or uninstall.
    313 
    314     .PARAMETER MinimumVersion
    315         Provides the minimum version of the module you want to install or uninstall.
    316 
    317     .PARAMETER Force
    318         Forces the installation of modules. If a module of the same name and version already exists on the computer,
    319         this parameter overwrites the existing module with one of the same name that was found by the command.
    320 
    321     .PARAMETER AllowClobber
    322         Allows the installation of modules regardless of if other existing module on the computer have cmdlets
    323         of the same name.
    324 
    325     .PARAMETER SkipPublisherCheck
    326         Allows the installation of modules that have not been catalog signed.
    327 #>
    328 function Set-TargetResource {
    329     <#
    330         These suppressions are added because this repository have other Visual Studio Code workspace
    331         settings than those in DscResource.Tests DSC test framework.
    332         Only those suppression that contradict this repository guideline is added here.
    333     #>
    334     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-ForEachStatement', '')]
    335     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-FunctionBlockBraces', '')]
    336     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-IfStatement', '')]
    337     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-TryStatement', '')]
    338     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-CatchClause', '')]
    339     [CmdletBinding()]
    340     param
    341     (
    342         [Parameter()]
    343         [ValidateSet('Present', 'Absent')]
    344         [System.String]
    345         $Ensure = 'Present',
    346 
    347         [Parameter(Mandatory = $true)]
    348         [System.String]
    349         $Name,
    350 
    351         [Parameter()]
    352         [System.String]
    353         $Repository = 'PSGallery',
    354 
    355         [Parameter()]
    356         [ValidateSet('Trusted', 'Untrusted')]
    357         [System.String]
    358         $InstallationPolicy = 'Untrusted',
    359 
    360         [Parameter()]
    361         [System.String]
    362         $RequiredVersion,
    363 
    364         [Parameter()]
    365         [System.String]
    366         $MaximumVersion,
    367 
    368         [Parameter()]
    369         [System.String]
    370         $MinimumVersion,
    371 
    372         [Parameter()]
    373         [System.Boolean]
    374         $Force,
    375 
    376         [Parameter()]
    377         [System.Boolean]
    378         $AllowClobber,
    379 
    380         [Parameter()]
    381         [System.Boolean]
    382         $SkipPublisherCheck
    383     )
    384 
    385     # Validate the repository argument
    386     if ($PSBoundParameters.ContainsKey('Repository')) {
    387         Test-ParameterValue -Value $Repository -Type 'PackageSource' -ProviderName 'PowerShellGet' -Verbose
    388     }
    389 
    390     if ($Ensure -ieq 'Present') {
    391         # Version check
    392         $extractedArguments = New-SplatParameterHashTable -FunctionBoundParameters $PSBoundParameters `
    393             -ArgumentNames ('MinimumVersion', 'MaximumVersion', 'RequiredVersion')
    394 
    395         $null = Test-VersionParameter @extractedArguments
    396 
    397         try {
    398             $extractedArguments = New-SplatParameterHashTable -FunctionBoundParameters $PSBoundParameters `
    399                 -ArgumentNames ('Name', 'Repository', 'MinimumVersion', 'MaximumVersion', 'RequiredVersion')
    400 
    401             Write-Verbose -Message ($localizedData.StartFindModule -f $Name)
    402 
    403             $modules = Find-Module @extractedArguments -ErrorVariable ev
    404         }
    405         catch {
    406             $errorMessage = $script:localizedData.ModuleNotFoundInRepository -f $Name
    407             New-InvalidOperationException -Message $errorMessage -ErrorRecord $_
    408         }
    409 
    410         $trusted = $null
    411         $moduleFound = $null
    412 
    413         foreach ($m in $modules) {
    414             # Check for the installation policy.
    415             $trusted = Get-InstallationPolicy -RepositoryName $m.Repository -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
    416 
    417             # Stop the loop if found a trusted repository.
    418             if ($trusted) {
    419                 $moduleFound = $m
    420                 break;
    421             }
    422         }
    423 
    424         try {
    425             # The repository is trusted, so we install it.
    426             if ($trusted) {
    427                 Write-Verbose -Message ($localizedData.StartInstallModule -f $Name, $moduleFound.Version.toString(), $moduleFound.Repository)
    428 
    429                 # Extract the installation options.
    430                 $extractedSwitches = New-SplatParameterHashTable -FunctionBoundParameters $PSBoundParameters -ArgumentNames ('Force', 'AllowClobber', 'SkipPublisherCheck')
    431 
    432                 $moduleFound | Install-Module @extractedSwitches 2>&1 | out-string | Write-Verbose
    433             }
    434             # The repository is untrusted but user's installation policy is trusted, so we install it with a warning.
    435             elseif ($InstallationPolicy -ieq 'Trusted') {
    436                 Write-Warning -Message ($localizedData.InstallationPolicyWarning -f $Name, $modules[0].Repository, $InstallationPolicy)
    437 
    438                 # Extract installation options (Force implied by InstallationPolicy).
    439                 $extractedSwitches = New-SplatParameterHashTable -FunctionBoundParameters $PSBoundParameters -ArgumentNames ('AllowClobber', 'SkipPublisherCheck')
    440 
    441                 # If all the repositories are untrusted, we choose the first one.
    442                 $modules[0] | Install-Module @extractedSwitches -Force 2>&1 | out-string | Write-Verbose
    443             }
    444             # Both user and repository is untrusted
    445             else {
    446                 $errorMessage = $script:localizedData.InstallationPolicyFailed -f $InstallationPolicy, 'Untrusted'
    447                 New-InvalidOperationException -Message $errorMessage
    448             }
    449 
    450             Write-Verbose -Message ($localizedData.InstalledSuccess -f $Name)
    451         }
    452         catch {
    453             $errorMessage = $script:localizedData.FailToInstall -f $Name
    454             New-InvalidOperationException -Message $errorMessage -ErrorRecord $_
    455         }
    456     }
    457     # Ensure=Absent
    458     else {
    459 
    460         $extractedArguments = New-SplatParameterHashTable -FunctionBoundParameters $PSBoundParameters `
    461             -ArgumentNames ('Name', 'Repository', 'MinimumVersion', 'MaximumVersion', 'RequiredVersion')
    462 
    463         # Get the module with the right version and repository properties.
    464         $modules = Get-RightModule @extractedArguments
    465 
    466         if (-not $modules) {
    467             $errorMessage = $script:localizedData.ModuleWithRightPropertyNotFound -f $Name
    468             New-InvalidOperationException -Message $errorMessage
    469         }
    470 
    471         foreach ($module in $modules) {
    472             # Get the path where the module is installed.
    473             $path = $module.ModuleBase
    474 
    475             Write-Verbose -Message ($localizedData.StartUnInstallModule -f $Name)
    476 
    477             try {
    478                 <#
    479                     There is no Uninstall-Module cmdlet for Windows PowerShell 4.0,
    480                     so we will remove the ModuleBase folder as an uninstall operation.
    481                 #>
    482                 Microsoft.PowerShell.Management\Remove-Item -Path $path -Force -Recurse
    483 
    484                 Write-Verbose -Message ($localizedData.UnInstalledSuccess -f $module.Name)
    485             }
    486             catch {
    487                 $errorMessage = $script:localizedData.FailToUninstall -f $module.Name
    488                 New-InvalidOperationException -Message $errorMessage -ErrorRecord $_
    489             }
    490         } # foreach
    491     } # Ensure=Absent
    492 }
    493 
    494 <#
    495     .SYNOPSIS
    496         This is a helper function. It returns the modules that meet the specified versions and the repository requirements.
    497 
    498     .PARAMETER Name
    499         Specifies the name of the PowerShell module.
    500 
    501     .PARAMETER RequiredVersion
    502         Provides the version of the module you want to install or uninstall.
    503 
    504     .PARAMETER MaximumVersion
    505         Provides the maximum version of the module you want to install or uninstall.
    506 
    507     .PARAMETER MinimumVersion
    508         Provides the minimum version of the module you want to install or uninstall.
    509 
    510     .PARAMETER Repository
    511         Specifies the name of the module source repository where the module can be found.
    512 #>
    513 function Get-RightModule {
    514     <#
    515         These suppressions are added because this repository have other Visual Studio Code workspace
    516         settings than those in DscResource.Tests DSC test framework.
    517         Only those suppression that contradict this repository guideline is added here.
    518     #>
    519     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-ForEachStatement', '')]
    520     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-FunctionBlockBraces', '')]
    521     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-IfStatement', '')]
    522     [CmdletBinding()]
    523     param
    524     (
    525         [Parameter(Mandatory = $true)]
    526         [ValidateNotNullOrEmpty()]
    527         [System.String]
    528         $Name,
    529 
    530         [Parameter()]
    531         [System.String]
    532         $RequiredVersion,
    533 
    534         [Parameter()]
    535         [System.String]
    536         $MinimumVersion,
    537 
    538         [Parameter()]
    539         [System.String]
    540         $MaximumVersion,
    541 
    542         [Parameter()]
    543         [System.String]
    544         $Repository
    545     )
    546 
    547     Write-Verbose -Message ($localizedData.StartGetModule -f $($Name))
    548 
    549     $modules = Microsoft.PowerShell.Core\Get-Module -Name $Name -ListAvailable -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
    550 
    551     if (-not $modules) {
    552         return $null
    553     }
    554 
    555     <#
    556         As Get-Module does not take RequiredVersion, MinimumVersion, MaximumVersion, or Repository,
    557         below we need to check whether the modules are containing the right version and repository
    558         location.
    559     #>
    560 
    561     $extractedArguments = New-SplatParameterHashTable -FunctionBoundParameters $PSBoundParameters `
    562         -ArgumentNames ('MaximumVersion', 'MinimumVersion', 'RequiredVersion')
    563     $returnVal = @()
    564 
    565     foreach ($m in $modules) {
    566         $versionMatch = $false
    567         $installedVersion = $m.Version
    568 
    569         # Case 1 - a user provides none of RequiredVersion, MinimumVersion, MaximumVersion
    570         if ($extractedArguments.Count -eq 0) {
    571             $versionMatch = $true
    572         }
    573 
    574         # Case 2 - a user provides RequiredVersion
    575         elseif ($extractedArguments.ContainsKey('RequiredVersion')) {
    576             # Check if it matches with the installed version
    577             $versionMatch = ($installedVersion -eq [System.Version] $RequiredVersion)
    578         }
    579         else {
    580 
    581             # Case 3 - a user provides MinimumVersion
    582             if ($extractedArguments.ContainsKey('MinimumVersion')) {
    583                 $versionMatch = ($installedVersion -ge [System.Version] $extractedArguments['MinimumVersion'])
    584             }
    585 
    586             # Case 4 - a user provides MaximumVersion
    587             if ($extractedArguments.ContainsKey('MaximumVersion')) {
    588                 $isLessThanMax = ($installedVersion -le [System.Version] $extractedArguments['MaximumVersion'])
    589 
    590                 if ($extractedArguments.ContainsKey('MinimumVersion')) {
    591                     $versionMatch = $versionMatch -and $isLessThanMax
    592                 }
    593                 else {
    594                     $versionMatch = $isLessThanMax
    595                 }
    596             }
    597 
    598             # Case 5 - Both MinimumVersion and MaximumVersion are provided. It's covered by the above.
    599             # Do not return $false yet to allow the foreach to continue
    600             if (-not $versionMatch) {
    601                 Write-Verbose -Message ($localizedData.VersionMismatch -f $Name, $installedVersion)
    602                 $versionMatch = $false
    603             }
    604         }
    605 
    606         # Case 6 - Version matches but need to check if the module is from the right repository.
    607         if ($versionMatch) {
    608             # A user does not provide Repository, we are good
    609             if (-not $PSBoundParameters.ContainsKey('Repository')) {
    610                 Write-Verbose -Message ($localizedData.ModuleFound -f "$Name $installedVersion")
    611                 $returnVal += $m
    612             }
    613             else {
    614                 # Check if the Repository matches
    615                 $sourceName = Get-ModuleRepositoryName -Module $m
    616 
    617                 if ($Repository -ieq $sourceName) {
    618                     Write-Verbose -Message ($localizedData.ModuleFound -f "$Name $installedVersion")
    619                     $returnVal += $m
    620                 }
    621                 else {
    622                     Write-Verbose -Message ($localizedData.RepositoryMismatch -f $($Name), $($sourceName))
    623                 }
    624             }
    625         }
    626     } # foreach
    627 
    628     return $returnVal
    629 }
    630 
    631 <#
    632     .SYNOPSIS
    633         This is a helper function that returns the module's repository name.
    634 
    635     .PARAMETER Module
    636         Specifies the name of the PowerShell module.
    637 #>
    638 function Get-ModuleRepositoryName {
    639     <#
    640         These suppressions are added because this repository have other Visual Studio Code workspace
    641         settings than those in DscResource.Tests DSC test framework.
    642         Only those suppression that contradict this repository guideline is added here.
    643     #>
    644     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-FunctionBlockBraces', '')]
    645     [Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-IfStatement', '')]
    646     [CmdletBinding()]
    647     param
    648     (
    649         [Parameter(Mandatory = $true)]
    650         [ValidateNotNullOrEmpty()]
    651         [System.Object]
    652         $Module
    653     )
    654 
    655     <#
    656         RepositorySourceLocation property is supported in PS V5 only. To work with the earlier
    657         PowerShell version, we need to do a different way. PSGetModuleInfo.xml exists for any
    658         PowerShell modules downloaded through PSModule provider.
    659     #>
    660     $psGetModuleInfoFileName = 'PSGetModuleInfo.xml'
    661     $psGetModuleInfoPath = Microsoft.PowerShell.Management\Join-Path -Path $Module.ModuleBase -ChildPath $psGetModuleInfoFileName
    662 
    663     Write-Verbose -Message ($localizedData.FoundModulePath -f $psGetModuleInfoPath)
    664 
    665     if (Microsoft.PowerShell.Management\Test-path -Path $psGetModuleInfoPath) {
    666         $psGetModuleInfo = Microsoft.PowerShell.Utility\Import-Clixml -Path $psGetModuleInfoPath
    667 
    668         return $psGetModuleInfo.Repository
    669     }
    670 }
    671 
    672 # SIG # Begin signature block
    673 # MIIjkgYJKoZIhvcNAQcCoIIjgzCCI38CAQExDzANBglghkgBZQMEAgEFADB5Bgor
    674 # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
    675 # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCig4H1kVMWxA7U
    676 # uX1JaRBJmDsHSZHmuBUTkDBwWHafCqCCDYEwggX/MIID56ADAgECAhMzAAABh3IX
    677 # chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
    678 # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
    679 # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
    680 # bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw
    681 # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
    682 # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
    683 # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
    684 # AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB
    685 # znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH
    686 # sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d
    687 # weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ
    688 # itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV
    689 # Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
    690 # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw
    691 # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
    692 # ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu
    693 # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
    694 # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
    695 # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
    696 # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
    697 # MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy
    698 # S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K
    699 # NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV
    700 # BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr
    701 # qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx
    702 # zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe
    703 # yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g
    704 # yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf
    705 # AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI
    706 # 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5
    707 # GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea
    708 # jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS
    709 # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
    710 # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
    711 # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
    712 # ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
    713 # MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
    714 # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
    715 # H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
    716 # AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
    717 # OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
    718 # 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
    719 # y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
    720 # 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
    721 # M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
    722 # X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
    723 # XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
    724 # 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
    725 # l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
    726 # RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
    727 # CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
    728 # BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
    729 # DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
    730 # 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
    731 # LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
    732 # Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
    733 # Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
    734 # Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
    735 # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
    736 # cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
    737 # XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
    738 # 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
    739 # 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
    740 # d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
    741 # Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
    742 # wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
    743 # aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
    744 # NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
    745 # xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
    746 # eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
    747 # r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
    748 # RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZzCCFWMCAQEwgZUwfjELMAkG
    749 # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
    750 # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
    751 # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN
    752 # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
    753 # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg2t+ikpO2
    754 # 0WdDEf/JRKsEEOWFz2O6CEnKmWwPbrvPFuIwQgYKKwYBBAGCNwIBDDE0MDKgFIAS
    755 # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
    756 # BgkqhkiG9w0BAQEFAASCAQBaj/JIwAbud/IMJN3SHVwenJwEjzrmM3cPznYlvkyE
    757 # rnB6RiDYnohm+72wkCmVWobuualV9Xw8OGA9w7MvJjZuEnFP9TwDjlWinR4FpdVl
    758 # YX49u4g50iMR2isaKTxMA2nA2LbyFpTLMqi6ynPLnv251xTdumj/XRLZjHdpr4Pt
    759 # p6HQz45/jMWRtlh8x3piJPrgpINuJtmO91tnMQnykF++QgteDqKSboXOu2Wg0oCn
    760 # Ao0eOifIujyUp2ez9Cqx2hzkMOqNa5jZD4JetiDTWBTkN8XHRbsfCVwyEQzxrpXn
    761 # wAFT7jMzuI8o8xdCuCvuDokIzcnm+rKZJIy6Rwp6Cn11oYIS8TCCEu0GCisGAQQB
    762 # gjcDAwExghLdMIIS2QYJKoZIhvcNAQcCoIISyjCCEsYCAQMxDzANBglghkgBZQME
    763 # AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB
    764 # MDEwDQYJYIZIAWUDBAIBBQAEIL/3GmTbcOXlRJe8Pu+1/QVBo0Mk83o/PGK7iApB
    765 # aAutAgZfYQoJ7SUYEzIwMjAwOTIyMjIxOTUxLjg4NlowBIACAfSggdSkgdEwgc4x
    766 # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
    767 # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p
    768 # Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg
    769 # VFNTIEVTTjo4OTdBLUUzNTYtMTcwMTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt
    770 # U3RhbXAgU2VydmljZaCCDkQwggT1MIID3aADAgECAhMzAAABLCKvRZd1+RvuAAAA
    771 # AAEsMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo
    772 # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
    773 # cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw
    774 # MB4XDTE5MTIxOTAxMTUwM1oXDTIxMDMxNzAxMTUwM1owgc4xCzAJBgNVBAYTAlVT
    775 # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK
    776 # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy
    777 # YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo4OTdB
    778 # LUUzNTYtMTcwMTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj
    779 # ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPK1zgSSq+MxAYo3qpCt
    780 # QDxSMPPJy6mm/wfEJNjNUnYtLFBwl1BUS5trEk/t41ldxITKehs+ABxYqo4Qxsg3
    781 # Gy1ugKiwHAnYiiekfC+ZhptNFgtnDZIn45zC0AlVr/6UfLtsLcHCh1XElLUHfEC0
    782 # nBuQcM/SpYo9e3l1qY5NdMgDGxCsmCKdiZfYXIu+U0UYIBhdzmSHnB3fxZOBVcr5
    783 # htFHEBBNt/rFJlm/A4yb8oBsp+Uf0p5QwmO/bCcdqB15JpylOhZmWs0sUfJKlK9E
    784 # rAhBwGki2eIRFKsQBdkXS9PWpF1w2gIJRvSkDEaCf+lbGTPdSzHSbfREWOF9wY3i
    785 # Yj8CAwEAAaOCARswggEXMB0GA1UdDgQWBBRRahZSGfrCQhCyIyGH9DkiaW7L0zAf
    786 # BgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBH
    787 # hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNU
    788 # aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF
    789 # BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0
    790 # YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG
    791 # AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQBPFxHIwi4vAH49w9Svmz6K3tM55RlW
    792 # 5pPeULXdut2Rqy6Ys0+VpZsbuaEoxs6Z1C3hMbkiqZFxxyltxJpuHTyGTg61zfNI
    793 # F5n6RsYF3s7IElDXNfZznF1/2iWc6uRPZK8rxxUJ/7emYXZCYwuUY0XjsCpP9pbR
    794 # RKeJi6r5arSyI+NfKxvgoM21JNt1BcdlXuAecdd/k8UjxCscffanoK2n6LFw1PcZ
    795 # lEO7NId7o+soM2C0QY5BYdghpn7uqopB6ixyFIIkDXFub+1E7GmAEwfU6VwEHL7y
    796 # 9rNE8bd+JrQs+yAtkkHy9FmXg/PsGq1daVzX1So7CJ6nyphpuHSN3VfTMIIGcTCC
    797 # BFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC
    798 # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
    799 # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv
    800 # b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcN
    801 # MjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
    802 # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
    803 # aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCASIw
    804 # DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0
    805 # VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEwWbEw
    806 # RA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQe
    807 # dGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJUGKx
    808 # Xf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw2k4G
    809 # kbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0CAwEA
    810 # AaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7
    811 # fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC
    812 # AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX
    813 # zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v
    814 # cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI
    815 # KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j
    816 # b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0g
    817 # AQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93
    818 # d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYB
    819 # BQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUA
    820 # bQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9naOh
    821 # IW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtRgkQS
    822 # +7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzymXlK
    823 # kVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon
    824 # /VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3DnKOi
    825 # PPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/
    826 # fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110mCII
    827 # YdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0
    828 # cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7a
    829 # KLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQ
    830 # cdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+
    831 # NR4Iuto229Nfj950iEkSoYIC0jCCAjsCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT
    832 # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
    833 # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP
    834 # cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo4
    835 # OTdBLUUzNTYtMTcwMTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy
    836 # dmljZaIjCgEBMAcGBSsOAwIaAxUADE5OKSMoNx/mYxYWap1RTOohbJ2ggYMwgYCk
    837 # fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
    838 # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
    839 # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF
    840 # AOMUwsMwIhgPMjAyMDA5MjIyMjM2NTFaGA8yMDIwMDkyMzIyMzY1MVowdzA9Bgor
    841 # BgEEAYRZCgQBMS8wLTAKAgUA4xTCwwIBADAKAgEAAgIlfwIB/zAHAgEAAgIRzTAK
    842 # AgUA4xYUQwIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB
    843 # AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAEmZCk5PsMA6oG40
    844 # YulPUpxDtQA+JAuXyNrLI4wJcdmv34Bzmj9gk3gv6ZxQZxlvZjA1O1P3lcKGIYco
    845 # 9UkRdAeP6Zzfim6U3UoiUz1AHKuSm6iLux7Z/hNtgEs2ZpYXxOK5JZ/9Pa2I5mg0
    846 # VxsGdXBxl6TOZqbB6aGNG1ZKytRWMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMC
    847 # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
    848 # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp
    849 # bWUtU3RhbXAgUENBIDIwMTACEzMAAAEsIq9Fl3X5G+4AAAAAASwwDQYJYIZIAWUD
    850 # BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B
    851 # CQQxIgQgioHn9SQtTXybUUTzgPmt61UPBGskDV9AErEC62Y8+H4wgfoGCyqGSIb3
    852 # DQEJEAIvMYHqMIHnMIHkMIG9BCBbn/0uFFh42hTM5XOoKdXevBaiSxmYK9Ilcn9n
    853 # u5ZH4TCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
    854 # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
    855 # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB
    856 # LCKvRZd1+RvuAAAAAAEsMCIEIJmkMFyuUW5yiXAemMCWHyk8T1EMMlB1cEiVD4/E
    857 # +vhqMA0GCSqGSIb3DQEBCwUABIIBAOyFm0zpO+VogyMfTuCFeJjMyyDnAJRy/KhW
    858 # jtq11pPg3e11HU0LuNa+ZpCrJXbSWlF+tLkU9eQXPpGPzO7ITGhxhnq5wyhfzA8a
    859 # 9TRGlDMUNHp+6WhH6BZ86zUqMpcYx5zN0H9TaJTpC8JJ7HrNTW8zp032ocr6IXVr
    860 # M6mOa0MUZsE366+OXRpCCm0fokT50uvXWbcRdngS9ZT5xmz134T1iS4Fds7ZOC5W
    861 # m0VofKEuaTYbTc5aF0WN/OGMvowHRxlJhG7zhMX8ZuXGvbgzANq/o7tZu0HmGFTN
    862 # rPs5smC3VEWVpNWgOTfrO3bfaWkAdsuBeLVXZUog+M4wmTDFSPs=
    863 # SIG # End signature block