Я хочу написать пакетную утилиту для копирования вывода окна командной строки в файл. Я запускаю окна командной строки с максимальной глубиной 9999 строк, и иногда мне нужно получить вывод команды, вывод которой находится за пределами экрана. Я могу сделать это вручную с помощью клавиш Ctrl-A
, Ctrl-C
, а затем вставить результат в блокнот — я просто хочу автоматизировать это в пакетном файле с вызовом:
SaveScreen <text file name>
Я знаю, что могу сделать это с перенаправлением, но для этого нужно знать, что мне нужно заранее сохранить вывод последовательности пакетных команд.
Итак, если бы у меня был пакетный скрипт:
call BuildPhase1.bat
if "%ErrorLevel% gtr 0 goto :ErrorExit
call BuildPhase2.bat
if "%ErrorLevel% gtr 0 goto :ErrorExit
call BuildPhase3.bat
if "%ErrorLevel% gtr 0 goto :ErrorExit
Я мог бы написать:
cls
call BuildPhase1.bat
if "%ErrorLevel% gtr 0 call SaveScreen.bat BuildPhase1.err & goto :ErrorExit
call BuildPhase2.bat
if "%ErrorLevel% gtr 0 call SaveScreen.bat BuildPhase2.err & goto :ErrorExit
call BuildPhase3.bat
if "%ErrorLevel% gtr 0 call SaveScreen.bat BuildPhase3.err & goto :ErrorExit
или я могу просто набрать SaveScreen batch.log
, когда увижу, что запуск не удался.
Мои эксперименты завели меня так далеко:
<!-- : Begin batch script
@cscript //nologo "%~f0?.wsf" //job:JS
@exit /b
----- Begin wsf script --->
<package>
<job id="JS">
<script language="JScript">
var oShell = WScript.CreateObject("WScript.Shell");
oShell.SendKeys ("hi folks{Enter}") ;
oShell.SendKeys ("^A") ; // Ctrl-A (select all)
oShell.SendKeys ("^C") ; // Ctrl-C (copy)
oShell.SendKeys ("% ES") ; // Alt-space, E, S (select all via menu)
oShell.SendKeys ("% EY") ; // Alt-space, E, Y (copy via menu)
// ... invoke a notepad session, paste the clipboard into it, save to a file
WScript.Quit () ;
</script>
</job>
</package>
Мои нажатия клавиш попадают в командную строку, поэтому, по-видимому, я сфокусировал правильное окно - кажется, что оно просто игнорирует модификаторы Ctrl
и Alt
. Он также распознает Ctrl-C
, но не Ctrl-A
. Поскольку он проигнорировал Ctrl-A
для выбора всего текста, Ctrl-C заставляет пакетный файл думать, что он видел команду разрыва.
Я видел другие ответы, такие как этот, но все они имеют дело с методами, использующими перенаправление, а не способ сделать это постфактум «по требованию».
* ОБНОВЛЕНИЕ *
На основе указателя @dxiv вот пакетная оболочка для подпрограммы:
Get-ConsoleAsText.bat
:: save the contents of the screen console buffer to a disk file.
@set "_Filename=%~1"
@if "%_Filename%" equ "" @set "_Filename=Console.txt"
@powershell Get-ConsoleAsText.ps1 >"%_Filename%"
@exit /b 0
Процедура Powershell почти такая же, как была представлена в ссылке, за исключением того, что:
Мне пришлось очистить его, чтобы удалить некоторые из наиболее интересных замен символов, введенных операцией выбора/копирования/вставки.
Оригинал также сохранил конечные пробелы. Те сейчас обрезаны.
Get-ConsoleAsText.ps1
# Get-ConsoleAsText.ps1 (based on: https://devblogs.microsoft.com/powershell/capture-console-screen/)
#
# The script captures console screen buffer up to the current cursor position and returns it in plain text format.
#
# Returns: ASCII-encoded string.
#
# Example:
#
# $textFileName = "$env:temp\ConsoleBuffer.txt"
# .\Get-ConsoleAsText | out-file $textFileName -encoding ascii
# $null = [System.Diagnostics.Process]::Start("$textFileName")
#
if ($host.Name -ne 'ConsoleHost') # Check the host name and exit if the host is not the Windows PowerShell console host.
{
write-host -ForegroundColor Red "This script runs only in the console host. You cannot run this script in $($host.Name)."
exit -1
}
$textBuilder = new-object system.text.stringbuilder # Initialize string builder.
$bufferWidth = $host.ui.rawui.BufferSize.Width # Grab the console screen buffer contents using the Host console API.
$bufferHeight = $host.ui.rawui.CursorPosition.Y
$rec = new-object System.Management.Automation.Host.Rectangle 0,0,($bufferWidth - 1),$bufferHeight
$buffer = $host.ui.rawui.GetBufferContents($rec)
for($i = 0; $i -lt $bufferHeight; $i++) # Iterate through the lines in the console buffer.
{
$Line = ""
for($j = 0; $j -lt $bufferWidth; $j++)
{
$cell = $buffer[$i,$j]
$line = $line + $cell.Character
}
$line = $line.trimend(" ") # remove trailing spaces.
$null = $textBuilder.Append($line)
$null = $textBuilder.Append("`r`n")
}
return $textBuilder.ToString()
PSHostRawUserInterface.GetBufferContents
получает весь буфер независимо от того, что видно в окне консоли. И это работает на консоли хоста, которая может быть командной строкой, не обязательно собственной консолью PowerShell. - person dxiv   schedule 03.05.2020Ctrl-A
,Ctrl-V
иCtrl-C
работали, необходимо изменить свойства (или значения по умолчанию для постоянного изменения). Вкладка «Параметры», отметьтеEnable Ctrl key Shortcuts
в параметрах редактирования. - person Stephan   schedule 03.05.2020