ConsoleMode.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# Hack! https://gist.github.com/lzybkr/f2059cb2ee8d0c13c65ab933b75e998c

if ($IsWindows -eq $false) {
    function Set-ConsoleMode {
        [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
        param()
    }
    return
}

Add-Type @"
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_PROCESSED_INPUT             = 0x0001
    ENABLE_LINE_INPUT                  = 0x0002
    ENABLE_ECHO_INPUT                  = 0x0004
    ENABLE_WINDOW_INPUT                = 0x0008
    ENABLE_MOUSE_INPUT                 = 0x0010
    ENABLE_INSERT_MODE                 = 0x0020
    ENABLE_QUICK_EDIT_MODE             = 0x0040
    ENABLE_EXTENDED_FLAGS              = 0x0080
    ENABLE_AUTO_POSITION               = 0x0100
    ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0200
}

[Flags()]
enum ConsoleModeOutputFlags
{
    ENABLE_PROCESSED_OUTPUT            = 0x0001
    ENABLE_WRAP_AT_EOL_OUTPUT          = 0x0002
    ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
}

function Set-ConsoleMode
{
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    param(
        [Parameter(ParameterSetName = "ANSI")]
        [switch]
        $ANSI,

        [Parameter(ParameterSetName = "Mode")]
        [uint32]
        $Mode,

        [switch]
        $StandardInput
    )

    if ($ANSI)
    {
        $outputMode = [NativeConsoleMethods]::GetConsoleMode($false)
        $null = [NativeConsoleMethods]::SetConsoleMode($false, $outputMode -bor [ConsoleModeOutputFlags]::ENABLE_VIRTUAL_TERMINAL_PROCESSING)

        if ($StandardInput)
        {
            $inputMode = [NativeConsoleMethods]::GetConsoleMode($true)
            $null = [NativeConsoleMethods]::SetConsoleMode($true, $inputMode -bor [ConsoleModeInputFlags]::ENABLE_VIRTUAL_TERMINAL_PROCESSING)
        }
    }
    else
    {
        [NativeConsoleMethods]::SetConsoleMode($StandardInput, $Mode)
    }
}