- 
      
- 
        Save nohwnd/5c07fe62c861ee563f69c9ee1f7c9688 to your computer and use it in GitHub Desktop. 
| #Requires -RunAsAdministrator | |
| function Uninstall-Pester ([switch]$All) { | |
| if ([IntPtr]::Size * 8 -ne 64) { throw "Run this script from 64bit PowerShell." } | |
| #Requires -RunAsAdministrator | |
| $pesterPaths = foreach ($programFiles in ($env:ProgramFiles, ${env:ProgramFiles(x86)})) { | |
| $path = "$programFiles\WindowsPowerShell\Modules\Pester" | |
| if ($null -ne $programFiles -and (Test-Path $path)) { | |
| if ($All) { | |
| Get-Item $path | |
| } | |
| else { | |
| Get-ChildItem "$path\3.*" | |
| } | |
| } | |
| } | |
| if (-not $pesterPaths) { | |
| "There are no Pester$(if (-not $all) {" 3"}) installations in Program Files and Program Files (x86) doing nothing." | |
| return | |
| } | |
| foreach ($pesterPath in $pesterPaths) { | |
| takeown /F $pesterPath /A /R | |
| icacls $pesterPath /reset | |
| # grant permissions to Administrators group, but use SID to do | |
| # it because it is localized on non-us installations of Windows | |
| icacls $pesterPath /grant "*S-1-5-32-544:F" /inheritance:d /T | |
| Remove-Item -Path $pesterPath -Recurse -Force -Confirm:$false | |
| } | |
| } | |
| Uninstall-Pester | 
@jasonrush good point. I spent some time and refactored into a true cmdlet using advanced function syntax. The module name is Utils and must be installed in a location located within $env:PSModulePath. The file structure is:
- Utils
- Utils.psd1
- Utils.psm1
- /Public
- Uninstall-Pester.ps1
 
- /Private
 
The Utils.psd1
@{
ModuleVersion = "1.0.0"
GUID = "e38b14a6-0d85-4be5-869e-38ed7e270126"
Author = "Your Name Here"
CompanyName = "My Company"
Copyright = "(c) 2021 My Company All rights reserved."
RootModule = "Utils.psm1"
}
Utils.ps1 file
Get-ChildItem -Filter *.ps1 -Path "$PSScriptRoot\public","$PSScriptRoot\private" -Recurse | ForEach-Object { . $_.FullName; Write-Verbose "Loaded $_.BaseName" }
Get-ChildItem -Filter *.ps1 -Path "$PSScriptRoot\public" -Recurse | ForEach-Object { Export-ModuleMember $_.BaseName; Write-Verbose "Exported $_.BaseName" }
Uninstall-Pester.ps1 file
function Uninstall-Pester {
    [CmdletBinding()]
    [OutputType([ bool ])]
    param(
        [Parameter()]
        [switch]
        $All = $false
    )
    
    begin {
        try {
            Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )]-Begin Enter"
            $result = $true
            $pesterPath = 'WindowsPowerShell\Modules\Pester'
            if ( -not $All ) {
                $pesterPath += '\3.*'
            }
            # See if there is anything to do
            $paths = @()
            foreach ( $path in @(${env:ProgramFiles}, ${env:ProgramFiles(x86)} ) ) {
                if ( $path -and ( Test-Path -Path "$path\$pesterPath" ) ) {
                    $paths += ( Get-ChildItem -Path "$path\$pesterPath" -Directory -ErrorAction SilentlyContinue ).FullName
                }
            }
            if ( -not $paths.Count ) {
                Write-Warning "There are no Pester$( if ( -not $All ) { " 3" } ) installations in Program Files and Program Files (x86)"
                $result = $false
                return
            }
        
            $isAdmin = (New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
            $is32BitProcess = $pshome -like "*syswow64*"
            $is64BitOS = ( Get-WmiObject Win32_OperatingSystem ).OSArchitecture -like "64*"
            $filePath = $null
            
            switch ( $true ) {
                { ( $is32BitProcess -and -not $is64BitOS ) -or ( -not $isAdmin -and $is64BitOS ) } {
                    Write-Warning "Restarting script under 64 bit powershell as admin"
                 
                    # relaunch this script under 64 bit shell as adminstrator
                    $filePath = "$( $pshome -replace "syswow64", "System32" )\powershell.exe"
                    break
                 }
                 { -not $isAdmin } {
                     Write-Warning "Restarting script using admin privs"
                    $filePath = 'powershell.exe'
                 }
            }
            
            if ( $filePath ) {
                Start-Process -FilePath $filePath -Verb RunAs -ArgumentList "-NoLogo -NoExit -Command `" Import-Module -name Utils; Uninstall-Pester $( if( $All ) { "-All" } )  `""
                $result = $false
                return
            }
        }
        catch {
            $result = $false
            Write-Verbose -Message  "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )] Exception:`r`n$_"
            throw $_
        }
        finally {
            Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )]-Begin Exit"
        }
    }
    process {
        try {
            Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )]-Process Enter"
            if ( -not $result ) {
                return
            }
            foreach ($path in $paths) {
                takeown /F $path /A /R
                icacls $path /reset
                # grant permissions to Administrators group, but use SID to do
                # it because it is localized on non-us installations of Windows
                icacls $path /grant "*S-1-5-32-544:F" /inheritance:d /T
                Remove-Item -Path $path -Recurse -Force -Confirm:$false -ErrorAction SilentlyContinue
            }
        
        }
        catch {
            $result = $false
            Write-Verbose -Message  "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )] Exception:`r`n$_"
            throw $_
        }
        finally {
            Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )]-Process Exit"
        }
    }
    
    end {
        try {
            Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )]-End Enter"
            return $result
        }
        catch {
            Write-Verbose -Message  "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )] Exception:`r`n$_"
            throw $_
        }
        finally {
            Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )]-End Exit"
        }
    }
}
@jcoryatjr my version is geared more towards non-interactive use. So I like that it fails when you are not admin. But thanks for sharing, hopefully someone will find it useful.
@jasonrush good point. I spent some time and refactored into a true cmdlet using advanced function syntax. The module name is Utils and must be installed in a location located within $env:PSModulePath. The file structure is:
Utils
Utils.psd1
Utils.psm1
/Public
- Uninstall-Pester.ps1
/Private
The Utils.psd1
@{ ModuleVersion = "1.0.0" GUID = "e38b14a6-0d85-4be5-869e-38ed7e270126" Author = "Your Name Here" CompanyName = "My Company" Copyright = "(c) 2021 My Company All rights reserved." RootModule = "Utils.psm1" }Utils.ps1 file
Get-ChildItem -Filter *.ps1 -Path "$PSScriptRoot\public","$PSScriptRoot\private" -Recurse | ForEach-Object { . $_.FullName; Write-Verbose "Loaded $_.BaseName" } Get-ChildItem -Filter *.ps1 -Path "$PSScriptRoot\public" -Recurse | ForEach-Object { Export-ModuleMember $_.BaseName; Write-Verbose "Exported $_.BaseName" }Uninstall-Pester.ps1 file
function Uninstall-Pester { [CmdletBinding()] [OutputType([ bool ])] param( [Parameter()] [switch] $All = $false ) begin { try { Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )]-Begin Enter" $result = $true $pesterPath = 'WindowsPowerShell\Modules\Pester' if ( -not $All ) { $pesterPath += '\3.*' } # See if there is anything to do $paths = @() foreach ( $path in @(${env:ProgramFiles}, ${env:ProgramFiles(x86)} ) ) { if ( $path -and ( Test-Path -Path "$path\$pesterPath" ) ) { $paths += ( Get-ChildItem -Path "$path\$pesterPath" -Directory -ErrorAction SilentlyContinue ).FullName } } if ( -not $paths.Count ) { Write-Warning "There are no Pester$( if ( -not $All ) { " 3" } ) installations in Program Files and Program Files (x86)" $result = $false return } $isAdmin = (New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) $is32BitProcess = $pshome -like "*syswow64*" $is64BitOS = ( Get-WmiObject Win32_OperatingSystem ).OSArchitecture -like "64*" $filePath = $null switch ( $true ) { { ( $is32BitProcess -and -not $is64BitOS ) -or ( -not $isAdmin -and $is64BitOS ) } { Write-Warning "Restarting script under 64 bit powershell as admin" # relaunch this script under 64 bit shell as adminstrator $filePath = "$( $pshome -replace "syswow64", "System32" )\powershell.exe" break } { -not $isAdmin } { Write-Warning "Restarting script using admin privs" $filePath = 'powershell.exe' } } if ( $filePath ) { Start-Process -FilePath $filePath -Verb RunAs -ArgumentList "-NoLogo -NoExit -Command `" Import-Module -name Utils; Uninstall-Pester $( if( $All ) { "-All" } ) `"" $result = $false return } } catch { $result = $false Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )] Exception:`r`n$_" throw $_ } finally { Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )]-Begin Exit" } } process { try { Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )]-Process Enter" if ( -not $result ) { return } foreach ($path in $paths) { takeown /F $path /A /R icacls $path /reset # grant permissions to Administrators group, but use SID to do # it because it is localized on non-us installations of Windows icacls $path /grant "*S-1-5-32-544:F" /inheritance:d /T Remove-Item -Path $path -Recurse -Force -Confirm:$false -ErrorAction SilentlyContinue } } catch { $result = $false Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )] Exception:`r`n$_" throw $_ } finally { Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )]-Process Exit" } } end { try { Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )]-End Enter" return $result } catch { Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )] Exception:`r`n$_" throw $_ } finally { Write-Verbose -Message "[$(( Get-Date ).TimeOfDay )][$( $MyInvocation.MyCommand )]-End Exit" } } }
Thanks your script worked out for to uninstall the module. And installing manually the newer version.
Thanks, helped me with this problem.
@jcoryatjr Note that your version would fail on any 32-bit only systems. While it should be rare to nonexistent, it is a possibility to consider.