gpt4 book ai didi

powershell - 如何在 powershell 中使用 SetConsoleMode 更改控制台输出模式?

转载 作者:行者123 更新时间:2023-12-02 22:12:13 56 4
gpt4 key购买 nike

我正在尝试更改 的 Windows 控制台模式输出 ( CONOUT$ ) 使用 Windows API 和 SetConsoleMode调用。所以我修改了一个 PowerShell 脚本,基于 ConinMode.ps1 (并且适用于输入),来做到这一点。阅读适用于 ConoutMode.exe和我的脚本,并返回:

# .\ConoutMode.exe
mode: 0x3
ENABLE_PROCESSED_OUTPUT 0x0001 ON
ENABLE_WRAP_AT_EOL_OUTPUT 0x0002 ON
ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 off <====
DISABLE_NEWLINE_AUTO_RETURN 0x0008 off
ENABLE_LVB_GRID_WORLDWIDE 0x0010 off

# .\ConoutMode.ps1
OK! GetConsoleWindow handle : 0x1F06D6
Console Input Mode (CONIN) : 0x21f
Console Output Mode (CONOUT) : 0x3

但是,我的脚本和 exe 都无法编写模式。 (可能是因为它认为我的输出句柄没有指向控制台?)

在 PowerShell 中:
# .\ConoutMode.exe set 0x000f
error: SetConsoleMode failed (is stdout a console?)

# .\ConoutMode.ps1 -Mode 7
OK! GetConsoleWindow handle : 0x1F06D6
old (out) mode: 0x3
SetConsoleMode (out) failed (is stdout a console?)
At C:\cygwin64\home\emix\win_esc_test\ConoutMode.ps1:112 char:9
+ throw "SetConsoleMode (out) failed (is stdout a console?)"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (SetConsoleMode ...out a console?):String) [], RuntimeException
+ FullyQualifiedErrorId : SetConsoleMode (out) failed (is stdout a console?)

这是我的 ConoutMode.ps1完整的脚本:
param (
[int] $Mode
)

$signature = @'
[DllImport("kernel32.dll", SetLastError=true)]
public static extern IntPtr GetConsoleWindow();

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);

public const int STD_INPUT_HANDLE = -10;
public const int STD_OUTPUT_HANDLE = -11;

public const int ENABLE_PROCESSED_OUTPUT = 0x0001;
public const int ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002;
public const int ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
public const int DISABLE_NEWLINE_AUTO_RETURN = 0x0008;
public const int ENABLE_LVB_GRID_WORLDWIDE = 0x0010;
'@
#----------------------------------------------------------
$WinAPI = Add-Type -MemberDefinition $signature -Name WinAPI -Namespace ConoutMode -PassThru
#$WinAPI = Add-Type -MemberDefinition $signature -Name WinAPI -Namespace IdentifyConsoleWindow -PassThru

$hwnd = $WinAPI::GetConsoleWindow()
if ($hwnd -eq 0) {
throw "Error: GetConsoleWindow returned NULL."
}
echo "OK! GetConsoleWindow handle : 0x$($hwnd.ToString("X"))"

function GetConIn {
$ret = $WinAPI::GetStdHandle($WinAPI::STD_INPUT_HANDLE)
if ($ret -eq -1) {
throw "Error: cannot get stdin handle"
}
return $ret
}

function GetConOut {
$ret = $WinAPI::GetStdHandle($WinAPI::STD_OUTPUT_HANDLE)
if ($ret -eq -1) {
throw "Error: cannot get stdout handle"
}
return $ret
}

function GetConInMode { #GetCOnsoleMode
$conin = GetConIn
$mode = 0
$ret = $WinAPI::GetConsoleMode($conin, [ref]$mode)
if ($ret -eq 0) {
throw "GetConsoleMode (in) failed (is stdin a console?)"
}
return $mode
}

function GetConOutMode {
$conout = GetConOut
$mode = 0
$ret = $WinAPI::GetConsoleMode($conout, [ref]$mode)
if ($ret -eq 0) {
throw "GetConsoleMode (out) failed (is stdout a console?)"
}
return $mode
}

function SetConInMode($mode) {
$conin = GetConIn
$ret = $WinAPI::SetConsoleMode($conin, $mode)
if ($ret -eq 0) {
throw "SetConsoleMode (in) failed (is stdin a console?)"
}
}

function SetConOutMode($mode) {
#$conout = GetConOut
# Different tack:
$conout = $hwnd
$ret = $WinAPI::SetConsoleMode($conout, $mode)
if ($ret -eq 0) {
throw "SetConsoleMode (out) failed (is stdout a console?)"
}
}

#----------------------------------------------------------
# MAIN
#----------------------------------------------------------
$oldInMode = GetConInMode
$oldOutMode = GetConOutMode

$newMode = $oldOutMode
$doit = $false

if ($PSBoundParameters.ContainsKey("Mode")) {
$newMode = $Mode
$doit = $true
}

if ($doit) {
echo "old (out) mode: 0x$($oldOutMode.ToString("x"))"
SetConOutMode $newMode
$newMode = GetConOutMode
echo "new (out) mode: 0x$($newMode.ToString("x"))"
} else {
echo "Console Input Mode (CONIN) : 0x$($oldInMode.ToString("x"))"
echo "Console Output Mode (CONOUT) : 0x$($oldOutMode.ToString("x"))"
}

所以在一天结束时,我想启用 ENABLE_VIRTUAL_TERMINAL_PROCESSING 对于控制台。

我为此使用的系统是:
---------------------------------------------------------
PowerShell Version : 6.1.1
OS Name : Microsoft Windows 8.1 (64-bit)
OS Version : 6.3.9600 [2018-11-16 00:50:01]
OS BuildLabEx : 9600.19179
OS HAL : 6.3.9600.18969
OS Kernel : 6.3.9600.18217
OS UBR : 19182
-------------------------------------------------------
with Privilege : Administrator
-------------------------------------------------------
ExecutionPolicy :
MachinePolicy : Undefined
UserPolicy : Undefined
Process : Undefined
CurrentUser : Undefined
LocalMachine : Bypass

Console Settings:
Type : ConsoleHost
OutputEncoding : Unicode (UTF-8)
Color Capability : 23
Registry VT Level : 1
CodePage (input) : 437
CodePage (output) : 437

我还启用了注册表项: HKCU:\Console\VirtualTerminalLevel ,按照其他地方的指示。

问: 如何使用 PowerShell 启用此位/标志?

我能想到的一些事情可能是错误的:
  • 我肯定对它的工作原理有错误的理解...
  • 我可能弄错了permissions写到控制台? (如何设置?)
  • 我可能不会写信给 correct输出缓冲区? (怎么找?)

    Note that setting the output mode of one screen buffer does not affect the output mode of other screen buffers.

  • 执行脚本时,可能会创建一个新的输出缓冲区? (怎么办?)
  • 我可能不得不create a new缓冲?
  • 我可能不得不create a new安慰?


  • 相关问题和链接:
  • ENABLE_VIRTUAL_TERMINAL_PROCESSING and DISABLE_NEWLINE_AUTO_RETURN failing
  • MSDN: Inside the Windows Console
  • MSDN: Introducing the Windows Pseudo Console - ConPty
  • 最佳答案

    我自己已经尝试了几天,并意识到了一些事情。显然 PowerShell 在启动时启用了虚拟终端处理。但是,它会在启动可执行文件时再次禁用它,然后在可执行文件退出时重新启用它。这意味着任何需要虚拟终端处理的可执行文件都必须启用它本身或通过启用它的包装程序调用,然后通过管道将 stdin/stdout/stderr 传递到终端。至于如何编写这样的程序,我不知道。

    关于powershell - 如何在 powershell 中使用 SetConsoleMode 更改控制台输出模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53753106/

    56 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com