Skip to content

Instantly share code, notes, and snippets.

Last active March 20, 2023 19:17
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
A skeleton of a PowerShell Script that install the lates tools on windows
$ErrorActionPreference = 'Stop'
$cachedir = '.\cache'
function New-TemporaryDirectory {
$parent = [System.IO.Path]::GetTempPath()
[string] $name = [System.Guid]::NewGuid()
$item = New-Item -ItemType Directory -Path (Join-Path $parent $name)
Write-Verbose "Created temporary directory $item"
return $item
function Get-IfMissing {
# Check if the file already exists
if (-not (Test-Path $Path)) {
# Download the file
Write-Verbose "Downloading $Path from $Url"
Invoke-WebRequest -Uri $Url -OutFile $Path
function Get-FirstPattern {
$files = Get-ChildItem -Path $Path | Where-Object { $_.Name -match $Pattern}
if (($files | Measure-Object).Count -gt 0) {
Write-Verbose "At least one file matching the pattern '$Pattern' exists"
return $files[0]
else {
Write-Verbose "No files matching the pattern '$Pattern' exist"
return $null
function Get-GithubLatest {
Write-Verbose "Download $Pattern from $Owner/$Repo if not cached"
# to avoid hitting the github api rate limit, check if we already have a file matching
$first = Get-FirstPattern -Path $cachedir -Pattern $Pattern
# we didn't so go ahead and download
if ($null -eq $first) {
$uri = "$owner/$repo/releases/latest"
$response = Invoke-RestMethod -Uri $uri
$asset = $response.assets | Where-Object { $ -match $Pattern }
if (($null -eq $asset) -or ($ -eq "")) {
Write-Host $response.assets
$msg = "No such asset found: $($Pattern)"
throw $msg
$tofile = Join-Path $cachedir $
Get-IfMissing $asset.browser_download_url $tofile
return $tofile
# we did, return the first file found
Write-Verbose "Skipping download of $Owner/$Repo"
return Join-Path $cachedir $first
function Expand-File {
$tmpdir = New-TemporaryDirectory
Write-Verbose "Extracting $Path to $tmpdir"
Expand-Archive -Path $Path -DestinationPath $tmpdir
$foundFiles = Get-ChildItem -Path $tmpdir -Recurse | Where-Object { $_.Name -match $Pattern}
if ($foundFiles) {
# Do something with the found files
foreach ($file in $foundFiles) {
Write-Verbose "Found file: $($file.FullName)"
$tofile = Join-Path $Destination $file.Name
Copy-Item -Path $file.FullName -Destination $toFile
} else {
Write-Host "$Pattern was not found in $Path"
# Get-ChildItem -Path $tmpDir -Recurse | Where-Object { !$_.PSIsContainer } | Select-Object FullName | Format-List -Property *
Write-Verbose "Removing $tmpdir"
Remove-Item -LiteralPath $tmpdir -Force -Recurse
if (-not (Test-Path -Path $Destination -PathType Container )) {
Write-Verbose "Creating $Destination"
New-Item -ItemType Directory -Path $Destination
if (-not (Test-Path -Path $cachedir -PathType Container )) {
Write-Verbose "Creating $cachedir"
New-Item -ItemType Directory -Path $cachedir
Write-Verbose "Getting nats"
$cliArchive = Get-GithubLatest -Owner nats-io -Repo natscli -Pattern 'nats-[v0-9\.].*-windows-amd64\.zip$'
Expand-File -Path $cliArchive -Pattern '\.exe$' -Destination $Destination
if ($WIthNsc) {
Write-Verbose "Getting nsc"
$nscArchive = Get-GithubLatest -Owner nats-io -Repo nsc -Pattern 'nsc.*windows-amd64\.zip$'
Expand-File -Path $nscArchive -Pattern '\.exe$' -Destination $Destination
if ($WithServer) {
Write-Verbose "Getting nats-server"
$zipfile = Get-GithubLatest -Owner nats-io -Repo nats-server -Pattern 'nats-server.*windows-amd64\.zip$'
Expand-File -Path $zipfile -Pattern '\.exe$' -Destination $Destination
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment