Git Product home page Git Product logo

dangough / nevergreen Goto Github PK

View Code? Open in Web Editor NEW
74.0 74.0 18.0 203 KB

This module is an alternative to Evergreen, and allows you to find the latest version and download URL for various Windows apps. Evergreen uses API queries to obtain its data whereas this module is more focussed on web scraping. This is more prone to breaking when websites are changed, hence the name.

License: The Unlicense

PowerShell 100.00%

nevergreen's People

Contributors

ashleyhow avatar codaamok avatar dangough avatar dezzie71 avatar jonathanpitre avatar thatdraggycodes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

nevergreen's Issues

[Broken] JabraDirect

Seems the logic for Jabra Direct is borked. Not a issue for me, just a heads up. :)

PS C:\Windows\system32> Nevergreen\Get-NevergreenApp -Name 'JabraDirect'
WARNING: No version found within 
--- a lot of HTML ---
Nevergreen\Get-NevergreenApp : Error retriving results for 'JabraDirect': Get-JabraDirect.ps1: Cannot validate argument on parameter 'Version'. The argument is null or empty. Provide an argument that is not null or 
empty, and then try the command again.
At line:1 char:1
+ Nevergreen\Get-NevergreenApp -Name 'JabraDirect'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-NevergreenApp
 

PS C:\Windows\system32> 

And version of the module

PS C:\Windows\system32> Get-Module -Name 'Nevergreen'

ModuleType Version    Name                                ExportedCommands                                                                                                                                               
---------- -------    ----                                ----------------                                                                                                                                               
Script     2109.1     Nevergreen                          {Find-NevergreenApp, Get-NevergreenApp}                                                                                                                        



PS C:\Windows\system32> 

[New App Request] OpenSSL

Updated script on 24th July 2024, due to OpenSSL changing their Website URLs and the formatting of content

I have written a new NeverGreen script to return each of the latest versions of OpenSSL (3.0.x, 3.1.x, 3.2.x & 3.3.x), (this is predominantly to be used for reporting purposes to give me an idea of new releases to fix security vulnerabilities).
The detail is obtained using a webscrape against their downloads page: https://openssl-library.org/source/index.html

N.B. As the downloads are .tar.gz format, I have added this as a valid file type to the $Type attribute in New-NevergreenApp.ps1
Also as I introduced the new ReleaseDate attribute in the #65 New issue, I have made use of it in here too.

Here is my script:

# Get-OpenSSL.ps1

$AppName = "OpenSSL"
$ReleaseURL = 'https://openssl-library.org/source/index.html'

$Releases = @(
    @{Type = 'Gz'; Ring ='3.0'; Pattern = '(3\.0\.\d+)'}
    @{Type = 'Gz'; Ring ='3.1'; Pattern = '(3\.1\.\d+)'}
    @{Type = 'Gz'; Ring ='3.2'; Pattern = '(3\.2\.\d+)'}
    @{Type = 'Gz'; Ring ='3.3'; Pattern = '(3\.3\.\d+)'}
)

foreach ($Release in $Releases) {
	$URL = Set-UriPrefix -Uri (Get-Link -Uri $ReleaseURL -MatchProperty href -Pattern $Release.Pattern) -Prefix $ReleaseURL
    [version]$Version = Get-Version -String $URL -Pattern '(\d+\.\d+\.\d+)'

	#Obtain Release Date and convert to "yyyy-MM-dd" format
	try {
		$Content = (Invoke-WebRequest -Uri $ReleaseURL).Content

		#$ReleaseDateRegEx = "(?s)(\d{4}-\w{3}-\d{2}).*?$($Release.Pattern)\."
		$ReleaseDateRegEx = "(?s)$($Release.Pattern).*?(\d{2}\s\w{3}\s\d{4})"

		# Extract the captured groups and display them
		foreach ($match in [regex]::Matches($Content, $ReleaseDateRegEx)) {
			$ReleasedOn = $match.Groups[2].Value  # Date group
		}
	}
	catch {
		Throw "Failed to connect to ($($ReleaseUrl)) with error $_."
		Break
	}
	finally {
		# Define a regular expression pattern to match a date in the format "Year-Month-Day"
		$pattern = "\d{1,2}\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|January|February|March|April|May|June|July|August|September|October|November|December)\s\d{4}"

		# Use Select-String to find the date in the text
		$matchesfound = $ReleasedOn | Select-String -Pattern $pattern

		# Extract the matched date
		if ($matchesfound) {
			# Parse the date and reformat it to "YYYY-MM-DD"
			$ReleaseDate = (Get-Date $ReleasedOn).ToString("yyyy-MM-dd")
		} else {
			Write-Verbose "Date not found in the text."
			$ReleaseDate = ""
		}
		# Success
		New-NevergreenApp -Name $AppName -Architecture 'multi' -Version $Version -ReleaseDate $ReleaseDate -Uri $URL -Type $Release.Type -Ring $Release.Ring
	}
}

[New App Request] Google Workspace Sync for Microsoft Outlook

I have written a new NeverGreen script to return the latest versions of Google Worklspace Sync for Microsoft Outlook, this is obtained using a webscrape against their release notes page: https://support.google.com/a/answer/153463

N.B. The Uris have been obtained from both the Downloads page - for .Msi's (recommended for admin installs), and a direct link to the .exe file (recommended for user installs)

here is my script:

# Get-GoogleWorkspaceSync.ps1

$AppName = "Google Workspace Sync"

$Apps = @(
    @{Architecture = 'x64'; Type = 'Msi'; Pattern = 'Download 64-bit edition' } # Recommended for admins
    @{Architecture = 'x86'; Type = 'Msi'; Pattern = 'Download 32-bit edition' } # Recommended for admins
    @{Architecture = 'x86'; Type = 'Exe'; Pattern = 'Download GWSMO' } # Recommended for users
)

foreach ($App in $Apps) {
    try {
		$ReleaseURL = 'https://support.google.com/a/answer/153463'
		if ($App.Type -eq 'Exe'){
			$URL = 'https://dl.google.com/google-apps-sync/googleappssyncsetup.exe'
		} else {
			$DownloadURL = 'https://tools.google.com/dlpage/gssmo'
			$URL = Get-Link -Uri $DownloadURL -MatchProperty outerHTML -Pattern $App.Pattern
		}

        $Version = Get-Version -Uri $ReleaseURL -Pattern 'Release notes for (\d+\.\d+\.\d+\.\d+)'
        New-NevergreenApp -Name $AppName -Version $Version -Uri $URL -Architecture $App.Architecture -Type $App.Type
    }
    catch {
        Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
    }
}

Add Notepad3

https://www.rizonesoft.com/downloads/notepad3

We can improve the following code with Nevergreen standard.

$webRequest = Invoke-WebRequest -UseBasicParsing -Uri ("https://www.rizonesoft.com/downloads/notepad3") -SessionVariable websession
$regexURL = "https\:\/\/www\.rizonesoft\.com\/download\/\d.+/"
$regexZip = "Notepad3_\d.\d{2}.\d{3}.\d_Setup.zip"
$appURL = $webRequest.RawContent | Select-String -Pattern $regexURL -AllMatches | ForEach-Object { $_.Matches.Value } | Select-Object -First 1
$appZip = $webRequest.RawContent | Select-String -Pattern $regexZip -AllMatches | ForEach-Object { $_.Matches.Value } | Select-Object -First 1
$appVersion = $appZip.Split("_")[1]
$appSetup = "Notepad3_$($appVersion)_Setup.exe"

Adobe Reader - Missing x64 MUI Patch

Can be added, by adding:

@{Architecture = 'x64'; Language = 'Multi'; Pattern = 'AcroRdrDCx64Upd\d{8,12}_MUI\.msp'}

to Get-AdobeAcrobatReader.ps1

Adobe Creative Cloud returning wrong uri/version for x86 and x64

image

It should return the following...

Version   Uri                                                                              Architecture
-------   ---                                                                              ------------
4.9.0.504 https://ccmdl.adobe.com/AdobeProducts/KCCC/CCD/4_9/win32/ACCCx4_9_0_504.zip      x86
5.4.5.550 https://ccmdl.adobe.com/AdobeProducts/KCCC/CCD/5_4_5/win64/ACCCx5_4_5_550.zip    x64
5.4.5.550 https://ccmdl.adobe.com/AdobeProducts/KCCC/CCD/5_4_5/winarm64/ACCCx5_4_5_550.zip ARM64

[New App Request] Dell Command | Update

I have written a new NeverGreen script to return the latest versions of Dell Command | Update for Windows, this is obtained using a webscrape against the Dell Command | Update Summary page https://www.dell.com/support/kbdoc/en-uk/000177325/dell-command-update

N.B. The downloads ($URL in my script) are obtained from their own sub page ($ReleaseURL in my script) links from the Summary page

# Get-DellCommandUpdate.ps1

$AppName = "Dell Command Update"
$SummaryURL = 'https://www.dell.com/support/kbdoc/en-uk/000177325/dell-command-update'
[version]$Version = Get-Version -Uri $SummaryURL -Pattern '- Dell Command \| Update (\d+\.\d+\.\d+)'
Write-Verbose "Version :: $Version"

$Platforms = @(
    @{Architecture = 'x86'; Platform = 'Windows Universal Application'; Language = 'Neutral'; Pattern = 'Dell Command \| Update Windows Universal Application'; Download = 'Dell-Command-Update-Windows-Universal-Application_.*?_WIN_.*?\.EXE'}
    @{Architecture = 'x86'; Platform = 'Windows Application (Classic)'; Language = 'Neutral'; Pattern = 'Dell Command \| Update Application \(Classic\)'; Download = 'Dell-Command-Update-Application_.*?_WIN_.*?\.EXE'}
)

foreach ($Platform in $Platforms) {
	$SearchCount = 2

	do {
		$ReleaseURL = Get-Link -Uri $SummaryURL -MatchProperty outerHTML -Pattern $Platform.Pattern
		#Write-Verbose "Release URL :: $ReleaseURL"

		$URL = Get-Link -Uri $ReleaseURL -MatchProperty href -Pattern $Platform.Download
		#Write-Verbose "Download URL :: $URL"

		if ($URL) {
			New-NevergreenApp -Name $($AppName) -Version $Version -Uri $URL -Architecture $Platform.Architecture -Platform $Platform.Platform -Language $Platform.Language -Type 'exe'
			break
		}
		$SearchCount--
	} until ($SearchCount -eq 0)

	if ($SearchCount -eq 0) {
		Write-Warning "Could not find release for $($AppName) $($Platform.Platform) $($Platform.Architecture) $($Platform.Language)"
	}
}

TikTok Effect House [New App Request]

I would like to be able to screen scrape the Tiktok Effects House downloads page to obtain the URL for the latest version download

Download URL : "https://effecthouse.tiktok.com/download"
Release Notes : "https://effecthouse.tiktok.com/latest/release-notes-latest/"

I have managed to read the latest version number (from the Release Notes page), but have so far been unable to find the installer URL from the downloads page - this is what I have acheived so far with the following Powershell:

[cmdletbinding()]
Param()

Clear-Host
Write-Verbose "Setting Arguments" -Verbose

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$DetectionMethod = "Webscrape"
$AppName = "TikTokEffectHouse"
$Application = "TikTok Effect House"
#$Arch = "x64"
$AppType = "EXE"
$AppInstaller = "Effect_House_Setup.exe"
$InstallPath = "$($env:LOCALAPPDATA)\Effect House\Effect House.exe"
$DownloadsURL = "https://effecthouse.tiktok.com/download"
$ReleaseNotes = "https://effecthouse.tiktok.com/latest/release-notes-latest/"

# $PSScriptRoot should always be something like C:\Users\FSmith\gitrepos\Intune\Admin\Scripts.
# Our Base folder should be 'Intune', or 2 levels up.
$BaseFolder = "$PSScriptRoot\..\.."
$AllAppsFolder = ".\Apps"
$PrepToolExe = ".\Microsoft-Win32-Content-Prep-Tool-1.8.4\IntuneWinAppUtil.exe"

$StartTime = Get-Date

Write-Verbose "Finding installed version" -Verbose
# Check if App is installed and if it is get version
if (Test-Path -Path $InstallPath) {
    [version]$InstalledVersion = (Get-ItemProperty $InstallPath).VersionInfo.FileVersion
    Write-Host "Installed version of $($Application) is: $($InstalledVersion)"
} else {
    Write-Host "WARNING :: $($Application) is not installed" -ForegroundColor Red
}

Write-Verbose "Using $($DetectionMethod) to check for latest version from: $($ReleaseNotes)..." -Verbose
try {
    # $Web = Invoke-WebRequest -UseBasicParsing -Uri $DownloadsUrl -ErrorAction SilentlyContinue
    $Web = Invoke-WebRequest -UseBasicParsing -Uri $ReleaseNotes -ErrorAction SilentlyContinue
}
catch {
    Throw "Failed to connect to URL: $ReleaseNotes with error $_."
    Break
}
finally {
# Luckily, although this web page covers a major release it only seems to have active links to the very latest update.
# So we can determine the latest version by searching for specific text in the page...
    $PageContent = ($Web.Content)
    $SearchString = "</style><h2 class=`"css-ov5iey e15xsn0a4`">v"
    $CaptureStart = $PageContent.IndexOf($SearchString) + $SearchString.Length
    $EndIndex = $PageContent.IndexOf(" (", $CaptureStart) - $CaptureStart
    $Version = ($PageContent.Substring($CaptureStart, $EndIndex).Trim()) -replace "\.","-"
    [version]$LatestVersion = ($PageContent.Substring($CaptureStart, $EndIndex).Trim()) -replace "-","."
}

Write-Output "Latest version of $($Application) is:          $($LatestVersion)"

Write-Verbose "Using $($DetectionMethod) to find latest version download from: $($DownloadsURL)..." -Verbose
try {
    # $Web = Invoke-WebRequest -UseBasicParsing -Uri $DownloadsUrl -ErrorAction SilentlyContinue
    $Download = Invoke-WebRequest -UseBasicParsing -Uri $DownloadsURL -ErrorAction SilentlyContinue
}
catch {
    Throw "Failed to connect to URL: $DownloadsURL with error $_."
    Break
}
finally {
# This web page only seems to have an active link to the very latest update - obscured by CSS.
# So we need to determine the latest version download by searching within the links on the page...
    $DownloadContent = (($Download.Links | Where-Object {$_.href -eq "/download"}).outerHTML)
    <#
    $SourceUrl = "" # To be read from page ?
    #>
    # Current Download URL for v3.3.2.87 has been obtained in a browser:
    $SourceUrl = "https://sf16-va.tiktokcdn.com/obj/eden-va2/olaa_ajlmml_zlp/ljhwZthlaukjlkulzlp/V332_External_Release_0927/Effect_House_v3.3.2.87_101_Setup.exe"
}

<#
Other code...
N.B. Includes setting path to $Outfile
#>

# New Version available, so open Release Notes
$ReleaseNotesURL = "https://effecthouse.tiktok.com/effect-platform/latest/release-notes-latest/v$($version)/?enter_method=category_card"
Write-Output ""
Write-Host "New version $($LatestVersion) has been released, Opening release notes in default browser..." -ForegroundColor DarkGreen
Start-Process $ReleaseNotesURL
Write-Output ""

# Download the latest Installer
Write-Output ""
Write-Output "Downloading $($Application) $($LatestVersion) from $($SourceUrl)..."
$ProgressPreference = 'SilentlyContinue'
Invoke-WebRequest -Uri $SourceUrl -OutFile $Outfile

Irfanview download URL is not working

Irfanview download URL is not working, it downloads an incomplete file. The same issue occurs with the setup and plugin file.

https://www.fosshub.com/IrfanView.html?dwl=iview460_x64_setup.exe
redirects to
https://download.fosshub.com/Protected/expiretime=1648034402;badurl=aHR0cHM6Ly93d3cuZm9zc2h1Yi5jb20vSXJmYW5WaWV3Lmh0bWw=/7939fbcbd770399eb8f3f3a68222a6deb6255eff5c6ef1435077df24aacc7d3c/5b8d1f5659eee027c3d7883a/623457812413750bd71fef36/iview460_x64_setup.exe
for instance.

I tried the Resolve-Uri function and I still can't get it to work.

Maybe it would be easier to switch the source links to betanews.com, just like Eric did?

https://github.com/haavarstein/Applications/blob/master/Misc/IrfanView/Install.ps1

MicrosoftAzureInformationProtection does not work anymore

`Get-Nevergreenapp -Name MicrosoftAzureInformationProtection
get-nevergreenapp : Error retriving results for 'MicrosoftAzureInformationProtection': Cannot validate
argument on parameter 'Uri'. The argument "" does not match the "^(http|https)://" pattern. Supply an
argument that matches "^(http|https)://" and try the command again.
At line:1 char:1

  • get-nevergreenapp -Name MicrosoftAzureInformationProtection
  •   + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
      + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-NevergreenApp`
    

[New App Request] FileZilla

After a long running conversation with Aaron Parker on the Evergreen Issues page regarding FileZilla no longer working via Evergreen (aaronparker/evergreen#581) and with your input it has lead me to investigate using NeverGreen to solve this problem

I now understand why Nevergreen is exactly the right way to solve this 'web scrape problem' ๐Ÿ˜

Using your Get-AdobeAcrobatReader.ps1 script as a template, I have created a new Get-FileZilla.ps1 script, which works exactly as required for my purposes.
N.B. I have removed the Language attribute (as FileZilla is not language specific)
I have added a Headers splat to include the Headers that the FileZilla site requires / expects before it will serve content
I guess the Platforms that Filezilla supports 'could' be expanded in the future for other OS distributions, but for now I'm assuming this module is only likely to be used for Windows.

Here's my script, feel free to check and include in any future release(s) of NeverGreen:

# Get-Filezilla.ps1
$Platforms = @(
    @{Architecture = 'x86'; Type = 'exe'; Pattern = 'FileZilla_\d+\.\d+\.\d+_win32-setup\.exe'}
    @{Architecture = 'x64'; Type = 'exe'; Pattern = 'FileZilla_\d+\.\d+\.\d+_win64-setup\.exe'}
    @{Architecture = 'x86'; Type = 'zip'; Pattern = 'FileZilla_\d+\.\d+\.\d+_win32\.zip'}
    @{Architecture = 'x64'; Type = 'zip'; Pattern = 'FileZilla_\d+\.\d+\.\d+_win64\.zip'}
)

foreach ($Platform in $Platforms) {

    $ReleaseURL = 'https://filezilla-project.org/download.php?show_all=1'
    $SearchCount = 3

    $Headers = @{
	"Accept"="*/*"
	"Accept-Language"="en-GB,en;q=0.9,en-US;q=0.8"
	"User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0"
        "Host" = "filezilla-project.org"
    }

    do {
        $URL = Get-Link -Uri $ReleaseURL -Headers $Headers -MatchProperty href -Pattern $Platform.Pattern
        if ($URL) {
            $Version = ($URL | Get-Version -Pattern 'FileZilla_(\d+\.\d+\.\d+)_.+(exe|zip)')
            New-NevergreenApp -Name 'FileZilla' -Version $Version -Uri $URL -Architecture $Platform.Architecture -Type $Platform.Type
            break
        }

        $SearchCount--
    } until ($SearchCount -eq 0)

    if ($SearchCount -eq 0) {
        Write-Warning "Could not find release for FileZilla $($Platform.Architecture) $($Platform.Language)"
    }

}

LibreOffice returns an error

Get-NevergreenApp -Name LibreOffice
C:\Program Files\WindowsPowerShell\Modules\nevergreen\2208.1\Apps\Get-LibreOffice.ps1 : Get-LibreOffice.ps1: Cannot val
idate argument on parameter 'Uri'. The argument "" does not match the "^(http|https)://" pattern. Supply an argument th
at matches "^(http|https)://" and try the command again.
At C:\Program Files\WindowsPowerShell\Modules\nevergreen\2208.1\Public\Get-NevergreenApp.ps1:61 char:31
+                     $Output = &$Script
+                               ~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-LibreOffice.ps1

C:\Program Files\WindowsPowerShell\Modules\nevergreen\2208.1\Apps\Get-LibreOffice.ps1 : Get-LibreOffice.ps1: Cannot val
idate argument on parameter 'Uri'. The argument "" does not match the "^(http|https)://" pattern. Supply an argument th
at matches "^(http|https)://" and try the command again.
At C:\Program Files\WindowsPowerShell\Modules\nevergreen\2208.1\Public\Get-NevergreenApp.ps1:61 char:31
+                     $Output = &$Script
+                               ~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-LibreOffice.ps1



Name         : LibreOffice
Channel      : Fresh
Language     : Multi
Architecture : x86
Type         : MSI
Version      : 7.4.1
Uri          : https://download.documentfoundation.org/libreoffice/stable/7.4.1/win/x86/LibreOffice_7.4.1_Win_x86.msi

Name         : LibreOffice
Channel      : Still
Language     : Multi
Architecture : x86
Type         : MSI
Version      : 7.3.6
Uri          : https://download.documentfoundation.org/libreoffice/stable/7.3.6/win/x86/LibreOffice_7.3.6_Win_x86.msi

[BUG] LibreOffice

While running the latest version (2311.2) and get details for LibreOffice

Get-NevergreenApp -Name LibreOffice

I recieve an error:

WARNING: No version found within

... HTML Source ...

C:\Program Files\WindowsPowerShell\Modules\nevergreen\2311.2\Apps\Get-LibreOffice.ps1 : Get-LibreOffice.ps1: Cannot
validate argument on parameter 'Version'. The argument is null or empty. Provide an argument that is not null or
empty, and then try the command again.
At C:\Program Files\WindowsPowerShell\Modules\nevergreen\2311.2\Public\Get-NevergreenApp.ps1:61 char:31
+                     $Output = &$Script
+                               ~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-LibreOffice.ps1

C:\Program Files\WindowsPowerShell\Modules\nevergreen\2311.2\Apps\Get-LibreOffice.ps1 : Get-LibreOffice.ps1: Cannot
validate argument on parameter 'Version'. The argument is null or empty. Provide an argument that is not null or
empty, and then try the command again.
At C:\Program Files\WindowsPowerShell\Modules\nevergreen\2311.2\Public\Get-NevergreenApp.ps1:61 char:31
+                     $Output = &$Script
+                               ~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-LibreOffice.ps1

And no results

[New App Request] Scooter Software Beyond Compare

I have written a new NeverGreen script to return the latest versions of Scooter Softwares Beyond Compare for Windows, this is obtained using a webscrape against https://www.scootersoftware.com/download

N.B. The Platform Uris have been obtained from both the Downloads page (for .exe's) and the Alternate Installers page (for .msi & .zip files)
As I introduced the new ReleaseDate attribute in the [Enhancement] Microsoft SSMS New issue, I have made use of it in here too.

Here is my script:

# Get-ScooterBeyondCompare.ps1

$AppName = "Scooter Beyond Compare"
$ReleaseURL = 'https://www.scootersoftware.com/download'
$Version = ((Get-Link -Uri $ReleaseURL -MatchProperty href -Pattern '\.exe$') | Get-Version -Pattern '(\d+\.\d+(\.\d+){0,2})')

#Obtain Release Date and convert to "yyyy-MM-dd" format
try {
	$Content = (Invoke-WebRequest -Uri $ReleaseURL).RawContent
	$SearchString = ", released "
	$CaptureStart = $Content.IndexOf($SearchString) + $SearchString.Length
	$EndIndex = $Content.IndexOf("</span>", $CaptureStart) - $CaptureStart
	$ReleasedOn = $Content.Substring($CaptureStart, $EndIndex).Trim()
}
catch {
	Throw "Failed to connect to ($($ReleaseUrl)) with error $_."
	Break
}
finally {
	# Define a regular expression pattern to match a date in the format "Month. Day, Year"
    $pattern = "\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|January|February|March|April|May|June|July|August|September|October|November|December)\.\s\d{1,2},\s\d{4}\b"

    # Use Select-String to find the date in the text
    $matchesfound = $ReleasedOn | Select-String -Pattern $pattern

    # Extract the matched date
    if ($matchesfound) {
        # Parse the date and reformat it to "YYYY-MM-DD"
        $parsedDate = Get-Date $ReleasedOn
        #Create $LatestVersion variable to create folder structure
        $ReleaseDate = $parsedDate.ToString("yyyy-MM-dd")
        #Write-Verbose "Found Date: $ReleaseDate"
    } else {
        Write-Verbose "Date not found in the text."
		$ReleaseDate = ""
    }
	# Success
}

$Platforms = @(
    @{Architecture = 'x64'; Type = 'Msi'; Platform = 'Windows'; Language = 'English'; Uri = "https://www.scootersoftware.com/files/BCompare-$($Version)_x64.msi"}
    @{Architecture = 'x86'; Type = 'Msi'; Platform = 'Windows'; Language = 'English'; Uri = "https://www.scootersoftware.com/files/BCompare-$($Version)_x86.msi"}
    @{Architecture = 'x64'; Type = 'Zip'; Platform = 'Windows'; Language = 'English'; Uri = "https://www.scootersoftware.com/files/BCompare-$($Version).zip"}
	@{Architecture = 'x64'; Type = 'Exe'; Platform = 'Windows'; Language = 'English'; Uri = "https://www.scootersoftware.com/files/BCompare-$($Version).exe"}
	@{Architecture = 'x64'; Type = 'Exe'; Platform = 'Windows'; Language = 'German'; Uri = "https://www.scootersoftware.com/files/BCompare-de-$($Version).exe"}
	@{Architecture = 'x64'; Type = 'Exe'; Platform = 'Windows'; Language = 'French'; Uri = "https://www.scootersoftware.com/files/BCompare-fr-$($Version).exe"}
	@{Architecture = 'x64'; Type = 'Exe'; Platform = 'Windows'; Language = 'Japanese'; Uri = "https://www.scootersoftware.com/files/BCompare-jp-$($Version).exe"}
	@{Architecture = 'x64'; Type = 'Exe'; Platform = 'Windows'; Language = 'Chinese (Simplified)'; Uri = "https://www.scootersoftware.com/files/BCompare-zh-$($Version).exe"}
)

foreach ($Platform in $Platforms) {

    $SearchCount = 1

	do {
		New-NevergreenApp -Name $($AppName) -Version $($Version) -ReleaseDate $($ReleaseDate) -Language $($Platform.Language) -Uri $($Platform.Uri) -Platform $($Platform.Platform) -Architecture $($Platform.Architecture) -Type $($Platform.Type)
        break

        $SearchCount--
    } until ($SearchCount -eq 0)

    if ($SearchCount -eq 0) {
        Write-Warning "Could not find release for $($AppName) $($Platform.Platform) $($Platform.Architecture)"
    }
}

[New App Request] SysInternals ZoomIt

I have written a new NeverGreen script to return the latest version of (Microsoft) SysInternals ZoomIt, this is obtained using a webscrape against the release page: https://learn.microsoft.com/en-us/sysinternals/downloads/zoomit

N.B. For each release, there is only one (.zip) download containing the x86, x64 and ARM64 executables

Here is my Script:

# Get-SysInternalsZoomIt.ps1

$AppName = "SysInternals ZoomIt"

$Apps = @(
    @{Architecture = 'multi'; Type = 'Zip'; Pattern = 'Download ZoomIt' }
)

$ReleaseURL = 'https://learn.microsoft.com/en-us/sysinternals/downloads/zoomit'
$URL = Get-Link -Uri $ReleaseURL -MatchProperty outerHTML -Pattern $Apps.Pattern
$Version = Get-Version -Uri $ReleaseURL -Pattern 'ZoomIt v(\d+\.\d+)'

New-NevergreenApp -Name $AppName -Version $Version -Uri $URL -Architecture $Apps.Architecture -Type $Apps.Type

Cisco Apps

I would love to see all the Cisco Apps like

Cisco Jabber
Cisco Jabber JVDI
Cisco Webex Meetings
Cisco Webex Virtual Desktop Plug-in
Cisco Teams
Cisco Teams VDI

Could you add this apps?

Request: Microsoft Office Deployment Tool

Could also apply to anything else also on download.microsoft.com

I wish I knew RegEx, hopefully it's not too hard

Version on URL: https://www.microsoft.com/en-us/download/details.aspx?id=49117
i.e.
Version: </div><p>16.0.15629.20208</p>

Download Link on URL: https://www.microsoft.com/en-us/download/confirmation.aspx?id=49117
i.e.
http-equiv="refresh" content="0;url=https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_15629-20208.exe"

[New App Request] Azeus Convene

Here is my NeverGreen script to return the latest versions of Azeus Convene for Windows and MacOS, this is obtained using a webscrape against https://www.azeusconvene.com/downloads

In order for the script to return MacOS versions too, this does require the modification of the New-NevergreenApp.ps1script via an additional 'dmg' file type in the ValidateSet setting within the Type attribute (currently line 83 and then update comment on line 30)
P.S. If this script is to only return the Windows version - Lines 9 and 10 (within the $Platforms splat) could be removed or commented out

N.B. This is quite a niche app request, but thought I'd share my code in case it is useful for anyone else.

# Get-AzeusConvene.ps1

$AppName = "Azeus Convene Desktop"
$ReleaseURL = 'https://www.azeusconvene.com/downloads'
[version]$Version = Get-Version -Uri $ReleaseURL -Pattern '<p>Latest Version: v*?(\d+\.\d+(\.\d+){0,2})'

$Platforms = @(
    @{Architecture = 'x64'; Type = 'Exe'; Platform = 'Windows'; Uri = "https://www.azeusconvene.com/installers/winos/standard/convene_setup.$($Version)-64bit.exe"}
    @{Architecture = 'x64'; Type = 'Dmg'; Platform = 'MacOS (Intel)';  Uri = "https://www.azeusconvene.com/installers/macos/standard/Azeus%20Convene.v$($Version).dmg"}
    @{Architecture = 'ARM64'; Type = 'Dmg'; Platform = 'MacOS (Apple)';  Uri = "https://www.azeusconvene.com/installers/macos/standard/Azeus%20Convene.aarch64.v$($Version).dmg"}
)

foreach ($Platform in $Platforms) {

    $SearchCount = 3

	do {
		[version]$AppVersion = ($Platform.Uri | Get-Version -Pattern 'convene.*?(\d+\.\d+(\.\d+){0,2}).+(exe|dmg)')
		New-NevergreenApp -Name $AppName -Version $AppVersion -Uri $Platform.Uri -Platform $Platform.Platform -Architecture $Platform.Architecture -Type $Platform.Type
        break

        $SearchCount--
    } until ($SearchCount -eq 0)

    if ($SearchCount -eq 0) {
        Write-Warning "Could not find release for $($AppName) $($Platform.Platform) $($Platform.Architecture)"
    }
}

[New App Request] Microsoft OLE DB Driver for SQL Server

New app request to replace the Evergreen version - Evergreen requires the Microsoft fwlink addresses updating in the JSON each time Microsoft release a new version (not really the point of EverGreen), so with NeverGreen we can scrape the webpage and always have the latest version of each "ring" (v18.x & v19.x)
This reads the Release notes for the Microsoft OLE DB Driver for SQL Server, returns all versions, then refines this list to the latest for each ring before creating language specific URLs for each architecture.
Note: ARM64 msi is not available for earlier v18.x builds

N.B. This also makes use of the ReleaseDate Parameter introduced in the [Enhancement] Microsoft SSMS

This is probably the most complex NeverGreen script to date ๐Ÿ˜‰:

# Get-MicrosoftOLEDBDriverforSQLServer.ps1

$AppName = "Microsoft OLE DB Driver for SQL Server"
$ReleaseUrl = "https://learn.microsoft.com/en-us/sql/connect/oledb/release-notes-for-oledb-driver-for-sql-server?view=sql-server-ver16"

$RawContent = (Invoke-WebRequest -Uri $ReleaseUrl).RawContent
Write-Verbose "Obtaining $($AppName) Release Versions..."

$pattern = [regex]::new('<h2 id="\d+">(?<version>[^<]+)</h2>\s*<p>.*?<strong><a href="(?<x64>[^"]+)"[^>]*>Download x64 installer</a></strong><br>.*?<strong><a href="(?<x86>[^"]+)"[^>]*>Download x86 installer</a></strong>(<br>.*?<strong><a href="(?<arm64>[^"]+)"[^>]*>Download Arm64 installer</a></strong>)?</p>\s*<p>Released:\s*(?<date>[^<]+)</p>', [System.Text.RegularExpressions.RegexOptions]::Singleline)
$releases = $pattern.Matches($RawContent)

# Dictionary to store the latest version for each major version
$latestVersions = @{}

# Process matches
foreach ($release in $releases) {
    $ThisVersion = [version]$release.Groups['version'].Value
    $majorVersion = $ThisVersion.Major
    $x64Url = $release.Groups['x64'].Value
    $x86Url = $release.Groups['x86'].Value
    $arm64Url = $release.Groups['arm64'].Value
    $releaseDate = $release.Groups['date'].Value

    # Update the latest version for the major version if needed
    if (-not $latestVersions.ContainsKey($majorVersion) -or $ThisVersion -gt $latestVersions[$majorVersion].Version) {
        $latestVersions[$majorVersion] = @{
            Version = $ThisVersion
            x64Url = $x64Url
            x86Url = $x86Url
            arm64Url = $arm64Url
            ReleaseDate = $releaseDate
        }
    }
}

# Filter to keep only v19.x and v18.x major versions
$majorVersionsToKeep = @(18, 19)

# Process the latest versions
foreach ($majorVersion in $majorVersionsToKeep) {
    if ($latestVersions.ContainsKey($majorVersion)) {
        $latestVersion = $latestVersions[$majorVersion]
        $ThisVersion = $latestVersion.Version
        $x64Url = $latestVersion.x64Url
        $x86Url = $latestVersion.x86Url
        $arm64Url = $latestVersion.arm64Url
        $releaseDate = $latestVersion.ReleaseDate

        $AppVersions = @(
            @{Version = $ThisVersion; Ring = $ThisVersion.Major; Type = 'msi'; Architecture = 'x86'; Uri = $x86Url}
            @{Version = $ThisVersion; Ring = $ThisVersion.Major; Type = 'msi'; Architecture = 'x64'; Uri = $x64Url}
            @{Version = $ThisVersion; Ring = $ThisVersion.Major; Type = 'msi'; Architecture = 'ARM64'; Uri = $arm64Url}
        )

        $AppLanguages = @(
            @{Language = 'Chinese (Simplified)'; Pattern = '&clcid=0x804'}
            @{Language = 'Chinese (Traditional)'; Pattern = '&clcid=0x404'}
            @{Language = 'English'; Pattern = '&clcid=0x409'} # N.B this is 'English  (United States)'
            @{Language = 'French'; Pattern = '&clcid=0x40c'}
            @{Language = 'German'; Pattern = '&clcid=0x407'}
            @{Language = 'Italian'; Pattern = '&clcid=0x410'}
            @{Language = 'Japanese'; Pattern = '&clcid=0x411'}
            @{Language = 'Korean'; Pattern = '&clcid=0x412'}
            @{Language = 'Portuguese (Brazil)'; Pattern = '&clcid=0x416'}
            @{Language = 'Russian'; Pattern = '&clcid=0x419'}
            @{Language = 'Spanish'; Pattern = '&clcid=0x40a'}
        )

        foreach ($AppVersion in $AppVersions) {
            foreach ($AppLanguage in $AppLanguages) {
                $SearchCount = 2 # This may need increasing as future versions are released
                $Version = $AppVersion.Version
                $Uri = $AppVersion.Uri
                if ($NULL -ne $Uri) {
                    do {
                        if ($Uri) {
                            $Uri = (Resolve-Uri -Uri "$($AppVersion.Uri)$($AppLanguage.Pattern)").Uri
                            Write-Verbose "New $($AppLanguage.Language) URI : $Uri"
                            # Build each link with Platform specific versions
                            New-NevergreenApp -Name $AppName -Version $Version -Ring $AppVersion.Ring -Uri $Uri -Architecture $AppVersion.Architecture -Type $AppVersion.Type -Language $AppLanguage.Language -ReleaseDate $releaseDate
                            break
                        }

                        $SearchCount--
                    } until ($SearchCount -eq 0)

                    if ($SearchCount -eq 0) {
                        Write-Warning "Could not find $($AppLanguage.Language) release for $($AppName) $($Version) ($($AppVersion.Architecture))"
                    }
                }
            }
        }
    }
}

Add Druide Antidote patches

It does require an enterprise account to download the main software but at least we could provide the patches for the latest update.

We can improve the following code with the Nevergreen standard.

$appURLVersion = "https://www.antidote.info/en/assistance/mises-a-jour/historique/antidote-10/windows"
$webRequest = Invoke-WebRequest -UseBasicParsing -Uri ($appURLVersion) -SessionVariable websession
$regexAppVersion = "Antidote \d\d v\d.+ Windows"
$webVersion = $webRequest.RawContent | Select-String -Pattern $regexAppVersion -AllMatches | ForEach-Object { $_.Matches.Value } | Select-Object -First 1
$appShortVersion = ($webVersion).Split(" ")[1]
$appPatchVersion = ($webVersion).Trim("Andidote $appShortVersion v").Trim(" Windows").Replace(" ", "")
$appVersion = "$appShortVersion.$appPatchVersion"
$appURLPatch = "https://telechargement12.druide.com/Win/antidote_$appShortVersion/Diff_Antidote_$($appShortVersion)_C_$($appShortVersion).$appPatchVersion.msp"
$appURLPatch2 = "https://telechargement12.druide.com/Win/antidote_$appShortVersion/Diff_Antidote_$($appShortVersion)_Module_F_$($appShortVersion).$appPatchVersion.msp"
$appURLPatch3 = "https://telechargement12.druide.com/Win/antidote_$appShortVersion/Diff_Antidote_$($appShortVersion)_Module_E_$($appShortVersion).$appPatchVersion.msp"
$appURLPatch4 = "https://telechargement12.druide.com/Win/antidote_$appShortVersion/Diff_Connectix_$($appShortVersion)_C_$($appShortVersion).$appPatchVersion.msp"
$appURLMultiMgr = "https://telechargement.druide.com/telecharger/Reseau/antidote_$appShortVersion/GestionnaireMultiposte_Antidote$appShortVersion.exe"
$appPatch = $appURLPatch.Split("/")[5]
$appPatch2 = $appURLPatch2.Split("/")[5]
$appPatch3 = $appURLPatch3.Split("/")[5]
$appPatch4 = $appURLPatch4.Split("/")[5]

[Feature request] Android Platform Tools

Request to add Android Platform Tools to Nevergreen.

PowerShell to get latest version:

[System.Net.WebClient]::new().DownloadString('https://developer.android.com/studio/releases/platform-tools').Split(
    [System.Environment]::NewLine,
    [System.StringSplitOptions]::RemoveEmptyEntries
).ForEach{
    $_.Trim() -replace '\s{2,}', ' '
}.Where{
    $_ -like '<h4 id=*'
}[0].Split('>')[1].Split(' ')[0]

URL to always latest version of the tools:

Module version not playing nicely with #Requires statement

For some reason, most likely a bug in Powershell, if you add this Requires statement to your code:

#Requires -Modules @{ ModuleName='Nevergreen'; ModuleVersion='2105.2' }

It fails with:

ResourceUnavailable: The script 'AutoPackager.ps1' cannot be run because the following modules that are specified by the "#requires" statements of the script are missing: Nevergreen.

Yet it works if you retry!

I suspect this might be down to the version format used. I have copied the version format used by Evergreen, i.e. YYMM.Build, except my first release was 2105.001. However when I published the module it was coming up as 2105.1. Seeing that it stripped the preceeding zeroes, I just called the next release 2105.2 in the module manifest.

Visiting the Powershell Gallery at https://www.powershellgallery.com/packages/Nevergreen though redirects to 2105.1 instead of the latest version, which is odd, and the reason why I suspect the version being a cause.

Microsoft PowerBI getting 404

Microsoft PowerBI Apps appear to be broken:

Get-NevergreenApp -Name MicrosoftPowerBIDesktop
Get-Version : Unable to query URL 'https://www.microsoft.com/download/details.aspx?id=58494': The remote server returned an error: (404) Not Found.

The URL displays the PowerBI Download webpage fine in a browser but PowerShell Invoke-WebRequest on the same URL returns 404.

CCleaner, defragler

To optimize your windows installation, I could recommend Ccleaner and defragler. Please add these to your apps if possible.

[Enhancement] Microsoft SSMS

The current Get-MicrosoftSSMS.ps1 script:

$URL64 = (Resolve-Uri -Uri 'https://aka.ms/ssmsfullsetup').Uri
$Version = Get-Version -Uri 'https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms' -Pattern 'Release number: ((?:\d+\.)+\d+)'
New-NevergreenApp -Name 'Microsoft SSMS' -Version $Version -Uri $URL64 -Architecture 'x64' -Type 'Exe'

only returns the latest new full version in 'English (United States)' language, but does not return any earlier versions.
Earlier versions are sometimes still required as Microsoft may still update earlier versions to fix security issues.
Earlier versions are required to work with specific components of certain SQL server releases (SSIS for example requires v18.x)

Therefore I have re-written the Get-MicrosoftSSMS.ps1 script to webscrape the release notes page, to return all current released versions.

# Get-SSMS.ps1

# Define AppName
$AppName = "Microsoft SQL Server Management Studio"

# Main script to fetch and process links
$ReleaseURL = "https://learn.microsoft.com/en-us/sql/ssms/release-notes-ssms?view=sql-server-ver16"  # Replace with the URL of the web page you want to process

Write-Verbose "Obtaining $($AppName) Release Versions...`n=============================================================================`n"
# Fetch the HTML content of the webpage
$htmlContent = Invoke-WebRequest -Uri $ReleaseUrl

# Define the RegEx pattern to match the links and capture the version number and BaseURI
$pattern = '<a[^>]*href="([^"]*)"[^>]*>\s*Download SSMS ([\d.]+)\s*</a>'

$SearchCount = ([regex]::Matches($htmlContent.RawContent, $pattern)).Count

Write-Verbose "$($AppName) Release Versions found: $($SearchCount)`n-------------------------------------------------------------------------`n"

do {
	# Use RegEx to find matches
	foreach ($patternmatch in [regex]::Matches($htmlContent.Content, $pattern)) {
		# Extract the URI and version number
		$ThisVersionUri = $patternmatch.Groups[1].Value
		[version]$ThisVersion = $patternmatch.Groups[2].Value
		$BaseVersion = $($ThisVersion.Major)

		# Regular expression to match the release information
		$regex = "<li>Release number: $($ThisVersion)</li>`n<li>Build number: (.*?)</li>`n<li>Release date: (.*?)</li>"
		
		$BuildCount = ([regex]::Matches($htmlContent.RawContent, $regex)).Count
		foreach ($regexmatch in [regex]::Matches($htmlContent.RawContent, $regex)) {
			#$ReleaseVersion = $regexmatch.Groups[1].Value
			[version]$BuildNumber = $regexmatch.Groups[1].Value
			$ReleaseDate = $regexmatch.Groups[2].Value

			do {
				$AppVersions = @(
					@{Version = $ThisVersion; BuildNumber = $BuildNumber; ReleaseDate = $ReleaseDate; Language = 'Chinese (Simplified)'; Pattern = '&clcid=0x804'}
					@{Version = $ThisVersion; BuildNumber = $BuildNumber; ReleaseDate = $ReleaseDate; Language = 'Chinese (Traditional)'; Pattern = '&clcid=0x404'}
					@{Version = $ThisVersion; BuildNumber = $BuildNumber; ReleaseDate = $ReleaseDate; Language = 'English'; Pattern = '&clcid=0x409'}
					@{Version = $ThisVersion; BuildNumber = $BuildNumber; ReleaseDate = $ReleaseDate; Language = 'French'; Pattern = '&clcid=0x40c'}
					@{Version = $ThisVersion; BuildNumber = $BuildNumber; ReleaseDate = $ReleaseDate; Language = 'German'; Pattern = '&clcid=0x407'}
					@{Version = $ThisVersion; BuildNumber = $BuildNumber; ReleaseDate = $ReleaseDate; Language = 'Italian'; Pattern = '&clcid=0x410'}
					@{Version = $ThisVersion; BuildNumber = $BuildNumber; ReleaseDate = $ReleaseDate; Language = 'Japanese'; Pattern = '&clcid=0x411'}
					@{Version = $ThisVersion; BuildNumber = $BuildNumber; ReleaseDate = $ReleaseDate; Language = 'Korean'; Pattern = '&clcid=0x412'}
					@{Version = $ThisVersion; BuildNumber = $BuildNumber; ReleaseDate = $ReleaseDate; Language = 'Portuguese (Brazil)'; Pattern = '&clcid=0x416'}
					@{Version = $ThisVersion; BuildNumber = $BuildNumber; ReleaseDate = $ReleaseDate; Language = 'Russian'; Pattern = '&clcid=0x419'}
					@{Version = $ThisVersion; BuildNumber = $BuildNumber; ReleaseDate = $ReleaseDate; Language = 'Spanish'; Pattern = '&clcid=0x40a'}
				)

				foreach ($AppVersion in $AppVersions) {
					if ($ThisVersionUri) {
						#Build each link with Language specific versions
						$URL = (Resolve-Uri -Uri "$($ThisVersionUri)$($AppVersion.Pattern)").Uri
						New-NevergreenApp -Name $AppName -Ring $BaseVersion -Version $AppVersion.Version -BuildNumber $AppVersion.BuildNumber -ReleaseDate $AppVersion.ReleaseDate -Uri $URL -Architecture 'x64' -Language $AppVersion.Language -Type 'Exe'
						#break
					}
				}
				$BuildCount--
			} until ($BuildCount -eq 0)
		}
		$SearchCount--
	}
} until ($SearchCount -eq 0)

This modified script has also required the modification of the New-NeverGreenApp.ps1 script to specifically handle the BuildNumber and ReleaseDate parameters (To give similar functionality as Evergreen), so here is my updated version:

function New-NevergreenApp {
    <#
    .SYNOPSIS
        Returns a PSCustomObject to output.

    .DESCRIPTION
        Returns a PSCustomObject to output.

    .NOTES
        Site: https://packageology.com
        Author: Dan Gough
        Twitter: @packageologist

    .LINK
        https://github.com/DanGough/Nevergreen

    .PARAMETER Name
        Mandatory. The name of the application.

    .PARAMETER Uri
        Mandatory. The download URI for the application.

    .PARAMETER Version
        Mandatory. The application version.

    .PARAMETER Architecture
        Mandatory. Must match x86, x64, ARM32, ARM64 or Multi.

    .PARAMETER Type
        Mandatory. Must match Msi, Msp, Exe, Zip, Msix, AppX, AppV, 7z if supplied.

    .PARAMETER Language
        Optional. The language of the application installer, e.g. 'en'.

    .PARAMETER Ring
        Optional. The deployment ring, e.g. 'General', 'Preview'.

    .PARAMETER Channel
        Optional. The channel, e.g. 'Enterprise'.

    .PARAMETER Platform
        Optional. The platform, e.g. 'Windows Server'.

    .PARAMETER BuildNumber
        Optional. The Build Version (used where available - example SSMS).

    .PARAMETER ReleaseDate
        Optional. The Date the version was released.

    .PARAMETER MD5
        Optional. The MD5 hash of the file.

    .PARAMETER SHA256
        Optional. The SHA256 hash of the file.

    .EXAMPLE
        New-NevergreenApp -Uri 'http://somewhere.com/something.exe' -Version '1.0' -Architecture 'x64' -Type 'Exe'

        Description:
        Outputs a PSCustomObject with the chosen properties.
    #>
    [CmdletBinding(SupportsShouldProcess = $False)]
    param (
        [Parameter(
            Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String] $Name,
        [Parameter(
            Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String] $Version,
        [Parameter(
            Mandatory = $true)]
        [ValidatePattern('^(http|https)://')]
        [Alias('Url')]
        [String] $Uri,
        [Parameter(
            Mandatory = $true)]
        [ValidateSet('x86', 'x64', 'ARM32', 'ARM64', 'Multi')]
        [String] $Architecture,
        [Parameter(
            Mandatory = $true)]
        [ValidateSet('Msi', 'Msp', 'Exe', 'Zip', 'Msix', 'AppX', 'AppV', '7z')]
        [String] $Type,
        [Parameter(
            Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String] $Language,
        [Parameter(
            Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String] $Ring,
        [Parameter(
            Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String] $Channel,
        [Parameter(
            Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String] $Platform,
        [Parameter(
            Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String] $BuildNumber,
        [Parameter(
            Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String] $ReleaseDate,
        [Parameter(
            Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String] $MD5,
        [Parameter(
            Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String] $SHA256
    )

    $Output = [PSCustomObject]@{
        Name    = $Name
    }

    if ($Ring) {
        Add-Member -InputObject $Output -MemberType NoteProperty -Name 'Ring' -Value $Ring
    }

    if ($Channel) {
        Add-Member -InputObject $Output -MemberType NoteProperty -Name 'Channel' -Value $Channel
    }

    if ($Language) {
        Add-Member -InputObject $Output -MemberType NoteProperty -Name 'Language' -Value $Language
    }

    if ($BuildNumber) {
        Add-Member -InputObject $Output -MemberType NoteProperty -Name 'BuildNumber' -Value $BuildNumber
    }

    if ($ReleaseDate) {
        Add-Member -InputObject $Output -MemberType NoteProperty -Name 'ReleaseDate' -Value $ReleaseDate
    }

    if ($Platform) {
        Add-Member -InputObject $Output -MemberType NoteProperty -Name 'Platform' -Value $Platform
    }

    if ($Architecture) {
        Add-Member -InputObject $Output -MemberType NoteProperty -Name 'Architecture' -Value $Architecture
    }

    if ($Type) {
        Add-Member -InputObject $Output -MemberType NoteProperty -Name 'Type' -Value $Type
    }

    Add-Member -InputObject $Output -MemberType NoteProperty -Name 'Version' -Value $Version
    Add-Member -InputObject $Output -MemberType NoteProperty -Name 'Uri' -Value $Uri

    if ($MD5) {
        Add-Member -InputObject $Output -MemberType NoteProperty -Name 'MD5' -Value $MD5
    }

    if ($SHA256) {
        Add-Member -InputObject $Output -MemberType NoteProperty -Name 'SHA256' -Value $SHA256
    }

    $Output
}

Add built-in resolution of URLs

Add a function inside Get-NevergreenApp to automatically resolve the URL provided by each application script, for example to turn:

https://aka.ms/installazurecliwindows

Into:

https://azcliprod.blob.core.windows.net/msi/azure-cli-2.23.0.msi

I could a;so resolve the filename portion of the URL, and the modified date of the file and output that as an extra field.

This is not straightforward:

  • Some URLs do not resolve correctly with some user agents
  • Some URLs like Github releases and Oracle Java downloads end in what looks like a valid filename, until you resolve the redirects you end up with a query string. You then have to parse the Content-Disposition header to retrieve the filename.
  • When querying the header with Invoke-WebRequest -Method HEAD, some URLs refuse to respond, so fallback methods required.

I have old scripts that do this already, they just need polishing and integration.

[Bug] Zoom VDI download link is now forbidden

Get-NevergreenApp Zoom now returns the following error

Get-Link : Get-Link: The remote server returned an error: (403) Forbidden.
At C:\Users\jonathan\Documents\WindowsPowerShell\Modules\Nevergreen\2110.1\Apps\Get-zoom.ps1:29 char:23
+ ... wnloadURL = Get-Link -Uri 'https://support.zoom.us/hc/en-us/sections/ ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-Link
 
WARNING: Unable to get results for Zoom VDI downloads: Cannot validate argument on parameter 'Uri'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

The VDI download url is still valid trough a web browser but cannot be reached with Invoke-WebRequest for some reason.

Invoke-WebRequest -Uri "https://support.zoom.us/hc/en-us/sections/360011509631-VDI-Downloads"
Invoke-WebRequest : The remote server returned an error: (403) Forbidden.
At line:1 char:1
+ Invoke-WebRequest -Uri "https://support.zoom.us/hc/en-us/sections/360 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.