HotCakeX / Harden-Windows-Security

Harden Windows Safely, Securely using Official Supported Microsoft methods and proper explanation | Always up-to-date and works with the latest build of Windows | Provides tools and Guides for Personal, Enterprise, Government and Military security levels | Read The Rationale https://github.com/HotCakeX/Harden-Windows-Security/blob/main/Rationale.md
https://hotcakex.github.io
MIT License
1.8k stars 139 forks source link

[Bug]: Error invoking PowerShell when profile sets PSReadLine `-PredictionViewStyle Inline` #337

Closed SamErde closed 1 month ago

SamErde commented 1 month ago

Tools category

Harden Windows Security Module

Does Your System Meet The Requirements?

Is your Windows Installation Genuine?

Did You Read The Frequently Asked Questions?

Please Explain The Bug

After choosing options and clicking the 'go' button (what do you call it? 😊), a large number of the selected changes were completed. The last clean line in my log was 9/4/2024 4:58:52 PM: Verbose: Creating the deny policy file.

The next step it tried to perform was to run C:\Program Files\PowerShell\Modules\WDACConfig\0.4.4\Core\New-DenyWDACConfig.psm1.

I didn't include the whole error report because the reason was made obvious by the error provided: my profile sets the PSReadLine prediction view style, but that option is not supported in this context. (There is probably a check that I can add to my profile to avoid this setting when running non-interactively.) I think the easiest solution for Harden Windows Security would be to just add the -NoProfile option when calling pwsh.exe to run other scripts.

Let me know if you'd like more info or another test!

Error Details

Exception calling "Run" with "1" argument(s): "Program 'powershell.exe' failed to run: PowerShell script execution failed: Error: The predictive suggestion feature cannot be enabled because the console output doesn't support virtual terminal processing or it's redirected.
HotCakeX commented 1 month ago

Hi, do you have this

Set-PSReadLineOption -PredictionViewStyle InlineView

in your PowerShell profile?

I put the same line in PowerShell profiles but couldn't reproduce the error when running the Downloads defense measures category. These are the profile locations i tried:

"C:\Program Files\PowerShell\7\profile.ps1"
"C:\Users\Admin\Documents\PowerShell\Microsoft.PowerShell_profile.ps1"

the module uses the System.Management.Automation namespace for running native PowerShell code.

SamErde commented 1 month ago

Yes. Hmmm, maybe I assumed too quickly.

My CurrentUserAllHosts profile only contains one line that dot-sources my "real" profile from a cloned repo. That profile contains this:

# Base PowerShell Profile for CurrentUserAllHosts
# Written by Sam Erde. Feel free to use, customize, and let me know if you have any questions!

#region Default Settings for All Versions
Import-Module Terminal-Icons
Import-Module posh-git

$PSDefaultParameterValues = @{
    'ConvertTo-Csv:NoTypeInformation' = $True
    'ConvertTo-Xml:NoTypeInformation' = $True
    'Export-Csv:NoTypeInformation'    = $True
    'Format-[WT]*:Autosize'           = $True
    'Get-Help:ShowWindow'             = $False
    '*:Encoding'                      = 'utf8'
    'Out-Default:OutVariable'         = 'LastOutput'
}

$PSReadLineOptions = @{
    HistoryNoDuplicates           = $true
    HistorySearchCursorMovesToEnd = $true
}
Set-PSReadLineOption @PSReadLineOptions

# Do not write to history file if command was less than 4 characters. Borrowed from Sean Wheeler.
$global:__DefaultHistoryHandler = (Get-PSReadLineOption).AddToHistoryHandler
Set-PSReadLineOption -AddToHistoryHandler {
    param([string]$Line)
    $DefaultResult = $global:__defaultHistoryHandler.Invoke($Line)
    if ($DefaultResult -eq 'MemoryAndFile') {
        if ($Line.Length -gt 3 -and $Line[0] -ne ' ' -and $Line[-1] -ne ';') {
            return 'MemoryAndFile'
        } else {
            return 'MemoryOnly'
        }
    }
    return $DefaultResult
}

# Set the working location to my Repositories folder.
if (Test-Path -Path $([System.IO.Path]::Combine($HOME, 'Repositories')) -PathType Container -ErrorAction SilentlyContinue) {
    Set-Location ([System.IO.Path]::Combine($HOME, 'Repositories'))
} else {
    Set-Location -Path $HOME
}
#endregion Default Settings for All Versions

#region Version-Specific Settings
if ($PSVersionTable.PSVersion -lt '6.0') {
    $IsLinux = $IsMacOS = $false
    $IsWindows = $true
    $IsWindowsPowerShell = $true
} else {
    $IsPowerShell = $true
}
if ($host.Name -eq 'Windows PowerShell ISE Host') {
    $IsPowerShellISE = $true
}

if ($IsWindowsPowerShell) {
    # Windows PowerShell 5.1- doesn't support history plugins.
    Set-PSReadLineOption -PredictionViewStyle Inline -PredictionSource History
}

if ($IsPowerShell) {
    <# These only need to be run once:
    #   Enable-ExperimentalFeature PSSubsystemPluginModel
    #   Enable-ExperimentalFeature PSFeedbackProvider
    #   Enable-ExperimentalFeature PSCommandNotFoundSuggestion
    #>
    Import-Module CompletionPredictor
    Set-PSReadLineOption -PredictionViewStyle ListView -PredictionSource HistoryAndPlugin
}

if (-not $IsPowerShellISE) {
    # Initialize Oh My Posh prompt:
    oh-my-posh init pwsh --config '~\Repositories\Private\Private-Workshop\Backups\sturdy.omp.json' | Invoke-Expression
} else {
    # Something in this seems to be causing a delay that I didn't have until recently. I need to debug it.
    function Prompt {
        Write-Host "[#$((Get-History).Count) ~ $([math]::Ceiling((((Get-History)[-1]).EndExecutionTime - ((Get-History)[-1]).StartExecutionTime).TotalMilliseconds))ms] " -NoNewline -ForegroundColor Yellow
        #Write-Host "" -NoNewline -ForegroundColor Yellow
        Write-Host "$($PWD.ToString().Replace($HOME,'~'))" -ForegroundColor Cyan
        Write-Host '>' -NoNewline -ForegroundColor White
        return ' '
    }
}

if ($IsLinux -or $IsMacOS) {
    Import-Module Microsoft.PowerShell.UnixTabCompletion
    Import-PSUnixTabCompletion
}
#endregion Version-Specific Settings

#region Transcription
function ExitPowerShell () {
    try {
        Stop-Transcript | Out-Null
        Write-Host 'Transcript stopped.' -ForegroundColor Green -BackgroundColor Black -NoNewline
    } catch {
        [System.InvalidOperationException]
    }
    exit
}
$ExitAction = { ExitPowerShell }

if ($Host.Name -eq 'ConsoleHost') {
    # Start-Transcript for logging
    $DailyTranscriptLogFile = '~\PowerShell_Logs\{0:yyyyMMdd\THHmmss.ffffzz}.log' -f (Get-Date)
    Start-Transcript $DailyTranscriptLogFile
    Remove-Variable -Name DailyTranscriptLogFile

    # Register exit handler to Stop-Transcript and save command history.
    [void](Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action $ExitAction)

    # Clean up Old Log files
    Get-ChildItem -Path '~\PowerShell_Logs' |
        Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } |
            Remove-Item -Force -ErrorAction SilentlyContinue

} else {
    # Register exit handler to stop-transcript and save command history
    [void](Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action $ExitAction)
}
#endregion Transcription
HotCakeX commented 1 month ago

Can you please try something and let me know if it fixes it.

in the PowerShellExecutor.cs file located at

"C:\Users\USERNAME\OneDrive\Documents\PowerShell\Modules\Harden-Windows-Security-Module\0.6.0\C#\Others\PowerShellExecutor.cs"

Replace this part in line 20

using (PowerShell psInstance = PowerShell.Create())

with this

using (PowerShell psInstance = PowerShell.Create(RunspaceMode.NewRunspace))

Then close/reopen PS and try the command again that used to fail.

SamErde commented 1 month ago

Will try this and hopefully let you know tomorrow!

SamErde commented 1 month ago

OK, for the record, here's my full error report. Maybe something more specific will jump out at you:

❯ (irm 'https://raw.githubusercontent.com/HotCakeX/Harden-Windows-Security/main/Harden-Windows-Security.ps1')+'P'|iex
Transcript started, output file is ~\PowerShell_Logs\20240905T153141.9727-04.log
MethodInvocationException: Exception calling "Run" with "1" argument(s): "Program 'powershell.exe' failed to run: PowerShell script
execution failed: Error: The predictive suggestion feature cannot be enabled because the console output
doesn't support virtual terminal processing or it's redirected. Category: NotSpecified Target:  Script
StackTrace: at <ScriptBlock>, ~\Repositories\Private\Private-Workshop\PSProfileBase.ps1: line
63 at <ScriptBlock>, ~\OneDrive\Documents\WindowsPowerShell\profile.ps1: line 2 at
<ScriptBlock>, <No file>: line 1 Exception Type: System.Management.Automation.RemoteException StackTrace:
At C:\Program Files\PowerShell\Modules\WDACConfig\0.4.4\Core\New-DenyWDACConfig.psm1:348 char:17 +
powershell.exe -Command { +                 ~~~~~~~~~~~~~~~~~~~~~~~~~."

ErrorRecord                 : Exception calling "Run" with "1" argument(s): "Program 'powershell.exe'
                              failed to run: PowerShell script execution failed: Error: The predictive
                              suggestion feature cannot be enabled because the console output doesn't
                              support virtual terminal processing or it's redirected.
                              Category: NotSpecified
                              Target:
                              Script StackTrace: at <ScriptBlock>,
                              ~\Repositories\Private\Private-Workshop\PSProfileBase.ps1: line
                              63
                              at <ScriptBlock>,
                              ~\OneDrive\Documents\WindowsPowerShell\profile.ps1: line 2
                              at <ScriptBlock>, <No file>: line 1
                              Exception Type: System.Management.Automation.RemoteException
                              StackTrace: At C:\Program
                              Files\PowerShell\Modules\WDACConfig\0.4.4\Core\New-DenyWDACConfig.psm1:348
                              char:17
                              +                 powershell.exe -Command {
                              +                 ~~~~~~~~~~~~~~~~~~~~~~~~~."
WasThrownFromThrowStatement : False
TargetSite                  : Void
                              CheckActionPreference(System.Management.Automation.Language.FunctionContext,
                              System.Exception)
Message                     : Exception calling "Run" with "1" argument(s): "Program 'powershell.exe'
                              failed to run: PowerShell script execution failed: Error: The predictive
                              suggestion feature cannot be enabled because the console output doesn't
                              support virtual terminal processing or it's redirected.
                              Category: NotSpecified
                              Target:
                              Script StackTrace: at <ScriptBlock>,
                              ~\Repositories\Private\Private-Workshop\PSProfileBase.ps1: line
                              63
                              at <ScriptBlock>,
                              ~\OneDrive\Documents\WindowsPowerShell\profile.ps1: line 2
                              at <ScriptBlock>, <No file>: line 1
                              Exception Type: System.Management.Automation.RemoteException
                              StackTrace: At C:\Program
                              Files\PowerShell\Modules\WDACConfig\0.4.4\Core\New-DenyWDACConfig.psm1:348
                              char:17
                              +                 powershell.exe -Command {
                              +                 ~~~~~~~~~~~~~~~~~~~~~~~~~."
Data                        : {[System.Management.Automation.Interpreter.InterpretedFrameInfo,
                              System.Management.Automation.Interpreter.InterpretedFrameInfo[]]}
InnerException              : System.Management.Automation.RuntimeException: Program 'powershell.exe'
                              failed to run: PowerShell script execution failed: Error: The predictive
                              suggestion feature cannot be enabled because the console output doesn't
                              support virtual terminal processing or it's redirected.
                              Category: NotSpecified
                              Target:
                              Script StackTrace: at <ScriptBlock>,
                              ~\Repositories\Private\Private-Workshop\PSProfileBase.ps1: line
                              63
                              at <ScriptBlock>,
                              ~\OneDrive\Documents\WindowsPowerShell\profile.ps1: line 2
                              at <ScriptBlock>, <No file>: line 1
                              Exception Type: System.Management.Automation.RemoteException
                              StackTrace: At C:\Program
                              Files\PowerShell\Modules\WDACConfig\0.4.4\Core\New-DenyWDACConfig.psm1:348
                              char:17
                              +                 powershell.exe -Command {
                              +                 ~~~~~~~~~~~~~~~~~~~~~~~~~.
                               ---> System.Management.Automation.ApplicationFailedException: Program
                              'powershell.exe' failed to run: PowerShell script execution failed: Error:
                              The predictive suggestion feature cannot be enabled because the console
                              output doesn't support virtual terminal processing or it's redirected.
                              Category: NotSpecified
                              Target:
                              Script StackTrace: at <ScriptBlock>,
                              ~\Repositories\Private\Private-Workshop\PSProfileBase.ps1: line
                              63
                              at <ScriptBlock>,
                              ~\OneDrive\Documents\WindowsPowerShell\profile.ps1: line 2
                              at <ScriptBlock>, <No file>: line 1
                              Exception Type: System.Management.Automation.RemoteException
                              StackTrace: At C:\Program
                              Files\PowerShell\Modules\WDACConfig\0.4.4\Core\New-DenyWDACConfig.psm1:348
                              char:17
                              +                 powershell.exe -Command {
                              +                 ~~~~~~~~~~~~~~~~~~~~~~~~~.
                               ---> System.InvalidOperationException: PowerShell script execution failed:
                              Error: The predictive suggestion feature cannot be enabled because the
                              console output doesn't support virtual terminal processing or it's
                              redirected.
                              Category: NotSpecified
                              Target:
                              Script StackTrace: at <ScriptBlock>,
                              ~\Repositories\Private\Private-Workshop\PSProfileBase.ps1: line
                              63
                              at <ScriptBlock>,
                              ~\OneDrive\Documents\WindowsPowerShell\profile.ps1: line 2
                              at <ScriptBlock>, <No file>: line 1
                              Exception Type: System.Management.Automation.RemoteException
                              StackTrace:
                                 at HardenWindowsSecurity.PowerShellExecutor.<>c__DisplayClass0_0.<ExecuteS
                              cript>b__3(Object sender, DataAddedEventArgs args)
                                 at System.Management.Automation.PSDataCollection`1.RaiseEvents(Guid
                              psInstanceId, Int32 index)
                                 at System.Management.Automation.PSDataCollection`1.InternalAddRange(Guid
                              psInstanceId, ICollection collection)
                                 at
                              System.Management.Automation.Internal.PSDataCollectionStream`1.Write(Object
                              obj, Boolean enumerateCollection)
                                 at System.Management.Automation.Internal.Pipe.AddToPipe(Object obj)
                                 at System.Management.Automation.MshCommandRuntime._WriteErrorSkipAllowChec
                              k(ErrorRecord errorRecord, Nullable`1 actionPreference, Boolean
                              isFromNativeStdError)
                                 at System.Management.Automation.NativeCommandProcessor.ProcessOutputRecord
                              (ProcessOutputObject outputValue)
                                 at System.Management.Automation.NativeCommandProcessor.ConsumeAvailableNat
                              iveProcessOutput(Boolean blocking)
                                 at System.Management.Automation.NativeCommandProcessor.Complete()
                                 --- End of inner exception stack trace ---
                                 at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference
                              (FunctionContext funcContext, Exception exception)
                                 at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(In
                              terpretedFrame frame)
                                 at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstructio
                              n.Run(InterpretedFrame frame)
                                 at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstructio
                              n.Run(InterpretedFrame frame)
                                 --- End of inner exception stack trace ---
                                 at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable
                              input)
                                 at System.Management.Automation.PowerShell.Worker.ConstructPipelineAndDoWo
                              rk(Runspace rs, Boolean performSyncInvoke)
                                 at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAn
                              dDoWork(Runspace rsToUse, Boolean isSync)
                                 at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput
                              ](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings
                              settings)
                                 at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDa
                              taCollection`1 input, PSDataCollection`1 output, PSInvocationSettings
                              settings)
                                 at System.Management.Automation.PowerShell.Invoke()
                                 at HardenWindowsSecurity.PowerShellExecutor.ExecuteScript(String script,
                              Boolean returnOutput, Boolean NonTerminatingErrors)
                                 at HardenWindowsSecurity.DownloadsDefenseMeasures.Invoke()
                                 at
                              HardenWindowsSecurity.GUIProtectWinSecurity.<>c.<AddEventHandlers>b__0_18()
                                 at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread
                              threadPoolThread, ExecutionContext executionContext, ContextCallback
                              callback, Object state)
                              --- End of stack trace from previous location ---
                                 at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread
                              threadPoolThread, ExecutionContext executionContext, ContextCallback
                              callback, Object state)
                                 at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task&
                              currentTaskSlot, Thread threadPoolThread)
                              --- End of stack trace from previous location ---
                                 at HardenWindowsSecurity.GUIProtectWinSecurity.<>c.<<AddEventHandlers>b__0
                              _10>d.MoveNext()
                              --- End of stack trace from previous location ---
                                 at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state)
                                 at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate
                              callback, Object args, Int32 numArgs)
                                 at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source,
                              Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
                                 at System.Windows.Threading.DispatcherOperation.InvokeImpl()
                                 at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object
                              obj)
                                 at System.Threading.ExecutionContext.RunInternal(ExecutionContext
                              executionContext, ContextCallback callback, Object state)
                              --- End of stack trace from previous location ---
                                 at System.Threading.ExecutionContext.RunInternal(ExecutionContext
                              executionContext, ContextCallback callback, Object state)
                                 at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExec
                              utionContext executionContext, ContextCallback callback, Object state)
                                 at System.Windows.Threading.DispatcherOperation.Invoke()
                                 at System.Windows.Threading.Dispatcher.ProcessQueue()
                                 at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32
                              msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
                                 at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam,
                              IntPtr lParam, Boolean& handled)
                                 at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate
                              callback, Object args, Int32 numArgs)
                                 at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source,
                              Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
                                 at
                              System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority
                              priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
                                 at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr
                              wParam, IntPtr lParam)
                                 at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
                                 at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame
                              frame)
                                 at System.Windows.Application.RunDispatcher(Object ignore)
                                 at System.Windows.Application.RunInternal(Window window)
                                 at CallSite.Target(Closure, CallSite, Application, Window)
HelpLink                    :
Source                      : System.Management.Automation
HResult                     : -2146233087
StackTrace                  :    at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference
                              (FunctionContext funcContext, Exception exception)
                                 at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(In
                              terpretedFrame frame)
                                 at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstructio
                              n.Run(InterpretedFrame frame)
                                 at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstructio
                              n.Run(InterpretedFrame frame)

MyCommand             :
BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 364
OffsetInLine          : 17
HistoryId             : 1
ScriptName            : ~\OneDrive\Documents\PowerShell\Modules\Harden-Windows-Security-Module
                        \0.6.0\Core\Protect-WindowsSecurity.psm1
Line                  :                 [System.Void] [HardenWindowsSecurity.GUIMain]::app.Run([HardenWindo
                        wsSecurity.GUIMain]::mainGUIWindow)

Statement             : [System.Void] [HardenWindowsSecurity.GUIMain]::app.Run([HardenWindowsSecurity.GUIMa
                        in]::mainGUIWindow)
PositionMessage       : At ~\OneDrive\Documents\PowerShell\Modules\Harden-Windows-Security-Mod
                        ule\0.6.0\Core\Protect-WindowsSecurity.psm1:364 char:17
                        + …             [System.Void] [HardenWindowsSecurity.GUIMain]::app.Run([H …
                        +               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PSScriptRoot          : ~\OneDrive\Documents\PowerShell\Modules\Harden-Windows-Security-Module
                        \0.6.0\Core
PSCommandPath         : ~\OneDrive\Documents\PowerShell\Modules\Harden-Windows-Security-Module
                        \0.6.0\Core\Protect-WindowsSecurity.psm1
InvocationName        :
PipelineLength        : 0
PipelinePosition      : 0
ExpectingInput        : False
CommandOrigin         : Internal
DisplayScriptPosition :
HotCakeX commented 1 month ago

Thanks for sharing the full log, i used it all in my test except for the oh-my-posh one because i don't have whatever it needs, the json file. so this is what i used in the profile

# Base PowerShell Profile for CurrentUserAllHosts
# Written by Sam Erde. Feel free to use, customize, and let me know if you have any questions!

Install-Module CompletionPredictor
Install-Module Terminal-Icons
Install-Module posh-git
Install-Module oh-my-posh

#region Default Settings for All Versions
Import-Module Terminal-Icons
Import-Module posh-git

$PSDefaultParameterValues = @{
    'ConvertTo-Csv:NoTypeInformation' = $True
    'ConvertTo-Xml:NoTypeInformation' = $True
    'Export-Csv:NoTypeInformation'    = $True
    'Format-[WT]*:Autosize'           = $True
    'Get-Help:ShowWindow'             = $False
    '*:Encoding'                      = 'utf8'
    'Out-Default:OutVariable'         = 'LastOutput'
}

$PSReadLineOptions = @{
    HistoryNoDuplicates           = $true
    HistorySearchCursorMovesToEnd = $true
}
Set-PSReadLineOption @PSReadLineOptions

# Do not write to history file if command was less than 4 characters. Borrowed from Sean Wheeler.
$global:__DefaultHistoryHandler = (Get-PSReadLineOption).AddToHistoryHandler
Set-PSReadLineOption -AddToHistoryHandler {
    param([string]$Line)
    $DefaultResult = $global:__defaultHistoryHandler.Invoke($Line)
    if ($DefaultResult -eq 'MemoryAndFile') {
        if ($Line.Length -gt 3 -and $Line[0] -ne ' ' -and $Line[-1] -ne ';') {
            return 'MemoryAndFile'
        }
        else {
            return 'MemoryOnly'
        }
    }
    return $DefaultResult
}

# Set the working location to my Repositories folder.
if (Test-Path -Path $([System.IO.Path]::Combine($HOME, 'Repositories')) -PathType Container -ErrorAction SilentlyContinue) {
    Set-Location ([System.IO.Path]::Combine($HOME, 'Repositories'))
}
else {
    Set-Location -Path $HOME
}
#endregion Default Settings for All Versions

#region Version-Specific Settings
if ($PSVersionTable.PSVersion -lt '6.0') {
    $IsWindowsPowerShell = $true
}
else {
    $IsPowerShell = $true
}
if ($host.Name -eq 'Windows PowerShell ISE Host') {
    $IsPowerShellISE = $true
}

if ($IsWindowsPowerShell) {
    # Windows PowerShell 5.1- doesn't support history plugins.
    Set-PSReadLineOption -PredictionViewStyle Inline -PredictionSource History
}

if ($IsPowerShell) {
    <# These only need to be run once:
    #   Enable-ExperimentalFeature PSSubsystemPluginModel
    #   Enable-ExperimentalFeature PSFeedbackProvider
    #   Enable-ExperimentalFeature PSCommandNotFoundSuggestion
    #>
    Import-Module CompletionPredictor
    Set-PSReadLineOption -PredictionViewStyle ListView -PredictionSource HistoryAndPlugin
}

if (-not $IsPowerShellISE) {
    # Initialize Oh My Posh prompt:
    # oh-my-posh init pwsh --config '~\Repositories\Private\Private-Workshop\Backups\sturdy.omp.json' | Invoke-Expression
}
else {
    # Something in this seems to be causing a delay that I didn't have until recently. I need to debug it.
    function Prompt {
        Write-Host "[#$((Get-History).Count) ~ $([math]::Ceiling((((Get-History)[-1]).EndExecutionTime - ((Get-History)[-1]).StartExecutionTime).TotalMilliseconds))ms] " -NoNewline -ForegroundColor Yellow
        #Write-Host "" -NoNewline -ForegroundColor Yellow
        Write-Host "$($PWD.ToString().Replace($HOME,'~'))" -ForegroundColor Cyan
        Write-Host '>' -NoNewline -ForegroundColor White
        return ' '
    }
}

if ($IsLinux -or $IsMacOS) {
    Import-Module Microsoft.PowerShell.UnixTabCompletion
    Import-PSUnixTabCompletion
}
#endregion Version-Specific Settings

#region Transcription
function ExitPowerShell () {
    try {
        Stop-Transcript | Out-Null
        Write-Host 'Transcript stopped.' -ForegroundColor Green -BackgroundColor Black -NoNewline
    }
    catch {
        [System.InvalidOperationException]
    }
    exit
}
$ExitAction = { ExitPowerShell }

if ($Host.Name -eq 'ConsoleHost') {
    # Start-Transcript for logging
    $DailyTranscriptLogFile = '~\PowerShell_Logs\{0:yyyyMMdd\THHmmss.ffffzz}.log' -f (Get-Date)
    Start-Transcript $DailyTranscriptLogFile
    Remove-Variable -Name DailyTranscriptLogFile

    # Register exit handler to Stop-Transcript and save command history.
    [void](Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action $ExitAction)

    # Clean up Old Log files
    Get-ChildItem -Path '~\PowerShell_Logs' |
    Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } |
    Remove-Item -Force -ErrorAction SilentlyContinue

}
else {
    # Register exit handler to stop-transcript and save command history
    [void](Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action $ExitAction)
}
#endregion Transcription


I didn't have any of those modules so installed them first. Restarted the system after that for completeness.

Then i ran the Downloads Defense Measures category and it still worked fine. Could the problem be the oh-my-posh? i'm not really sure now. From the logs, I can see where the error is occurring, it is in the WDACConfig module's code, so i went ahead and tested that module itself, using the same command that the Harden Windows Security module internally uses.


New-DenyWDACConfig -PathWildCards -PolicyName 'Downloads Defense Measures' -FolderPath "C:\Users\Admin\Downloads\*" -Deploy -Verbose


And you can see it was successful


image

HotCakeX commented 1 month ago

More testing

Installed oh-my-posh from MS store, restarted, added the oh-myposh command back to the profile, the same one you used in yours, ran both the WDACConfig module and the Download defense measures category, still no error was thrown.

image

I also tested it on PowerShell from MSI file and the one downloaded from MS store.

image


Based on these results and the full log, the problem must be in the json file that i don't have

# oh-my-posh init pwsh --config '~\Repositories\Private\Private-Workshop\Backups\sturdy.omp.json' | Invoke-Expression

can you please share it with me? if it has sensitive content you can remove it but i just want to reproduce this error so i can make sure the fix will be accurate.

btw i think this is an edge case, the command that is causing the problem is jumping through 3 hoops. first you dot source another ps1 file in your profile, that gets executed and runs all those commands, and then there is a line that executes the json file with invoke expression and oh-my-posh!


SamErde commented 1 month ago

Fascinating. I just stripped Oh My Posh by running function prompt { Write-Host 'PS>' } and was very surprised to see Protect-WindowsSecurity run successfully! (Side note, the OMP module is unnecessary and deprecated. It's just a wrapper around the executable.)

Here is my OMP theme from `sturdy.omp.json`. ```json { "$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json", "blocks": [ { "alignment": "left", "segments": [ { "background": "#ffe9aa", "foreground": "#100e23", "powerline_symbol": "\ue0b0", "style": "powerline", "template": " \uf0e7 \uf4ff ", "type": "root" }, { "type": "executiontime", "style": "powerline", "powerline_symbol": "\ue0b0", "foreground": "#ffffff", "background": "#25265e", "template": " <#fefefe>\uf520 {{ .FormattedMs }} ", "properties": { "threshold": 500, "style": "austin", "always_enabled": true } }, { "background": "#22bcee", "foreground": "#100e23", "powerline_symbol": "\ue0b0", "properties": { "folder_icon": "\uf115", "folder_separator_icon": " \ue0b1 ", "style": "full" }, "style": "powerline", "template": " {{ .Path }} ", "type": "path" }, { "background": "#95ffa4", "foreground": "#193549", "powerline_symbol": "\ue0b0", "style": "powerline", "template": " {{ .HEAD }} ", "type": "git" }, { "background": "#906cff", "foreground": "#100e23", "powerline_symbol": "\ue0b0", "style": "powerline", "template": " \ue235 {{ if .Error }}{{ .Error }}{{ else }}{{ if .Venv }}{{ .Venv }} {{ end }}{{ .Full }}{{ end }} ", "type": "python" }, { "background": "#ff8080", "foreground": "#ffffff", "powerline_symbol": "\ue0b0", "style": "powerline", "template": " \ue20f ", "type": "status" } ], "type": "prompt" }, { "alignment": "left", "newline": true, "segments": [ { "foreground": "#007ACC", "style": "plain", "template": "\u276f ", "type": "text" } ], "type": "prompt" } ], "version": 2 } ```

This does have a few elements I never use that could be cleaned up (the python segment, for example). I copied and modified an existing theme as a starting point.

To further test this, I swapped OMP out for a few other variations of this prompt that I created on my own without OMP.

function Prompt {
    Write-Host ("PS [$((Get-History).Count)] $((((Get-History)[-1]).EndExecutionTime - ((Get-History)[-1]).StartExecutionTime).TotalMilliseconds) ms> $($($PWD.Path).Replace($HOME,'~'))>")
    Write-Host '>' -NoNewline
    return ' '
}

This also produced the same error:

PS [47] 47.2825 ms> ~\Repositories>
> Protect-WindowsSecurity -GUI
Protect-WindowsSecurity: Exception setting "WindowTitle": "A command that prompts the user failed because the host program or the command type does not support user interaction. Try a host program that supports user interaction, such as the PowerShell Console, and remove prompt-related commands from command types that do not support user interaction."
SamErde commented 1 month ago

Unsurprisingly, this also caused the error:

    function Prompt {
        Write-Host "[#$((Get-History).Count) ~ $([math]::Ceiling((((Get-History)[-1]).EndExecutionTime - ((Get-History)[-1]).StartExecutionTime).TotalMilliseconds))ms] " -NoNewline -ForegroundColor Yellow
        #Write-Host "" -NoNewline -ForegroundColor Yellow
        Write-Host "$($PWD.ToString().Replace($HOME,'~'))" -ForegroundColor Cyan
        Write-Host '>' -NoNewline -ForegroundColor White
        return ' '
    }

image

SamErde commented 1 month ago

This one also failed with and without the colors defined: image

SamErde commented 1 month ago

Hey, @JanDeDobbeleer, I think OMP has been vindicated, but I'm curious if you have any ideas on this one!

Ref: https://github.com/HotCakeX/Harden-Windows-Security/blob/e16b1846160672a976c3546a161ec29fdee252fa/Harden-Windows-Security%20Module/Main%20files/C%23/Others/PowerShellExecutor.cs#L20

HotCakeX commented 1 month ago

I've fixed all the errors related to WindowTitle and made the process more resilient, allowing competing components to coexist alongside the module.

I've also added -NoProfile to 2 places for future proofing.

I still can't reproduce the original error about prediction though, i put the exact JSON file you gave me in the same path.

SamErde commented 1 month ago

It's a weird one. Wonder if there's something else in my environment causing this. I can't be the first person with Oh My Posh or a similar prompt. The -NoProfile should help. I'm curious about your other WindowTitle fixes. Let me know and I'll retest.

HotCakeX commented 1 month ago

With these 2 updates:

All of the problems mentioned here must be fixed. but please let me know if they don't :)

SamErde commented 1 month ago

Protect-WindowsSecurity -GUI works now. Protect-WindowsSecurity -Categories ... also works! Nice job fixing the issue!

HotCakeX commented 1 month ago

Thanks, that's great ^^