From eece8b58c8200dbfca5dff5755671ee2905ba23c Mon Sep 17 00:00:00 2001 From: coredotbin Date: Fri, 2 Jan 2026 13:29:53 -0500 Subject: [PATCH] Refactor uninstall scripts --- windows/Install-ActivTrak.ps1 | 76 +++++++++++++ windows/Install-IPerf3.ps1 | 133 ++++++++++++++++++---- windows/Install-IPerf3ServerService.ps1 | 17 --- windows/Install-WinAcme.ps1 | 82 ++++++++----- windows/Uninstall-IPerf3.ps1 | 41 +++++++ windows/Uninstall-IPerf3ServerService.ps1 | 19 +++- 6 files changed, 292 insertions(+), 76 deletions(-) create mode 100644 windows/Install-ActivTrak.ps1 delete mode 100644 windows/Install-IPerf3ServerService.ps1 create mode 100644 windows/Uninstall-IPerf3.ps1 diff --git a/windows/Install-ActivTrak.ps1 b/windows/Install-ActivTrak.ps1 new file mode 100644 index 0000000..bfddb13 --- /dev/null +++ b/windows/Install-ActivTrak.ps1 @@ -0,0 +1,76 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory=$true)] + [String] + $InstallerUrl +) + +<# +.SYNOPSIS + Silently installs the ActivTrak agent. +.DESCRIPTION + This script silently downloads and installs the ActivTrak agent from a given URL. + Installer URLs expire after 72 hours. Generate a new installer URL using the instructions on this page: + https://support.activtrak.com/hc/en-us/articles/360052228952-Deploy-Via-PowerShell-Script +.PARAMETER InstallerUrl + The URL from which to download the ActivTrak installer +.LINK + https://support.activtrak.com/hc/en-us/articles/360052228952-Deploy-Via-PowerShell-Script +#> +process { + # Download + + Write-Host "Downloading application..." + ## Create a WebRequest to read only headers + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12 + $Request = [System.Net.HttpWebRequest]::Create($InstallerUrl) + $Request.Method = "HEAD" + + try { + $Response = $Request.GetResponse() + $ContentDisposition = $Response.Headers["Content-Disposition"] + $Response.Close() + } catch { + throw "Failed to retrieve response headers. $_" + } + + if ($ContentDisposition) { + $InstallerName = [System.Net.WebUtility]::UrlDecode(($ContentDisposition -replace '.*filename=([^;]+).*', '$1')) + $InstallerPath = Join-Path -Path $env:TEMP -ChildPath $InstallerName + + ## Download file to the full path + try { + # Invoke-WebRequest -Uri $InstallerUrl -OutFile $InstallerPath + + # Use Legacy WebClient for compatibility + (New-Object Net.WebClient).DownloadFile($InstallerUrl, $InstallerPath) + } catch { + throw "Download failed. $_" + } + + # Install + try { + Write-Host "Installing application..." + $ExitCode = (Start-Process -FilePath "msiexec.exe" -ArgumentList "/i `"$($InstallerPath)`" /qn /l*v `"$($InstallerPath).log`"" -Wait -PassThru).ExitCode + } catch { + throw "Failed installing application. $_" + } + } else { + Write-Host "Content-Disposition header not found. Please contact ActivTrak Support at Support@ActivTrak.com if problem persists." + } +} + +end { + # Clean up + + Write-Host "Removing package download from '$InstallerPath'" + Remove-Item -Path $InstallerPath -Force + + switch ($ExitCode) { + 0 { Write-Host "Installation succeeded."; break } + 3010 { Write-Host "A reboot is required to complete installation."; break } + default { + Write-Error "Installation failed with exit code $ExitCode. For help see https://learn.microsoft.com/en-us/windows/win32/msi/error-codes" + } + } +} \ No newline at end of file diff --git a/windows/Install-IPerf3.ps1 b/windows/Install-IPerf3.ps1 index 9a7ee98..9a7252f 100644 --- a/windows/Install-IPerf3.ps1 +++ b/windows/Install-IPerf3.ps1 @@ -1,40 +1,123 @@ -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12 +[CmdletBinding()] +param ( + [Parameter()] + [String] + $DestinationPath = 'C:\Program Files\iperf3', + [Parameter()] + [Switch] + $ServerService +) -$PackagesPath = 'C:\Packages' -$DestinationPath = 'C:\Program Files\iperf3' +<# +.SYNOPSIS + Install the latest version of iPerf3 +.DESCRIPTION + Download and install the latest windows build of iPerf3 with the server service. + Requires NSSM to install the server service. +.PARAMETER DestinationPath + Specifies the path into which iPerf3 is installed (Default: 'C:\Program Files\iperf3') +.PARAMETER ServerService + Specifies whether the server service should be installed +#> -$InstallerUrl = 'https://github.com/ar51an/iperf3-win-builds/releases/download/3.17.1/iperf-3.17.1-win64.zip' +begin { + $Releases = (Invoke-WebRequest 'https://api.github.com/repos/ar51an/iperf3-win-builds/releases').Content | ConvertFrom-Json | Where-Object { $_.prerelease -eq $false -and $_.draft -eq $false } + $ReleaseTag = ($Releases | Select-Object -First 1).tag_name + + $InstallerUrl = "https://github.com/ar51an/iperf3-win-builds/releases/download/$ReleaseTag/iperf-$ReleaseTag-win64.zip" + # $Asset = ($Releases | Select-Object -First 1).Assets | Where-Object { $_.name -match "(iperf-(?:\d\.?)+-win64\.zip)" } + # $InstallerUrl = $Asset.url -$ArchivePath = Join-Path -Path $PackagesPath -ChildPath ($InstallerUrl | Select-String -Pattern "(iperf-(?:\d\.?)+-win64\.zip)").Matches.Value + $ArchivePath = Join-Path -Path $env:TEMP -ChildPath ($InstallerUrl | Select-String -Pattern "(iperf-(?:\d\.?)+-win64\.zip)").Matches.Value + # $ArchivePath = Join-Path -Path $env:TEMP -ChildPath $Asset.name -# Exit if the application is already installed -if (Test-Path $DestinationPath) { Write-Host 'iPerf3 is already installed.'; exit } + $ExecutablePath = Join-Path -Path $DestinationPath -ChildPath 'iperf3.exe' + + # Install iPerf3 executable if it is not already installed + if (Test-Path $ExecutablePath) { $iPerf3Installed = $true; Write-Host 'iPerf3 already installed.' } -# Prep + if ($ServerService) { + $Service = Get-Service -Name iperf3server -ErrorAction SilentlyContinue + if ($null -ne $Service) { + $ServerServiceInstalled = $true + Write-Host 'Server service already installed.' + } else { + if (-not (Test-Path 'C:\Program Files\nssm') ) { + # if ('nssm' -notin $env:PATH) { + throw 'NSSM is not installed. Please install NSSM before attempting to install the server service.' + } + } + } -# Create the $PackagesPath directory if it doesn't already exist -if (-not (Test-Path -PathType Container $PackagesPath)) { New-Item -ItemType Directory -Path $PackagesPath | Out-Null } + if ($iPerf3Installed -and $ServerServiceInstalled) { Write-Host 'Nothing to do.'; exit 0 } +} -# Download +process { + if (-not $iPerf3Installed) { + Write-Host "Installing iPerf3..." + + # Prep + + # Create the logs directory if it doesn't already exist + if (-not (Test-Path -PathType Container (Join-Path -Path $DestinationPath -ChildPath 'logs'))) { New-Item -ItemType Directory -Path (Join-Path -Path $DestinationPath -ChildPath 'logs') | Out-Null } -Write-Host "Downloading application..." -# Use Legacy WebClient for compatibility -(New-Object Net.WebClient).DownloadFile($InstallerUrl, $ArchivePath) + # Download + try { + Write-Host "Downloading application..." -# Extract + $ProgressPreference = 'SilentlyContinue' + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12 + # Use Legacy WebClient for compatibility + (New-Object Net.WebClient).DownloadFile($InstallerUrl, $ArchivePath) + } catch { + throw "Failed downloading application. $_" + } -Write-Host "Extracting application..." -Expand-Archive -Path $ArchivePath -DestinationPath $DestinationPath -Force -Write-Host "Application extracted to $DestinationPath" + # Install + try { + Write-Host "Installing application..." -# Install + Expand-Archive -Path $ArchivePath -DestinationPath $DestinationPath -Force -Write-Host "Installing application..." + # Add the DestinationPath to Path system environment variable + if ($DestinationPath -notin $env:PATH) { [Environment]::SetEnvironmentVariable("Path", $env:Path + ";$DestinationPath\", [System.EnvironmentVariableTarget]::Machine) } -# Add the DestinationPath to Path system environment variable -[Environment]::SetEnvironmentVariable("Path", $env:Path + ";$DestinationPath\", [System.EnvironmentVariableTarget]::Machine) + # Add firewall rule allowing application executable + if ('Allow iPerf3' -notin (Get-NetFirewallRule).DisplayName) { New-NetFirewallRule -DisplayName 'Allow iPerf3' -Direction Inbound -Program $ExecutablePath -RemoteAddress Any -Profile Any -Action Allow } + } catch { + Write-Error "Failed to install application. $_" + } + } -# Clean up + if ($ServerService -and -not $ServerServiceInstalled) { + try { + Write-Host "Installing server service..." -Write-Host "Removing package download from '$ArchivePath'" -Remove-Item -Path $ArchivePath -Force \ No newline at end of file + # Install the iperf3server service + if ((Get-CimInstance Win32_OperatingSystem).OSArchitecture) { + $NssmExecutable = 'C:\Program Files\nssm\win64\nssm.exe' + } else { + $NssmExecutable = 'C:\Program Files\nssm\win32\nssm.exe' + } + & "$NssmExecutable" install iperf3server "$ExecutablePath" "--server --port 5201 --format m --verbose" + & "$NssmExecutable" set iperf3server DisplayName "iPerf3 Server" | Out-Null + & "$NssmExecutable" set iperf3server Description "iPerf3 is a tool for active measurements of the maximum achievable bandwidth on IP networks." | Out-Null + & "$NssmExecutable" set iperf3server AppStdout "$(Join-Path -Path $DestinationPath -ChildPath 'logs\service.log')" | Out-Null + & "$NssmExecutable" set iperf3server AppStderr "$(Join-Path -Path $DestinationPath -ChildPath 'logs\service.log')" | Out-Null + + Write-Host "Starting service..." + Start-Service -Name iperf3server + } catch { + Write-Error "Failed to install server service. $_" + } + } +} + +end { + # Clean up + + if (-not (Test-Path -Path $ArchivePath)) { + Write-Host "Removing iPerf package download from '$ArchivePath'" + Remove-Item -Path $ArchivePath -Force + } +} \ No newline at end of file diff --git a/windows/Install-IPerf3ServerService.ps1 b/windows/Install-IPerf3ServerService.ps1 deleted file mode 100644 index 5f3ca9e..0000000 --- a/windows/Install-IPerf3ServerService.ps1 +++ /dev/null @@ -1,17 +0,0 @@ -# Create the logs directory if it doesn't already exist -if (-not (Test-Path -PathType Container 'C:\Program Files\iperf3\logs')) { New-Item -ItemType Directory -Path 'C:\Program Files\iperf3\logs' | Out-Null } - -$Service = Get-Service -Name iperf3server -ErrorAction SilentlyContinue - -if ($null -eq $Service) { - & "C:\Program Files\nssm\win64\nssm.exe" install iperf3server "C:\Program Files\iperf3\iperf3.exe" "--server --port 5201 --format m --verbose" - & "C:\Program Files\nssm\win64\nssm.exe" set iperf3server DisplayName "iPerf3 Server" | Out-Null - & "C:\Program Files\nssm\win64\nssm.exe" set iperf3server Description "iPerf3 is a tool for active measurements of the maximum achievable bandwidth on IP networks." | Out-Null - & "C:\Program Files\nssm\win64\nssm.exe" set iperf3server AppStdout "C:\Program Files\iperf3\logs\service.log" | Out-Null - & "C:\Program Files\nssm\win64\nssm.exe" set iperf3server AppStderr "C:\Program Files\iperf3\logs\service.log" | Out-Null - - Write-Host "Starting service..." - Start-Service -Name iperf3server -} else { - Write-Host "Service is already installed." -} \ No newline at end of file diff --git a/windows/Install-WinAcme.ps1 b/windows/Install-WinAcme.ps1 index f0ad303..4932d96 100644 --- a/windows/Install-WinAcme.ps1 +++ b/windows/Install-WinAcme.ps1 @@ -1,40 +1,66 @@ -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12 +[CmdletBinding()] +param ( + [Parameter()] + [String] + $DestinationPath = 'C:\Program Files\win-acme' +) -$PackagesPath = 'C:\Packages' -$DestinationPath = 'C:\Program Files\win-acme' +<# +.SYNOPSIS + Install win-acme +.DESCRIPTION + This script downloads and installs the latest version of win-acme. +.PARAMETER DestinationPath + Specifies the path into which win-acme is installed +.LINK + https://www.win-acme.com/ +#> -$InstallerUrl = 'https://github.com/win-acme/win-acme/releases/download/v2.2.9.1701/win-acme.v2.2.9.1701.x64.pluggable.zip' +begin { + # Prep + $Releases = (Invoke-WebRequest 'https://api.github.com/repos/win-acme/win-acme/releases').Content | ConvertFrom-Json | Where-Object { $_.prerelease -eq $false -and $_.draft -eq $false } + $ReleaseTag = ($Releases | Select-Object -First 1).tag_name -$ArchivePath = Join-Path -Path $PackagesPath -ChildPath ($InstallerUrl | Select-String -Pattern "(win-acme\.v?(?:\d\.?)+\.x64\.pluggable\.zip)").Matches.Value + # $InstallerUrl = 'https://github.com/win-acme/win-acme/releases/download/v2.2.9.1701/win-acme.v2.2.9.1701.x64.pluggable.zip' + $InstallerUrl = "https://github.com/win-acme/win-acme/releases/download/$ReleaseTag/win-acme.$ReleaseTag.x64.pluggable.zip" + $ArchivePath = Join-Path -Path $env:TEMP -ChildPath ($InstallerUrl | Select-String -Pattern "(win-acme\.v?(?:\d\.?)+\.x64\.pluggable\.zip)").Matches.Value -# Exit if the application is already installed -if (Test-Path $DestinationPath) { Write-Host 'win-acme is already installed.'; exit } + # Exit if the application is already installed + if (Test-Path $DestinationPath) { Write-Host 'win-acme is already installed.'; exit } +} -# Prep +process { + # Download -# Create the $PackagesPath directory if it doesn't already exist -if (-not (Test-Path -PathType Container $PackagesPath)) { New-Item -ItemType Directory -Path $PackagesPath | Out-Null } + try { + Write-Host "Downloading application..." -# Download + # Use Legacy WebClient for compatibility + $ProgressPreference = 'SilentlyContinue' + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12 + (New-Object Net.WebClient).DownloadFile($InstallerUrl, $ArchivePath) + } catch { + throw "Failed downloading application. $_" + } -Write-Host "Downloading application..." -# Use Legacy WebClient for compatibility -(New-Object Net.WebClient).DownloadFile($InstallerUrl, $ArchivePath) + # Install + try { + Write-Host "Installing application..." -# Extract + Expand-Archive -Path $ArchivePath -DestinationPath $DestinationPath -Force -Write-Host "Extracting application..." -Expand-Archive -Path $ArchivePath -DestinationPath $DestinationPath -Force -Write-Host "Application extracted to $DestinationPath" + # Add the DestinationPath to Path system environment variable + if ($DestinationPath -notin $env:PATH) { [Environment]::SetEnvironmentVariable("Path", $env:Path + ";$DestinationPath\", [System.EnvironmentVariableTarget]::Machine) } + } catch { + throw "Failed installing application. $_" + } +} -# Install +end { + # Clean up -Write-Host "Installing application..." - -# Add the DestinationPath to Path system environment variable -[Environment]::SetEnvironmentVariable("Path", $env:Path + ";$DestinationPath\", [System.EnvironmentVariableTarget]::Machine) - -# Clean up - -Write-Host "Removing package download from '$ArchivePath'" -Remove-Item -Path $ArchivePath -Force \ No newline at end of file + if (-not (Test-Path -Path $ArchivePath)) { + Write-Host "Removing package download from '$ArchivePath'" + Remove-Item -Path $ArchivePath -Force + } +} \ No newline at end of file diff --git a/windows/Uninstall-IPerf3.ps1 b/windows/Uninstall-IPerf3.ps1 new file mode 100644 index 0000000..f2c0859 --- /dev/null +++ b/windows/Uninstall-IPerf3.ps1 @@ -0,0 +1,41 @@ +begin { + function Uninstall-IPerf3 { + [CmdletBinding()] + param ( + [Parameter()] + [String] + $DestinationPath = 'C:\Program Files\iperf3' + ) + + begin { + $Service = Get-Service -Name iperf3server -ErrorAction SilentlyContinue + } + + process { + if ($null -eq $Service) { + Write-Host "Service is not installed" + } else { + try { + & "C:\Program Files\nssm\win64\nssm.exe" remove iperf3server confirm + } catch { + Write-Error "Failed to uninstall service. $_" + } + } + + # Remove Program Files folder + Remove-Item -Path $DestinationPath -Recurse -Force + + # Remove from PATH + $RegexPath = $DestinationPath -replace '\\', '\\' + [Environment]::SetEnvironmentVariable("Path", ($env:Path -replace ";$RegexPath\\",''), [System.EnvironmentVariableTarget]::Machine) + } + } +} + +process { + if (-not (Test-Path (Join-Path -Path $DestinationPath -ChildPath 'iperf3.exe'))) { + Write-Host 'iPerf3 is not installed.' + } else { + Uninstall-IPerf3 + } +} \ No newline at end of file diff --git a/windows/Uninstall-IPerf3ServerService.ps1 b/windows/Uninstall-IPerf3ServerService.ps1 index d4939a1..c471866 100644 --- a/windows/Uninstall-IPerf3ServerService.ps1 +++ b/windows/Uninstall-IPerf3ServerService.ps1 @@ -1,8 +1,15 @@ -$Service = Get-Service -Name iperf3server -ErrorAction SilentlyContinue +begin { + $Service = Get-Service -Name iperf3server -ErrorAction SilentlyContinue +} -if ($null -eq $Service) { - Write-Host "Service is not installed" -} else { - & "C:\Program Files\nssm\win64\nssm.exe" stop iperf3server - & "C:\Program Files\nssm\win64\nssm.exe" remove iperf3server +process { + if ($null -eq $Service) { + Write-Host "Service is not installed" + } else { + try { + & "C:\Program Files\nssm\win64\nssm.exe" remove iperf3server confirm + } catch { + Write-Error "Failed to uninstall service. $_" + } + } } \ No newline at end of file