Как я могу передать вывод консоли прямо в Блокнот?

47

Я запускаю приложение в командной строке или в оболочке Git , и я хотел бы получить вывод в Блокнот, чтобы потом было легче просматривать и редактировать.

Я попробовал следующее, но я всегда получаю пустой экземпляр Блокнота:

diff file1.txt file2.txt | notepad

Я знаю, что могу перенаправить вывод в другой файл, а затем открыть файл в блокноте. Я хотел бы избежать дополнительного шага, потому что я просто привык использовать Vim или менее в системах, отличных от Windows.

Der Hochstapler
источник
2
Конечно, вы также можете подключиться к moreWindows.
Гейб
1
Почему бы не передать файл в файл, а просто запустить новый путь к файлу - пусть ОС обрабатывает презентационное приложение. Это должен быть блокнот?
Гусдор
@Gusdor Вопрос заключается прежде всего в том, чтобы избегать создания (временного) файла.
Der Hochstapler
1
Функциональность блокнота настолько ограничена, что с ним практически ничего не поделаешь. Поскольку вы знакомы vim, почему бы просто не установить его?
Сиюань Рен
@CR Я мог бы делать это на своих компьютерах, но я регулярно работаю на компьютерах, которые мне не принадлежат. Поэтому полезно знать, какие есть варианты, без установки стороннего программного обеспечения.
Der Hochstapler

Ответы:

63

Из того, что я могу сказать, нет никакого способа напрямую передать в Блокнот.

Тем не менее, вы можете вставитьclip и затем вставить в блокнот, например, так:

 diff file1.txt file2.txt | clip && notepad

Затем просто нажмите Ctrl+ Vв блокноте.

Der Hochstapler
источник
3
Будет ли это работать, если вы перенаправите вывод в file3.txt, а затем && notepad file3.txt?
Конерак
4
@Konerak Да, это сработало бы, и это именно то, чего я пытался избежать (как объяснено в вопросе);)
Der Hochstapler
32

Подумайте об использовании Vim или, в вашем случае, gVim, если вы предпочитаете графическое окружение.

Затем вы можете передать в него один дефис в качестве аргумента, который указывает Vim / gVim читать из стандартного ввода.

diff file1.txt file2.txt | gvim -
Бенджамин Гудэйкр
источник
1
установить его, блокнот действительно ограничен, вы не можете использовать его для этого. Вы даже можете иметь его в портативных приложениях: portableapps.com/apps/development/gvim_portable
higuita
3
Также можно сделать это изнутри vim::%!diff file1.txt file2.txt
SlightlyCuban
@TankorSmash Я тоже, но не в этом суть вопроса;) Для дальнейших обсуждений "за" и "против" относительно vim (или любой другой темы), пожалуйста, найдите меня в Super User Chat , темы комментариев не являются отличным способом для разговора :(
Der Hochstapler
1
@OliverSalzburg Я пытался предположить, что gvim доступен в Windows, так как я понял, что ваш комментарий означает, что это не так. Я ошибался.
TankorSmash
-часто используется для обозначения «читать из стандартного ввода», поэтому это не ограничивается vim. Другие редакторы используют -i(например kate).
Бакуриу
8

Вот небольшая программа для Windows, которая делает это правильно (без зазубрин буфера обмена). Он должен быть адаптирован к PowerShell, и я мог бы обновить этот ответ, если у меня будет время, но вы также можете просто использовать эту программу напрямую.

Ну, а как насчет PowerShell? Не нужно устанавливать другое приложение. К сожалению, вам будет нужно создать файл сценария в своем PATH...

Короткая версия, которую вы можете использовать

Если вы создадите командный файл (например ShowInNotepad.bat) со следующим содержимым и поместите его в свое PATHместо:

@echo off
clip
powershell -Command $process = Start-Process -PassThru notepad;$SW_SHOW = 5;$sig = '[DllImport("""user32.dll""")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);';Add-Type -MemberDefinition $sig -name NativeMethods -namespace Win32;[Win32.NativeMethods]::ShowWindow($process.Id, $SW_SHOW) ^| Out-Null;Add-Type -AssemblyName System.Windows.Forms;[System.Windows.Forms.SendKeys]::SendWait('^^V');

Вы можете просто позвонить echo blah | ShowInNotepadиз любой точки мира!

Обратите внимание , что это действительно предположить , что вы используете последнюю иш версию Windows (Vista +) и не отключили PowerShell или деинсталлировать рамки .NET. Другими словами, установка Windows по умолчанию будет работать.


Длительное объяснение и альтернативы

Самый простой способ, который я могу придумать, - это автоматизировать действие вставки ( Ctrl+ V). Что, по крайней мере, еще один ответ уже делает, но тот, который использует AHK - вам, возможно, повезет, если заставить PowerShell работать в закрытой корпоративной среде.

Давайте продолжим со сценарием, да?

#start notepad, get process object (to get pid later)
$process = Start-Process -PassThru notepad;

# activate Notepad window
# based on http://stackoverflow.com/a/4994020/1030702
# SW_SHOW activates and shows a window http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548%28v=vs.85%29.aspx
$SW_SHOW = 5;
$sig = '[DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);';
Add-Type -MemberDefinition $sig -name NativeMethods -namespace Win32;
[Win32.NativeMethods]::ShowWindow($process.Id, $SW_SHOW) | Out-Null;

# send a "Ctrl+V" keystroke to the active window
# from http://stackoverflow.com/a/17851491/1030702
Add-Type -AssemblyName System.Windows.Forms;
[System.Windows.Forms.SendKeys]::SendWait('^V');

Это довольно просто, поэтому я не буду объяснять сценарий больше, чем комментарии.

использование

Чтобы использовать его, вам просто нужно поместить скрипт в .ps1файл (например ShowInNotepad.ps1), поместить его где-то в вашем PATHи затем вызвать powershell ShowInNotepad.ps1после размещения текста, который вы хотите отобразить в буфере обмена.

Пример:

echo blah | clip && powershell ShowInNotepad.ps1

К сожалению, выполнение сценариев PowerShell иногда может быть затруднено (политики выполнения и все). Поэтому я сжал этот скрипт до одной строки, которую вы можете вызвать напрямую из командной строки или даже поместить в командный файл:

powershell -Command $process = Start-Process -PassThru notepad;$SW_SHOW = 5;$sig = '[DllImport("""user32.dll""")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);';Add-Type -MemberDefinition $sig -name NativeMethods -namespace Win32;[Win32.NativeMethods]::ShowWindow($process.Id, $SW_SHOW) ^| Out-Null;Add-Type -AssemblyName System.Windows.Forms;[System.Windows.Forms.SendKeys]::SendWait('^^V');

Если вы создадите командный файл (например ShowInNotepad.bat) со следующим содержимым и поместите его в свое PATHместо:

@echo off
clip
powershell -Command $process = Start-Process -PassThru notepad;$SW_SHOW = 5;$sig = '[DllImport("""user32.dll""")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);';Add-Type -MemberDefinition $sig -name NativeMethods -namespace Win32;[Win32.NativeMethods]::ShowWindow($process.Id, $SW_SHOW) ^| Out-Null;Add-Type -AssemblyName System.Windows.Forms;[System.Windows.Forms.SendKeys]::SendWait('^^V');

Вы можете просто позвонить echo blah | ShowInNotepadиз любой точки мира!

боб
источник
Честно говоря, если вы собираетесь написать сценарий PS, я бы просто создал файл с именем Guid в папке временных файлов и удалил его, когда закончил. Автоматизация пасты кажется слишком хрупкой (например, что если вы потеряете фокус в неподходящее время или что-то в этом роде)?
Кейси
@emodendroket К сожалению, когда вы пытаетесь форсировать потоковый ввод в программу, которая изначально не поддерживает его, ничто не является действительно чистым. Создание временного файла имеет свои (второстепенные) недостатки: на самом деле вы не получаете «новый файл», поэтому Saveвыход и изменение измененного поведения отличаются. Если не считать замены самого Блокнота или непосредственной вставки текста в его элемент управления для редактирования, других вариантов не так много. Конечно, у этого метода есть недостаток, заключающийся в том, что содержимое буфера обмена забивается (хотя в любом случае оно должно быть эфемерным). Я не думаю, что потеря внимания является серьезной проблемой; это ...
Боб
... крайне маловероятное состояние гонки (между ShowWindowи отправкой нажатий клавиш). И этот метод требует немного больше настройки (создание файла скрипта), да.
Боб
5

Как насчет использования AutoHotkey ?

Сохраните следующее как stdin.ahkи поместите его в каталог AutoHotkey:

StdIn(max_chars=0xfff)
{
    static hStdIn=-1
    ; The following is for vanilla compatibility
    ptrtype := (A_PtrSize = 8) ? "ptr" : "uint"

    if (hStdIn = -1)
    {
        hStdIn := DllCall("GetStdHandle", "UInt", -10,  ptrtype) ; -10=STD_INPUT_HANDLE
        if ErrorLevel
            return 0
    }

    max_chars := VarSetCapacity(text, max_chars*(!!A_IsUnicode+1), 0)

    ret := DllCall("ReadFile"
        ,  ptrtype, hStdIn        ; hFile
        ,  "Str", text          ; lpBuffer
        , "UInt", max_chars*(!!A_IsUnicode+1)     ; nNumberOfBytesToRead
        , "UInt*", bytesRead    ; lpNumberOfBytesRead
        ,  ptrtype, 0)            ; lpOverlapped

    return text
}

loop 
{
    sleep 100 ;wait for data
    Buffer:=StdIn()
    PipeText:=PipeText . Buffer
    IfWinActive Untitled - Notepad
        {
        SendInput {Raw}%PipeText%
        PipeText = 
        }
}

Тогда командная строка:

ping -t www.google.com | AutoHotkeyA32.exe stdin.ahk

Передает вывод команды в Блокнот, пока окно открыто и озаглавлено Untitled - Notepad. Если окно не активно, оно будет активно буферизоваться в фоновом режиме до тех пор, пока окно не станет активным. Вы даже можете перейти к другой программе, и она снова будет выполнять буферизацию.

Это, кажется, умирает, когда программа, выводящая на наш стандартный ввод, умирает ...

(Для информации, код stdin () был бесстыдно отсюда полдюйма )

Мокубай
источник
...Ух ты. Если вы собираетесь пойти до такой степени, можете написать целую скомпилированную программу! Вероятно, будет более эффективным: P Upvote за усилия, хотя.
Боб
Даунвот от меня боюсь. Гипер-инженерство в классическом смысле. Кто управляет версией этого скрипта? Нужна ли autohotkey лицензия для коммерческих приложений? Кто это контролирует?
Гусдор
7
@Gusdor Весь Интернет полон неконтролируемых фрагментов кода. У нас есть преимущество, даже если у нас есть история изменений для этого поста. Я также не понимаю, как коммерческое лицензирование как-то связано с этим вопросом? AHK используется многими людьми, и они могут найти этот ответ полезным.
slhck
@slhck Я просто заметил недостатки этого решения, а не его обоснованность.
Гусдор
@slhck: Контент на этом сайте защищен Creative Commons.
Брайан
4

Это вполне возможно; Я только что попробовал это. Я предполагаю, что Блокнот по умолчанию настроен на открытие текстовых файлов:

diff file1.txt file2.txt > output.txt && start output.txt && timeout /T 3 && del output.txt

Хорошо, вы технически создаете файл, но он не сохраняется.

Трубить больше - это тоже вариант.

Casey
источник
4
Будьте осторожны - если у вас уже есть это, output.txtэто загубит его. Предельно безопаснее было бы использовать %temp%/somerandomstring.txt.
Боб
Безопаснее сохранить выходной файл во временном каталоге - посмотрите на этот ответ.
Lu55
1

Вот уродливый, но эффективный способ сделать это:

$OutputString = 'Hello World'
$WScript = New-Object -ComObject 'wscript.shell'
$WScript.Run('notepad.exe') | Out-Null
do 
    {
    Start-Sleep -Milliseconds 100
    }
until ($WScript.AppActivate('notepad'))
$WScript.SendKeys($OutputString)

Только обязательно отправляйте только текстовые сообщения. Другие данные могут быть интерпретированы как управляющие символы (CTRL, ALT, DEL и т. Д.).

Шон
источник
0

Вот пара решений на основе VBScript, которые могут работать (хотя ... они полагаются на приложения, которые открываются вовремя):

pipe2key.vbs - открывает приложение, указанное в качестве первого аргумента, а затем отправляет StdIn как нажатия клавиш. Необходимо использовать с cscript.exe, так как wscript не обеспечивает доступ к StdIn. Вероятно, довольно медленно для длинных документов - но не будет загромождать буфер обмена

Set inPipe=wScript.StdIn
Set wShell=wScript.CreateObject("wscript.shell")
wShell.Run wScript.Arguments(0), 5 ' Execute specified app, foreground it's window
wScript.Sleep 500 ' Wait for app to load
KeysToEscape="{}[]()^+%"
KeysToDrop=vbLf
While Not inPipe.AtEndOfStream
    keyChar=inPipe.Read(1)
    If InStr(KeysToDrop, keyChar) = 0 Then
        If InStr(KeysToEscape, keyChar) > 0 Then
            wShell.SendKeys "{" & keyChar & "}"
        Else
            wShell.SendKeys keyChar
        End If
    End If
Wend

Пример использования: diff file1.txt file2.txt | cscript pipe2key.vbs notepad.exe

Или pasteinto.vbs. Автоматизирует операцию CTRL-V после запуска приложения (таким образом, используется команда «clip», как упоминалось в предыдущих ответах). Значительно быстрее и чище (на мой взгляд), чем pipe2key.vbs, но процесс перезапишет буфер обмена

Set wShell=wScript.CreateObject("wscript.shell")
wShell.Run wScript.Arguments(0), 5 ' Execute specified app, foreground it's window
wScript.Sleep 500 ' Wait for app to load
wShell.SendKeys "^v"

Пример использования: diff file1.txt file2.txt | clip && pasteinto notepad.exe

Джейсон Масгроув
источник
-1

Нечто подобное "может" работать.

О, ты не понимал, что это то, что ты будешь делать каждый раз вручную (по звукам этого). Возможно, вам удастся создать какой-то макрос или что-то подобное, чтобы ускорить процесс. Не уверен в этом.

diff file1.txt file2.txt > file.txt | sleep 1 | notepad.exe file.txt | rm file.txt

Это должно было бы закончить запись содержимого diff в файл file.txt, чтобы загрузить всю операцию diff, что я не уверен, будет ли это выполнено. В таком случае может быть способ сделать паузу между операциями канала.

Codezilla
источник
5
Цель состоит в том, чтобы не создавать временный файл, и я уверен, что там что-то не так с вашим синтаксисом;)
Der Hochstapler
«для облегчения просмотра и редактирования позже» я подумал, что это то, что вы хотели? И, как указано и исправлено в Rev1.0, это работает. Это для дос, однако, я не уверен, что Cygwin будет иметь те же результаты.
Codezilla
3
Я думаю, потому что & было бы достаточно, так как на самом деле ничего не должно быть «передано» между этими вызовами.
Rev 1.0
3
@ Rev1.0 Правильно. &, &&И ||операторы в цепи команд вместе. Все 3 ведут себя по-разному, если они генерируют возвращаемое значение, отличное от 0. |совершенно иной , как она используется для труб выхода из одной программы в другую. Результатом может быть то, что вы хотели, но использование одного из операторов цепочки делает намерение более ясным, потому что в этом примере не требуется фактический конвейер. Для дополнительной справки: microsoft.com/resources/documentation/windows/xp/all/proddocs/…
Der Hochstapler
1
@Codezilla Я думаю, что идея в моем посте очень похожа на вашу, но это правильный синтаксис командной строки.
Кейси
-3

Мой язык не английский, так что извините за ошибки.

Я думаю, что вы не можете напрямую поместить вывод в открытый блокнот. Может быть, я ошибаюсь по этому поводу. Вы должны создать файл с выводом, чтобы работать с ним. Команда tee может передать вывод двум или может быть несколькими командами или файлами одновременно.

человек тройник

Не забудьте использовать >> вместо> при перенаправлении вывода в файл. > Перезапишет файл, >> добавит вывод после того, что уже есть в этом файле.

user338167
источник
1
teeобычно недоступен в Windows, и даже если бы он был, это не помогло бы решить эту проблему.
Der Hochstapler
-4

Вы не можете, Блокнот слишком ограничен для этого! А еще лучше ... установить Cygwin и обойти все это "отсутствие функций" Windows. Затем вы можете использовать команду, которую вы уже знаете.

AFAIK, очень немногие программы для Windows поддерживают конвейерную обработку, еще хуже для программ с графическим интерфейсом.

Вы можете попытаться открыть запросы функций в одной из программ «хвоста Windows», чтобы добавить это.

Игиты
источник
2
Я уже использую Cygwin. Это действительно проблема, специфичная для взаимодействия с Блокнотом.
Der Hochstapler
1
@emodendroket иногда люди используют неправильный инструмент для работы ... и почти в любом случае блокнот - это неправильный инструмент, он настолько прост и ограничен :)
higuita
1
@higuita Я - преданный пользователь Emacs, но иногда Блокнот - лучший инструмент для того, что я хочу сделать.
Кейси