-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathStart-ScriptAutoUpdater.ps1
More file actions
233 lines (218 loc) · 12.8 KB
/
Start-ScriptAutoUpdater.ps1
File metadata and controls
233 lines (218 loc) · 12.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
function Invoke-AutoUpdater {
[CmdletBinding()]
param(
# The GitHub API URL to fetch the latest release information
[string]$RepoURL = 'https://api.github.com/repos/microsoft/MicrosoftSupportLogs/releases/latest',
# The name of the script file to update
[string]$ScriptName = 'Generate-Microsoft-Support-Logs*.ps1',
# The pattern to match the asset in the release assets
[string]$AssetPattern = 'Generate-Microsoft-Support-Logs.zip*'
)
BEGIN {
# Function to generate a timestamp for log messages
Function Invoke-TimeStamp {
$TimeStamp = Get-Date -Format "MM/dd/yyyy hh:mm:ss tt"
return "$TimeStamp - "
}
# Function to write messages to the console with optional color and newline control
function Write-Console {
param (
[Parameter(Position = 1)]
[string]$Text, # The text to output
[Parameter(Position = 2)]
$ForegroundColor, # The color of the text
[Parameter(Position = 3)]
[switch]$NoNewLine # Switch to suppress the newline
)
# Check if the environment is interactive (e.g., PowerShell console)
if ([Environment]::UserInteractive) {
# If a foreground color is specified, use it
if ($ForegroundColor) {
Write-Host $Text -ForegroundColor $ForegroundColor -NoNewLine:$NoNewLine
} else {
Write-Host $Text -NoNewLine:$NoNewLine
}
} else {
# If not interactive (e.g., running as a script), output plain text
Write-Output $Text
}
}
# Function to display version status messages with customizable colors
Function Show-VersionStatus {
param (
[string]$Status, # The status title (e.g., "UP TO DATE")
[string]$Message, # The message content
[ConsoleColor]$HeaderColor = 'White', # Color for the header and borders
[ConsoleColor]$ContentColor = 'White' # Color for the message content
)
Write-Host
$lineLength = 60 # Length of the border lines
$border = "=" * $lineLength # Create a border line
# Center the status text within the borders
$paddedStatus = $Status.PadLeft(([int]($lineLength / 2) + [int]($Status.Length / 2))).PadRight($lineLength)
# Display the formatted status message with specified colors
Write-Host $border -ForegroundColor $HeaderColor
Write-Host $paddedStatus -ForegroundColor $HeaderColor
Write-Host $border -ForegroundColor $HeaderColor
Write-Host $Message -ForegroundColor $ContentColor
Write-Host $border -ForegroundColor $HeaderColor
Write-Host
}
}
PROCESS {
try {
# Attempt to retrieve the latest release information from the GitHub repository
$githubLatestRelease = (Invoke-WebRequest -ErrorAction Stop -Uri $RepoURL).Content | ConvertFrom-Json
} catch {
# If unable to access the repository URL, display an error message and exit
Write-Console "$(Invoke-TimeStamp)Unable to access the website: " -NoNewLine
Write-Console $RepoURL -ForegroundColor Red
Start-Sleep 8
break
}
# Extract the latest release tag name (e.g., "v1.2.3")
$latestRelease = $githubLatestRelease.tag_name
# Remove leading 'v' from the latest release version
$latestReleaseVersion = $latestRelease.Replace('v', '')
try {
# Determine the script directory and attempt to find the local script file
if ($PSScriptRoot) {
$content = Get-ChildItem "$PSScriptRoot\$ScriptName*" -ErrorAction Stop
} else {
$content = Get-ChildItem ".\$ScriptName*" -ErrorAction Stop
}
$scriptPath = $content[0].FullName # Get the full path of the script
$scriptContent = Get-Content $scriptPath -ErrorAction Stop # Read the script content
} catch {
# If the script is not found locally, prompt the user to download it
Write-Warning "$(Invoke-TimeStamp)Unable to access the $ScriptName or $ScriptName* file ($pwd). Make sure you are running this in the script directory!"
do {
# Prompt the user to attempt downloading the latest release
$answer = Read-Host "$(Invoke-TimeStamp)Attempt to download latest release from the internet? (Y/N)"
} until ($answer -eq 'y' -or $answer -eq 'n') # Repeat until a valid response is given
if ($answer -eq 'n') {
# If the user chooses not to download, exit the script
Write-Console "$(Invoke-TimeStamp)Stopping script"
break
} else {
# Proceed to download the latest release asset
Write-Console "$(Invoke-TimeStamp)Latest Release: " -NoNewLine
Write-Console $latestReleaseVersion -ForegroundColor Green
Write-Console "$(Invoke-TimeStamp)Finding asset matching pattern: $AssetPattern"
# Search for the asset in the release assets that matches the specified pattern
$githubAsset = $githubLatestRelease.Assets | Where-Object { $_.Name -like $AssetPattern } | Select-Object -First 1
if ($null -eq $githubAsset) {
# If no matching asset is found, display an error and exit
Write-Console "$(Invoke-TimeStamp)No suitable asset found in the release." -ForegroundColor Red
break
}
# Determine the file extension of the asset (e.g., ".zip", ".ps1")
$assetExtension = [System.IO.Path]::GetExtension($githubAsset.Name)
$filePath = Join-Path $pwd $githubAsset.Name # Construct the full path for the downloaded asset
# Download the asset file from the release
Write-Console "$(Invoke-TimeStamp)Downloading asset: $($githubAsset.Name) -> $filePath"
Invoke-WebRequest $githubAsset.browser_download_url -OutFile $filePath
# Handle the asset based on its file extension
if ($assetExtension -eq '.zip') {
# If the asset is a ZIP file, extract its contents
Write-Console "$(Invoke-TimeStamp)Expanding zip archive: $($githubAsset.Name)"
Expand-Archive -LiteralPath $filePath -DestinationPath $pwd -Force
# Remove the ZIP file after extraction
Write-Console "$(Invoke-TimeStamp)Cleaning up zip release..."
Remove-Item -LiteralPath $filePath -Force | Out-Null
} elseif ($assetExtension -eq '.ps1') {
# If the asset is a PowerShell script, inform the user
Write-Console "$(Invoke-TimeStamp)Downloaded PowerShell script: $($githubAsset.Name)"
# No extraction needed for .ps1 files
} else {
# If the asset type is unknown, display an error and exit
Write-Console "$(Invoke-TimeStamp)Unknown asset type: $($githubAsset.Name)" -ForegroundColor Red
break
}
}
}
# Proceed if the script was found or successfully downloaded
if (!$answer) {
# Attempt to extract the version number from the script content
$versionLine = $scriptContent | Select-String -Pattern '(Version: \d+(\.\d+)*|DevelopmentVersion)' | Select-Object -First 1
if ($versionLine)
{
if ($versionLine -match "DevelopmentVersion")
{
$scriptVersion = "999.0.0" # Set a high version to trigger development build message
}
else
{
# Extract the version number from the matched line
$scriptVersion = ($versionLine -split "Version: ")[1].Trim().Replace("v", "")
}
}
else
{
# If no version is found, default to "0.0.0"
$scriptVersion = "0.0.0"
}
# Compare the local script version with the latest release version
if ([version]$scriptVersion -gt [version]$latestReleaseVersion) {
# If the local version is newer than the latest release, it's a development build
$status = "DEVELOPMENT BUILD"
$message = "You are currently on a development build of $($content.Name) last modified on $(($scriptContent | Select-String -Pattern 'Last Modified: (.*)' | ForEach-Object { $_.Matches[0].Groups[1].Value } | Select-Object -First 1).Trim())"
# Display the status message with yellow header color
Show-VersionStatus -Status $status -Message $message -HeaderColor Yellow -ContentColor White
} elseif ([version]$scriptVersion -lt [version]$latestReleaseVersion) {
# If the local version is older, an update is available
$status = "UPDATE AVAILABLE"
$message = "Current Script Version: $scriptVersion`nLatest Release Version: $latestReleaseVersion"
# Display the status message with red header color
Show-VersionStatus -Status $status -Message $message -HeaderColor Red -ContentColor White
# Remove old script files before downloading the new version
Write-Console "$(Invoke-TimeStamp)Removing old script files to replace with newer versions."
Get-ChildItem -Path .\ -Include $ScriptName*, "$($ScriptName)-v*.*.*", Queries | Remove-Item -Recurse -Force
# Find and download the latest asset matching the pattern
Write-Console "$(Invoke-TimeStamp)Finding asset matching pattern: $AssetPattern"
$githubAsset = $githubLatestRelease.Assets | Where-Object { $_.Name -like $AssetPattern } | Select-Object -First 1
if ($null -eq $githubAsset) {
# If no matching asset is found, display an error and exit
Write-Console "$(Invoke-TimeStamp)No suitable asset found in the release." -ForegroundColor Red
break
}
# Determine the file extension and construct the download path
$assetExtension = [System.IO.Path]::GetExtension($githubAsset.Name)
$filePath = Join-Path $pwd $githubAsset.Name
# Download the asset from the release
Write-Console "$(Invoke-TimeStamp)Downloading asset: $($githubAsset.Name) -> $filePath"
Invoke-WebRequest $githubAsset.browser_download_url -OutFile $filePath
# Handle the downloaded asset based on its type
if ($assetExtension -eq '.zip') {
# If it's a ZIP file, extract it
Write-Console "$(Invoke-TimeStamp)Expanding zip archive: $($githubAsset.Name)"
Expand-Archive -LiteralPath $filePath -DestinationPath $pwd -Force
# Remove the ZIP file after extraction
Write-Console "$(Invoke-TimeStamp)Cleaning up zip release..."
Remove-Item -LiteralPath $filePath -Force | Out-Null
} elseif ($assetExtension -eq '.ps1') {
# If it's a PowerShell script, inform the user
Write-Console "$(Invoke-TimeStamp)Downloaded PowerShell script: $($githubAsset.Name)"
# No extraction needed
} else {
# If the asset type is unrecognized, display an error and exit
Write-Console "$(Invoke-TimeStamp)Unknown asset type: $($githubAsset.Name)" -ForegroundColor Red
break
}
} else {
# If the local version matches the latest release, inform the user
$status = "UP TO DATE"
$message = "You are currently on the latest version of $($content.Name): $latestReleaseVersion"
# Display the status message with green header color
Show-VersionStatus -Status $status -Message $message -HeaderColor Green -ContentColor White
}
}
}
END {
# Final message indicating the script has completed its execution
Write-Console "$(Invoke-TimeStamp)Script completed!"
Start-Sleep -Seconds 8
}
}
# Invoke the auto-updater function to check for updates and handle accordingly
Invoke-AutoUpdater