11<#
22. SYNOPSIS
3- Defender Control v3.2.0 - Comprehensive Microsoft Defender Disable/Enable Utility
3+ Defender Control v3.2.1 - Comprehensive Microsoft Defender Disable/Enable Utility
44
55. DESCRIPTION
66 Professional WPF GUI + CLI tool to fully disable or re-enable Microsoft Defender
@@ -158,27 +158,77 @@ Note: -Mode Disable|Enable are reserved; use the GUI for mutating operations.
158158}
159159
160160# ==================================================================================
161- # SELF-ELEVATION (forwards original args so CLI mode survives UAC re-launch )
161+ # ARG-FORWARD HELPER (reused by both edition-rehost and self-elevation )
162162# ==================================================================================
163- if (-not ([Security.Principal.WindowsPrincipal ][Security.Principal.WindowsIdentity ]::GetCurrent()).IsInRole(
164- [Security.Principal.WindowsBuiltInRole ]::Administrator)) {
165-
166- # Rebuild the original argument list from $PSBoundParameters so
167- # switches/values survive the UAC re-launch.
168- $forwardedArgs = New-Object System.Collections.Generic.List[string ]
163+ function Get-ForwardedArgString {
164+ $fwd = New-Object System.Collections.Generic.List[string ]
169165 foreach ($kv in $PSBoundParameters.GetEnumerator ()) {
170166 $name = $kv.Key
171167 $val = $kv.Value
172168 if ($val -is [System.Management.Automation.SwitchParameter ]) {
173- if ($val.IsPresent ) { $forwardedArgs .Add (" -$name " ) | Out-Null }
169+ if ($val.IsPresent ) { $fwd .Add (" -$name " ) | Out-Null }
174170 } else {
175- $forwardedArgs .Add (" -$name " ) | Out-Null
176- $forwardedArgs .Add (' "' + ($val -replace ' "' , ' \"' ) + ' "' ) | Out-Null
171+ $fwd .Add (" -$name " ) | Out-Null
172+ $fwd .Add (' "' + ($val -replace ' "' , ' \"' ) + ' "' ) | Out-Null
177173 }
178174 }
179- $argList = " -NoProfile -ExecutionPolicy Bypass -File `" $PSCommandPath `" "
180- if ($forwardedArgs.Count -gt 0 ) { $argList += " " + ($forwardedArgs -join ' ' ) }
175+ $base = " -NoProfile -ExecutionPolicy Bypass -File `" $PSCommandPath `" "
176+ if ($fwd.Count -gt 0 ) { return $base + " " + ($fwd -join ' ' ) }
177+ return $base
178+ }
179+
180+ # ==================================================================================
181+ # POWERSHELL EDITION CHECK -- auto-relaunch under Windows PowerShell 5.1
182+ # ==================================================================================
183+ # WPF (PresentationFramework) requires Windows PowerShell 5.1; PS 7 / Core does
184+ # not ship it on all installs. Instead of erroring out, we silently re-spawn
185+ # the script under powershell.exe (WinPS 5.1), preserving all original args.
186+ if ($PSVersionTable.PSEdition -eq ' Core' ) {
187+ $isAdmin = ([Security.Principal.WindowsPrincipal ][Security.Principal.WindowsIdentity ]::GetCurrent()).IsInRole(
188+ [Security.Principal.WindowsBuiltInRole ]::Administrator)
189+ $argList = Get-ForwardedArgString
190+ $winPs = Join-Path $env: WINDIR ' System32\WindowsPowerShell\v1.0\powershell.exe'
191+ if (-not (Test-Path $winPs )) { $winPs = ' powershell.exe' } # fall back to PATH
181192
193+ try {
194+ if ($script :IsCliMode ) {
195+ # CLI: wait synchronously so stdout/stderr + exit code return to caller.
196+ $spArgs = @ {
197+ FilePath = $winPs
198+ ArgumentList = $argList
199+ Wait = $true
200+ PassThru = $true
201+ NoNewWindow = $true
202+ }
203+ if (-not $isAdmin ) { $spArgs.Remove (' NoNewWindow' ); $spArgs [' Verb' ] = ' RunAs' }
204+ $proc = Start-Process @spArgs
205+ exit $proc.ExitCode
206+ } else {
207+ # GUI: fire-and-forget new window
208+ $spArgs = @ { FilePath = $winPs ; ArgumentList = $argList }
209+ if (-not $isAdmin ) { $spArgs [' Verb' ] = ' RunAs' }
210+ Start-Process @spArgs
211+ }
212+ } catch {
213+ if ($script :IsCliMode ) {
214+ [Console ]::Error.WriteLine(" DefenderControl: requires Windows PowerShell 5.1 and $winPs could not be launched: $ ( $_.Exception.Message ) " )
215+ exit $script :EXIT_USAGE
216+ }
217+ Add-Type - AssemblyName PresentationFramework
218+ [System.Windows.MessageBox ]::Show(
219+ " This tool requires Windows PowerShell 5.1.`n`n Could not auto-launch powershell.exe.`n`n Manual: powershell.exe -File `" $PSCommandPath `" " ,
220+ " Could not re-launch under Windows PowerShell" , " OK" , " Error" ) | Out-Null
221+ }
222+ exit
223+ }
224+
225+ # ==================================================================================
226+ # SELF-ELEVATION (forwards original args so CLI mode survives UAC re-launch)
227+ # ==================================================================================
228+ if (-not ([Security.Principal.WindowsPrincipal ][Security.Principal.WindowsIdentity ]::GetCurrent()).IsInRole(
229+ [Security.Principal.WindowsBuiltInRole ]::Administrator)) {
230+
231+ $argList = Get-ForwardedArgString
182232 try {
183233 Start-Process powershell.exe - ArgumentList $argList - Verb RunAs
184234 } catch {
@@ -202,7 +252,7 @@ if (-not $script:IsCliMode) {
202252 Add-Type - AssemblyName PresentationFramework, PresentationCore, WindowsBase, System.Windows.Forms
203253}
204254
205- $script :Version = " 3.2.0 "
255+ $script :Version = " 3.2.1 "
206256$script :DryRun = [bool ]$DryRun
207257$script :ShowVerbose = $true
208258
@@ -231,17 +281,8 @@ if ($script:OSBuild -lt 17763 -and -not $script:IsCliMode) {
231281 " Old Windows Build" , " OK" , " Warning" ) | Out-Null
232282}
233283
234- # Check PowerShell edition
235- if ($PSVersionTable.PSEdition -eq ' Core' ) {
236- if ($script :IsCliMode ) {
237- [Console ]::Error.WriteLine(" DefenderControl: requires Windows PowerShell 5.1 (not PowerShell 7+). Run with powershell.exe, not pwsh." )
238- exit $script :EXIT_USAGE
239- }
240- [System.Windows.MessageBox ]::Show(
241- " This tool requires Windows PowerShell 5.1 (not PowerShell 7+).`n`n Please run with: powershell.exe -File `" $PSCommandPath `" " ,
242- " Wrong PowerShell Edition" , " OK" , " Error" ) | Out-Null
243- exit
244- }
284+ # PowerShell edition check happened earlier (auto-relaunches under WinPS 5.1).
285+ # By this point we are guaranteed to be on Windows PowerShell 5.1.
245286
246287# ==================================================================================
247288# CLI MODE: read-only state enumeration + dispatch
0 commit comments