#!SEMICOLONS must be placed after each command as scriptdata needs to be sent to powershell directly with the -c parameter! ; if ($PSVersionTable.PSVersion.Major -le 5) { # For Windows PowerShell, we want to remove any PowerShell 7 paths from PSModulePath #snipped from https://github.com/PowerShell/DSC/pull/777/commits/af9b99a4d38e0cf1e54c4bbd89cbb6a8a8598c4e #Presumably users are supposed to know not to have custom paths for powershell desktop containing a 'powershell' subfolder?? ; $env:PSModulePath = ($env:PSModulePath -split ';' | Where-Object { $_ -notlike '*\powershell\*' }) -join ';'; }; $consoleModeSource = @" using System; using System.Runtime.InteropServices; public class NativeConsoleMethods { [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern IntPtr GetStdHandle(int handleId); [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern bool GetConsoleMode(IntPtr hConsoleOutput, out uint dwMode); [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern bool SetConsoleMode(IntPtr hConsoleOutput, uint dwMode); public static uint GetConsoleMode(bool input = false) { var handle = GetStdHandle(input ? -10 : -11); uint mode; if (GetConsoleMode(handle, out mode)) { return mode; } return 0xffffffff; } public static uint SetConsoleMode(bool input, uint mode) { var handle = GetStdHandle(input ? -10 : -11); if (SetConsoleMode(handle, mode)) { return GetConsoleMode(input); } return 0xffffffff; } } "@ ; [Flags()] enum ConsoleModeInputFlags { ENABLE_LINE_INPUT = 0x0002 ENABLE_ECHO_INPUT = 0x0004 }; if (!('NativeConsoleMethods' -as [System.Type])) { Add-Type $consoleModeSource } function psmain { param ( [validateSet('enableRaw', 'disableRaw')] [string]$Action ); # $inputflags = Get-ConsoleMode -StandardInput; if (!('NativeConsoleMethods' -as [System.Type])) { Add-Type $consoleModeSource } $inputFlags = [NativeConsoleMethods]::GetConsoleMode($true); $resultflags = $inputflags; if (($inputflags -band [ConsoleModeInputFlags]::ENABLE_LINE_INPUT) -eq [ConsoleModeInputFlags]::ENABLE_LINE_INPUT) { #cooked mode $initialstate = "cooked"; if ($action -eq "enableraw") { #disable cooked flags $disable = [uint32](-bnot [uint32][ConsoleModeInputFlags]::ENABLE_LINE_INPUT) -band ( -bnot [uint32][ConsoleModeInputFlags]::ENABLE_ECHO_INPUT); $adjustedflags = $inputflags -band ($disable); $resultflags = [NativeConsoleMethods]::SetConsoleMode($true,$adjustedflags); } } else { #raw mode $initialstate = "raw"; if ($action -eq "disableraw") { #set cooked flags $adjustedflags = $inputflags -bor [ConsoleModeInputFlags]::ENABLE_LINE_INPUT -bor [ConsoleModeInputFlags]::ENABLE_ECHO_INPUT; $resultflags = [NativeConsoleMethods]::SetConsoleMode($true,$adjustedflags); } } #return in format that can act as a tcl dict #write-host "startflags: $inputflags initialstate: $initialstate action: $Action endflags: $resultflags"; }; # psmain 'enableRaw'; $consoleid = $args[0]; if ([string]::IsNullOrEmpty($consoleid)) { $consoleid= "" }; $pipeName = "punkshell_ps_consolemode_$consoleid"; "pipename: $pipeName" $pipeServer = New-Object System.IO.Pipes.NamedPipeServerStream($pipeName); try { while ($true) { #"Waiting for connection on '$pipeName'"; $pipeServer.WaitForConnection(); #"Connection established"; $pipeReader = New-Object System.IO.StreamReader($pipeServer); #$pipeWriter = New-Object System.IO.StreamWriter($pipeServer); #$pipeWriter.AutoFlush = $true; $request = $pipeReader.ReadLine(); # "Received request: $request"; if ($request -eq "exit") { "consolemode_server.ps1 Exiting"; exit; } elseif ($request -eq "") { #"Empty input"; $pipeServer.Disconnect(); #"Disconnected"; continue; } elseif ($request -eq $none) { "Remote disconnected before sending"; $pipeServer.Disconnect(); "Disconnected"; continue; } elseif ($request -eq "enableraw") { #$result = psmain 'enableRaw'; $null = psmain 'enableRaw' # "Sending result: '$result'"; #$pipeWriter.Write($result); $pipeServer.Disconnect(); continue; } else { "consolemode_server.ps1 ignoring request: $request"; $pipeServer.Disconnect(); continue; } } } finally { $pipeServer.Dispose(); };