获取 Windows 命令提示内容到文本文件
Getting a Windows command prompt contents to a text file
我想编写一个批处理实用程序来将命令提示符 window 的输出复制到一个文件中。我 运行 我的命令提示符 windows 最大深度为 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>
我的击键进入了命令提示符,所以大概我有正确的 window 重点 - 它似乎忽略了 Ctrl
和 Alt
修饰符。它还识别 Ctrl-C
但不识别 Ctrl-A
。因为它忽略了 Ctrl-A
到 select 的所有文本,所以 Ctrl-C 使批处理文件认为它看到了中断命令。
我看过像 this one 这样的其他答案,但它们都处理使用重定向的方法,而不是事后做的方法 "on demand".
* 更新 *
根据@dxiv 的指针,这里是例程的批处理包装器:
获取-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 例程与 link 中介绍的几乎相同,除了:
我必须对其进行清理以删除 select/copy/paste 操作引入的一些更有趣的字符替换。
原版也保存了尾随空格。那些现在被修剪了。
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()
可以使用评论中提到的 PowerShell 团队博客 Capture console screen 中的 PS 脚本检索控制台缓冲区的内容,现在编辑到 OP 的问题中。
最后一行也可以更改为将内容复制到剪贴板而不是返回它。
Set-Clipboard -Value $textBuilder.ToString()
附带说明一下,How does StringBuilder work internally in C# and How the StringBuilder class is implemented 中讨论了使用 StringBuilder
而不是直接串联的原因。
我想编写一个批处理实用程序来将命令提示符 window 的输出复制到一个文件中。我 运行 我的命令提示符 windows 最大深度为 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>
我的击键进入了命令提示符,所以大概我有正确的 window 重点 - 它似乎忽略了 Ctrl
和 Alt
修饰符。它还识别 Ctrl-C
但不识别 Ctrl-A
。因为它忽略了 Ctrl-A
到 select 的所有文本,所以 Ctrl-C 使批处理文件认为它看到了中断命令。
我看过像 this one 这样的其他答案,但它们都处理使用重定向的方法,而不是事后做的方法 "on demand".
* 更新 *
根据@dxiv 的指针,这里是例程的批处理包装器:
获取-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 例程与 link 中介绍的几乎相同,除了:
我必须对其进行清理以删除 select/copy/paste 操作引入的一些更有趣的字符替换。
原版也保存了尾随空格。那些现在被修剪了。
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()
可以使用评论中提到的 PowerShell 团队博客 Capture console screen 中的 PS 脚本检索控制台缓冲区的内容,现在编辑到 OP 的问题中。
最后一行也可以更改为将内容复制到剪贴板而不是返回它。
Set-Clipboard -Value $textBuilder.ToString()
附带说明一下,How does StringBuilder work internally in C# and How the StringBuilder class is implemented 中讨论了使用 StringBuilder
而不是直接串联的原因。