Public/Invoke-Executable.ps1

function Invoke-Executable
{
    <#
        .DESCRIPTION
            Install or uninstall an EXE
        
        .PARAMETER FilePath
            Specify the path to the EXE file
    
        .PARAMETER Arguments
            Specify additional arguments to pass to the EXE file
    
        .PARAMETER ExitCodes
            Specify non-standard success exit codes (Comma seperated list)
    
        .EXAMPLE
            Install an EXE
                Invoke-Executable -FilePath "$PSScriptRoot\Setup.exe" -Arguments '/S /v"/qn REBOOT=reallysuppress"'
    
            Install an EXE with non-standard exit codes 2 and 8
                Invoke-Executable -FilePath "$PSScriptRoot\Setup.exe" -Arguments '/S' -ExitCodes '2,8'
    
        .NOTES
            Created by: Jon Anderson
            Modified: 2023-07-10
    #>

    [CmdletBinding()]    
    param(
        [parameter(Mandatory = $true)][ValidateScript({
        if(!($_ | Test-Path))
        {
            throw "$_ was not found"
        }
        if(!($_ | Test-Path -PathType Leaf))
        {
            throw "$_ is not a file path"
        }
        if($_ -notmatch "(\.exe)")
        {
            throw "$_ is not an EXE file"
        }
        return $true 
        })]
        [System.IO.FileInfo]$FilePath,
        [parameter(Mandatory = $false)][ValidateNotNullOrEmpty()]
        [String]$Arguments,
        [parameter(Mandatory = $false)][ValidateNotNullOrEmpty()]
        [String]$ExitCodes
    )

    $ArgumentList = New-Object 'System.Collections.Generic.List[string]'
    if($ExitCodes)
    {
        $ExitSplit = $ExitCodes.Split(',')
    }
    if($Arguments)
    {
        $Arguments = $ExecutionContext.InvokeCommand.ExpandString($Arguments)
        $ArgumentList.Add($Arguments)
    }
    $StringFilePath = $FilePath.ToString()
    $StringFilePath = $StringFilePath.insert(0,'"')
    $StringFilePath+='"'
    Write-LogEntry -Value "Running Command: $StringFilePath $ArgumentList" -Severity 1
    if($Arguments)
    {
        $ExitCode = (Start-Process -FilePath $StringFilePath -ArgumentList $ArgumentList -Wait -PassThru).ExitCode
    }
    else
    {
        $ExitCode = (Start-Process -FilePath $StringFilePath -Wait -PassThru).ExitCode
    }
    if(($ExitCode -ne 0) -and ($ExitCode -ne 3010) -and !($ExitSplit -contains $ExitCode))
    {
        Stop-Script -ErrorMessage "The executable terminated with an error: $ExitCode"
    }
    Write-LogEntry -Value "The exit code is $ExitCode" -Severity 1
}