################################################################################ # # Microsoft WindowsDefender exclusions cleaner # Espressif Systems, 2019 # ################################################################################ # # - cleans all Windows Defender process exclusions containing given path (both Process and Path) # - run as Administrator, eg: PowerShell -ExecutionPolicy ByPass -File tools_WD_clean.ps1 -RmExclPath "C:\Program Files\Espressif\ESP-IDF Tools". If not running with admin privileges, the script tries to elevate itself (new process, output grabbed on exit) # minimum requirements: Windows XP SP3, PowerShell 2.0, Windows Defender with relevant PS cmdlets # - Returns 0 on success or -1 on failure # ################################################################################ Param ( [String]$RmExclPath, [String]$logFile ) function Check-Command($cmdname) { return [bool](Get-Command -Name $cmdname -ErrorAction SilentlyContinue) } function Log-Msg($msg, $logF = $null) { if( ![string]::IsNullOrEmpty($logF) ) { Write-Output $msg *>> $logF } else { Write-Output $msg } [Console]::Out.Flush() } $retVal = 1 Try { Import-Module Defender #self-elevation support $myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent() $myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID) $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator if( -not $myWindowsPrincipal.IsInRole($adminRole) ) { $params = "" foreach($key in $PSBoundParameters.keys) { $params = -join( $params, "-", $key, " `"", $PSBoundParameters[$key], "`"" ) } #running elevated and logFile not set if( [string]::IsNullOrEmpty($logFile) ) { $tempFileName = Get-Date -UFormat "%Y%m%d%H%M%s" $lf = Join-Path -Path $env:TEMP -ChildPath "WDEspLog$tempFileName.log" } $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell" $newProcess.Arguments = "-ExecutionPolicy ByPass -File " + $script:MyInvocation.MyCommand.Definition + " " + $params + " -logFile $lf" $newProcess.Verb = "RunAs" $newProcess.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden $proc = [System.Diagnostics.Process]::Start($newProcess) $proc.WaitForExit() if (Test-Path -Path $lf ) { foreach($line in Get-Content $lf) { Log-Msg -msg $line } Remove-Item $lf } exit $proc.ExitCode } Log-Msg -msg "Getting Windows Defender process exclusions..." -logF $logFile $Preferences = Get-MpPreference #ExclusionProcess $cnt = $Preferences.ExclusionProcess.Count $cntRemoved = 0 $cntRemovedTotal = 0 $cntMissed = 0 $cntMissedTotal = 0 $bRmPath = ![string]::IsNullOrEmpty($RmExclPath) if( $bRmPath ) { Log-Msg -msg "Exclusion path: $RmExclPath" -logF $logFile } Log-Msg -msg " Found total $cnt of ExclusionProcess items" -logF $logFile foreach( $pref in $Preferences.ExclusionProcess ) { if( $bRmPath ) { $bGoAhead = $pref.Contains($RmExclPath) } else { $bGoAhead = $true } if( $bGoAhead ) { Log-Msg -msg " removing $pref" -logF $logFile Try { Remove-MpPreference -ExclusionProcess $pref $cntRemoved++ } Catch { if( ![string]::IsNullOrEmpty($logFile) ) { Write-Error -Exception $_.Exception *>> $logFile } Write-Error -Exception $_.Exception $cntMissed++ } } } if( $cntMissed -eq 0 ) { Log-Msg -msg " $cntRemoved relevant items removed from ExclusionProcess list" -logF $logFile } else { Log-Msg -msg " WARNING: Only $cntRemoved out of $(cntRemoved+cntMissed) relevant items removed from ExclusionProcess list" -logF $logFile } #ExclusionPath $cnt = $Preferences.ExclusionPath.Count $cntRemovedTotal = $cntRemoved $cntRemoved = 0 $cntMissedTotal = $cntMissed $cntMissed = 0 Log-Msg -msg " Found total $cnt of ExclusionPath items" -logF $logFile foreach( $pref in $Preferences.ExclusionPath ) { if( $bRmPath ) { $bGoAhead = $pref.Contains($RmExclPath) } else { $bGoAhead = $true } if( $bGoAhead ) { Log-Msg -msg " removing $pref" -logF $logFile Try { Remove-MpPreference -ExclusionPath $pref $cntRemoved++ } Catch { if( ![string]::IsNullOrEmpty($logFile) ) { Write-Error -Exception $_.Exception *>> $logFile } Write-Error -Exception $_.Exception $cntMissed++ } } } if( $cntMissed -eq 0 ) { Log-Msg -msg " $cntRemoved relevant items removed from ExclusionPath list" -logF $logFile } else { Log-Msg -msg " WARNING: Only $cntRemoved out of $(cntRemoved+cntMissed) relevant items removed from ExclusionPath list" -logF $logFile } #TOTAL $cntRemovedTotal += $cntRemoved $cntMissedTotal += $cntMissed Log-Msg -msg "============================" -logF $logFile if( $cntMissedTotal -eq 0 ) { Log-Msg -msg "OK: Processed all $cntRemovedTotal items" -logF $logFile } else { Log-Msg -msg "WARNING: Processed only $cntRemovedTotal out of $(cntRemovedTotal+cntMissedTotal) relevat items" -logF $logFile } Log-Msg -msg "`nDone" -logF $logFile $retVal = 0 } Catch { if( ![string]::IsNullOrEmpty($logFile) ) { Write-Error -Exception $_.Exception *>> $logFile } Write-Error -Exception $_.Exception [Environment]::Exit($retVal) } Finally { [Environment]::Exit($retVal) }