Skip to content

Refactor module functions to use begin/process/end with safer error handling - #32

Merged
rwidmark merged 6 commits into
devfrom
copilot/optimize-code-with-try-catch
Apr 16, 2026
Merged

rwidmark merged 6 commits into
devfrom
copilot/optimize-code-with-try-catch

Conversation

Copilot AI commented Apr 16, 2026

Copy link
Copy Markdown

The module functions were missing a consistent advanced-function structure and had several failure paths without targeted exception handling. This change standardizes function flow with begin/process/end, tightens error handling around downloads/installations/process execution, and removes a few brittle code paths.

  • Function structure

    • Converted module functions to advanced functions with explicit begin/process/end blocks
    • Added SupportsShouldProcess to Update-rsWinSoftware so state-changing behavior is declared explicitly
    • Preserved the existing control flow while making setup, execution, and cleanup boundaries clearer
  • Error handling

    • Wrapped network calls, package installs, module imports, and external process execution in targeted try/catch
    • Added explicit exit-code validation for msiexec and winget
    • Used finally blocks for temp file cleanup after WinGet, dependency, and PowerShell installer downloads
  • Code-path hardening

    • Added defensive handling for missing WinGet version data
    • Switched GitHub release tag normalization to a single-prefix removal pattern
    • Guarded optional HttpVersion usage so requests do not fail on unset values
    • Normalized a few variable names and messages for readability
  • Small optimizations

    • Reused parameter hashtables for web requests instead of repeating inline argument lists
    • Simplified dependency iteration and process argument construction
    • Reduced repeated path-building and cleanup logic

Example of the updated pattern:

function Confirm-rsWinGet {
    [CmdletBinding()]
    param($SysInfo)

    begin {
        $WinGetUrl = "https://api.github.com/repos/microsoft/winget-cli/releases/latest"
    }

    process {
        try {
            $release = Invoke-RestMethod @restMethodParameters
            Add-AppxPackage -Path $packagePath -ForceApplicationShutdown -ErrorAction Stop
        }
        catch {
            throw "Message: $($_.Exception.Message)`nError Line: $($_.InvocationInfo.Line)`n"
        }
        finally {
            if (Test-Path $packagePath) {
                Remove-Item $packagePath -Force -ErrorAction SilentlyContinue
            }
        }
    }
}

Copilot AI and others added 6 commits April 16, 2026 17:50
Agent-Logs-Url: https://github.com/rwidmark/WinSoftwareUpdate/sessions/f981789e-3b64-4df8-bd97-5d7a4ed428ea

Co-authored-by: rwidmark <76907327+rwidmark@users.noreply.github.com>
Agent-Logs-Url: https://github.com/rwidmark/WinSoftwareUpdate/sessions/f981789e-3b64-4df8-bd97-5d7a4ed428ea

Co-authored-by: rwidmark <76907327+rwidmark@users.noreply.github.com>
Agent-Logs-Url: https://github.com/rwidmark/WinSoftwareUpdate/sessions/f981789e-3b64-4df8-bd97-5d7a4ed428ea

Co-authored-by: rwidmark <76907327+rwidmark@users.noreply.github.com>
Agent-Logs-Url: https://github.com/rwidmark/WinSoftwareUpdate/sessions/f981789e-3b64-4df8-bd97-5d7a4ed428ea

Co-authored-by: rwidmark <76907327+rwidmark@users.noreply.github.com>
Agent-Logs-Url: https://github.com/rwidmark/WinSoftwareUpdate/sessions/f981789e-3b64-4df8-bd97-5d7a4ed428ea

Co-authored-by: rwidmark <76907327+rwidmark@users.noreply.github.com>
Agent-Logs-Url: https://github.com/rwidmark/WinSoftwareUpdate/sessions/f981789e-3b64-4df8-bd97-5d7a4ed428ea

Co-authored-by: rwidmark <76907327+rwidmark@users.noreply.github.com>
@rwidmark
rwidmark requested a review from Copilot April 16, 2026 17:59
@rwidmark
rwidmark marked this pull request as ready for review April 16, 2026 18:04
@rwidmark
rwidmark merged commit efc61b8 into dev Apr 16, 2026
4 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors key functions in the WinSoftwareUpdate PowerShell module to use a consistent advanced-function structure (begin/process/end) and adds more targeted error handling around web requests, installs, and external process execution.

Changes:

  • Converted several functions to advanced functions with explicit begin/process/end blocks.
  • Tightened error handling for GitHub API calls, downloads, Add-AppxPackage, and Start-Process exit-code validation.
  • Added SupportsShouldProcess to Update-rsWinSoftware and refactored WinGet upgrade argument construction.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ErrorAction = "Stop"
}

if (-not [string]::IsNullOrWhiteSpace([string]$SysInfo.HTTPVersion)) {

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as above: this adds HttpVersion unconditionally based on a non-empty string, which will break on Windows PowerShell 5.1 because Invoke-RestMethod there doesn’t accept -HttpVersion. Gate adding this parameter on $PSVersionTable.PSVersion.Major -ge 7 (or parameter availability) to keep the module compatible with the manifest’s PowerShellVersion = 5.1.

Suggested change
if (-not [string]::IsNullOrWhiteSpace([string]$SysInfo.HTTPVersion)) {
if (
$PSVersionTable.PSVersion.Major -ge 7 -and
-not [string]::IsNullOrWhiteSpace([string]$SysInfo.HTTPVersion)
) {

Copilot uses AI. Check for mistakes.
Comment on lines +392 to +397
if ($null -ne $SysInfo -and -not [string]::IsNullOrWhiteSpace([string]$SysInfo.HTTPVersion)) {
$MetadataParameters.HttpVersion = $SysInfo.HTTPVersion
}
elseif ($CurrentVersion -ge $MinimumPwsh7Version) {
$MetadataParameters.HttpVersion = "3.0"
}

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invoke-RestMethod on Windows PowerShell 5.1 doesn’t support -HttpVersion, but this block can still set HttpVersion (e.g., from $SysInfo.HTTPVersion or hard-coded "3.0") even when running under 5.1, leading to a runtime parameter binding failure. Only add HttpVersion when the current session supports it (PS 7+), otherwise omit it entirely.

Suggested change
if ($null -ne $SysInfo -and -not [string]::IsNullOrWhiteSpace([string]$SysInfo.HTTPVersion)) {
$MetadataParameters.HttpVersion = $SysInfo.HTTPVersion
}
elseif ($CurrentVersion -ge $MinimumPwsh7Version) {
$MetadataParameters.HttpVersion = "3.0"
}
if ($PSVersionTable.PSVersion.Major -ge 7) {
if ($null -ne $SysInfo -and -not [string]::IsNullOrWhiteSpace([string]$SysInfo.HTTPVersion)) {
$MetadataParameters.HttpVersion = $SysInfo.HTTPVersion
}
elseif ($CurrentVersion -ge $MinimumPwsh7Version) {
$MetadataParameters.HttpVersion = "3.0"
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +494 to +501
if (-not $IsAdministrator) {
Write-Error ("{0} needs admin privileges, exiting now...." -f $MyInvocation.MyCommand)
return
}

# Register WinGet
# Add-AppxPackage -RegisterByFamilyName -MainPackage "Microsoft.DesktopAppInstaller_8wekyb3d8bbwe"
if (-not $PSCmdlet.ShouldProcess("Local computer", "Update installed software with WinGet")) {
return
}

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With SupportsShouldProcess, -WhatIf should ideally be able to run without requiring elevation, but the admin check happens before ShouldProcess, so non-admin users can’t even preview actions. Consider calling ShouldProcess first (and returning early on -WhatIf), and only enforcing the admin check when actually performing the update.

Copilot uses AI. Check for mistakes.
Comment on lines 295 to +307
Function Confirm-rsDependency {
# Collecting systeminformation
$SysInfo = Get-rsSystemInfo

# If any dependencies are missing it will install them
foreach ($_info in $SysInfo.Software.keys) {
if ($_info -notlike "WinGet") {
$Software = $SysInfo.Software.$_info
if ($null -eq $Software.version -or $Software.version -eq "0.0.0.0") {
[CmdletBinding()]
Param()

begin {
}

process {
$SysInfo = Get-rsSystemInfo

foreach ($DependencyName in $SysInfo.Software.Keys | Where-Object { $_ -ne "WinGet" }) {
$Software = $SysInfo.Software[$DependencyName]
if ($null -eq $Software.Version -or $Software.Version -eq "0.0.0.0") {

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirm-rsDependency is exported (per module manifest) and performs state-changing installs/downloads, but it doesn’t declare SupportsShouldProcess or honor ShouldProcess internally. Either add SupportsShouldProcess + ShouldProcess guards around the install/download operations, or make this a private helper (remove from FunctionsToExport) so callers don’t invoke side effects unexpectedly.

Copilot uses AI. Check for mistakes.
Comment on lines 351 to +364
@@ -281,73 +357,92 @@ Function Confirm-rsPowerShell7 {
.EXAMPLE
#>

$MissingPWSH7 = $false

[version]$CurrentVersion = if ($PSVersionTable.PSVersion.Major -lt 7) {
$CheckpwshVersion = Test-Path -Path "C:\Program Files\PowerShell\7\pwsh.exe"
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false)]
$SysInfo
)

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module manifest exports Get-rsPowerShell7, but this file defines Confirm-rsPowerShell7 (and there is no Get-rsPowerShell7 function). This makes the public API inconsistent and can prevent consumers from calling the intended function. Align the function name and the manifest’s FunctionsToExport list (rename the function or update the manifest).

Copilot uses AI. Check for mistakes.
Comment on lines +428 to +431
Write-Output "PowerShell 7 was not installed on your system, PowerShell 7 have been installed and you need to restart PowerShell to use the new version"
}
else {
Write-Output "PowerShell 7 have been updated from $CurrentVersion to $Release, you need to restart PowerShell to use the new version"

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar in user-facing output: use singular verb forms ("has") with "PowerShell 7". This improves professionalism and clarity of console output.

Suggested change
Write-Output "PowerShell 7 was not installed on your system, PowerShell 7 have been installed and you need to restart PowerShell to use the new version"
}
else {
Write-Output "PowerShell 7 have been updated from $CurrentVersion to $Release, you need to restart PowerShell to use the new version"
Write-Output "PowerShell 7 was not installed on your system, PowerShell 7 has been installed and you need to restart PowerShell to use the new version"
}
else {
Write-Output "PowerShell 7 has been updated from $CurrentVersion to $Release, you need to restart PowerShell to use the new version"

Copilot uses AI. Check for mistakes.
ErrorAction = "Stop"
}

if (-not [string]::IsNullOrWhiteSpace([string]$SysInfo.HTTPVersion)) {

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$SysInfo.HTTPVersion is always set to a non-empty value ("2.0" on Windows PowerShell 5.1), so this code will add an HttpVersion parameter even when running on PowerShell 5.1 where Invoke-RestMethod does not support -HttpVersion, causing a parameter binding error. Only include HttpVersion when the current PowerShell supports it (e.g., $PSVersionTable.PSVersion.Major -ge 7 or by checking the cmdlet’s parameter set), or set SysInfo.HTTPVersion to $null for PS < 7.

Suggested change
if (-not [string]::IsNullOrWhiteSpace([string]$SysInfo.HTTPVersion)) {
if (
-not [string]::IsNullOrWhiteSpace([string]$SysInfo.HTTPVersion) -and
(Get-Command -Name Invoke-RestMethod).Parameters.ContainsKey('HttpVersion')
) {

Copilot uses AI. Check for mistakes.
@rwidmark
rwidmark deleted the copilot/optimize-code-with-try-catch branch April 16, 2026 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants