Skip to content

Instantly share code, notes, and snippets.

@atrenton
Created January 4, 2023 16:53
Show Gist options
  • Save atrenton/cffb27bcf732d2fe1eec0dd305edec1a to your computer and use it in GitHub Desktop.
Save atrenton/cffb27bcf732d2fe1eec0dd305edec1a to your computer and use it in GitHub Desktop.
Start Windows Defender Custom Scan

The following script runs a custom Windows Defender scan on multiple drives with exclusions.

👉 NOTE: Since this is a long-running script, be sure to turn off the Sleep setting for your computer before you run it.

Windows 10 procedure to change the Sleep setting to 'Never'

  1. Navigate to Settings > System > Power & sleep
  2. Click the drop-down setting for Sleep and change it to Never

✅ Don't forget to restore your system Sleep setting preference when the script finishes

#requires -RunAsAdministrator
Import-Module Defender

Function Start-CustomScan
{
<# .DESCRIPTION
    Runs Custom Windows Defender Scan on Multiple Drives with Exclusions
#>
    [CmdletBinding()]
    Param(
        [Parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]$volumes
    )
    $ErrorActionPreference = 'Stop'

    ForEach ($volume in $volumes)
    {
        $drive = "$($volume.DriveLetter):\"
        $exclusions = (Get-MpPreference).ExclusionExtension
        $friendlyName = "$($volume.FileSystemLabel)"
        $logFile = "CustomScan-Drive-$($volume.DriveLetter).csv"
        $message = "{0} CustomScan on Drive $drive"

        $LogMessage = @{
            LogFile = $logFile
            Message = $message -f 'BEGIN'
        }
        Write-Log @LogMessage

        try {
            Start-MpScan -ScanPath $drive -ScanType CustomScan
            $LogMessage.Message = "Volume $friendlyName exclusions: $exclusions"
            $LogMessage.Severity = 'Information'
        } catch {
            $LogMessage.Message = $_.Exception.Message
            $LogMessage.Severity = 'Error'
        }
        Write-Log @LogMessage

        $result = "$(Get-Date -f g) Drive $drive scan completed {0}."

        if ($LogMessage.Severity -ne 'Error') {
            $result = $result -f 'successfully'
        } else {
            $result = $result -f 'with error(s)'
            $LogMessage.Severity = 'Information'
        }

        $LogMessage.Message = $message -f '*END*'
        Write-Log @LogMessage
        Write-Output $result
    }
}

Function Write-Log
{
#   REF: https://adamtheautomator.com/powershell-log-function/
    [CmdletBinding()]
    Param(
        [Parameter()]
        [string]$LogDirectory = "$([Environment]::GetFolderPath("Desktop"))\Logs",

        [Parameter()]
        [string]$LogFile = 'LogFile.csv',

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$Message,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [ValidateSet('Information','Warning','Error')]
        [string]$Severity = 'Information'
    )

    if (-not(Test-Path -Path $LogDirectory -PathType Container)) {
        $null = New-Item -ItemType Directory -Path $LogDirectory -ErrorAction STOP
    }
    $LogPath = Join-Path -Path $LogDirectory -ChildPath $LogFile

    [PSCustomObject] @{
        # REF: https://social.technet.microsoft.com/wiki/contents/articles/32274.powershell-get-date-format.aspx
        Time = (Get-Date -f g)
        Message = $Message
        Severity = $Severity
    } | Export-Csv -Path $LogPath -Append -NoTypeInformation
}

echo "Windows Defender Last Updated Date and Age"
echo "=========================================="
(Get-MpComputerStatus | Select-Object *LastUpdated,*SignatureAge | Out-String).Trim()

# Setup for Custom Scan with Exclusions; CHANGE $exclusions FOR YOUR NEEDS
$exclusions = @('*.ffu','*.iso','*.m4a','*.mp3','*.wav','*.wim')
Set-MpPreference -CheckForSignaturesBeforeRunningScan $true
Set-MpPreference -ExclusionExtension $exclusions

Start-CustomScan (Get-Volume |
    Where-Object {$_.DriveLetter -ne $null -and $_.OperationalStatus -eq 'OK'} |
    Sort-Object DriveLetter)

$events = Get-WinEvent -FilterHashtable @{
   LogName = 'Microsoft-Windows-Windows Defender/Operational'
   Level = 2
}
if ($events) {
    $events | Out-GridView -Title 'Windows Defender Errors' -Wait
}

if (($Host.Name -eq 'ConsoleHost') -and (-not $env:WT_SESSION)) {
    Write-Host "`nPress any key to close this window . . ." -NoNewline
    $Host.UI.RawUI.ReadKey('NoEcho, IncludeKeyDown') | Out-Null
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment