Jak przesłać dane wyjściowe konsoli bezpośrednio do Notatnika?

47

Korzystam z aplikacji w wierszu polecenia lub powłoki Git i chciałbym pobrać dane wyjściowe do Notatnika, aby ułatwić ich późniejsze przejrzenie i edycję.

Próbowałem następujących czynności, ale zawsze otrzymuję pustą instancję Notatnika:

diff file1.txt file2.txt | notepad

Wiem, że mogę przekierować dane wyjściowe do innego pliku, a następnie otworzyć plik w Notatniku. Chciałbym uniknąć dodatkowego kroku, ponieważ jestem przyzwyczajony do pipowania do Vima lub mniej w systemach innych niż Windows.

Der Hochstapler
źródło
2
Oczywiście możesz również przesyłać do moreWindowsa.
Gabe
1
Dlaczego nie potokować do pliku i po prostu wykonać nową ścieżkę do powłoki - pozwól systemowi operacyjnemu obsłużyć aplikację prezentacji. Czy to musi być notatnik?
Gusdor
@Gusdor Pytanie dotyczy przede wszystkim unikania tworzenia (tymczasowego) pliku.
Der Hochstapler
1
Funkcjonalność Notatnika jest tak ograniczona, że ​​prawie nic z nim nie możesz zrobić. Skoro jesteś obeznany vim, dlaczego po prostu go nie zainstalować?
Siyuan Ren,
@CR Mógłbym to zrobić na własnych komputerach, ale regularnie pracuję na komputerach, których nie posiadam. Warto wiedzieć, jakie są dostępne opcje bez instalowania oprogramowania innych firm.
Der Hochstapler

Odpowiedzi:

63

Z tego, co mogę powiedzieć, nie ma sposobu na bezpośrednie podłączenie do Notatnika.

Możesz jednak potokować do notatnika, clipa następnie wklejać go w następujący sposób:

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

Następnie naciśnij Ctrl+ Vw Notatniku.

Der Hochstapler
źródło
3
Czy zadziałałoby, gdybyś przekierował dane wyjściowe do pliku file3.txt, a następnie && notepad file3.txt?
Konerak
4
@Konerak Tak, to by zadziałało i właśnie tego chciałem uniknąć (jak wyjaśniono w pytaniu);)
Der Hochstapler
32

Rozważ użycie Vima lub, w twoim przypadku, gVim, jeśli wolisz środowisko graficzne.

Możesz następnie potokować do niego za pomocą pojedynczego łącznika jako argumentu, który instruuje Vim / gVim, aby czytał ze standardowego wejścia.

diff file1.txt file2.txt | gvim -
Benjamin Goodacre
źródło
1
zainstaluj, Notatnik jest naprawdę ograniczony, nie możesz go do tego użyć. możesz go nawet mieć w aplikacjach przenośnych
higuita
3
Można to również zrobić z poziomu vima::%!diff file1.txt file2.txt
SlightlyCuban
@TankorSmash Ja też, ale nie o to chodzi w pytaniu;) W przypadku dalszych dyskusji pro i con dotyczących vim (lub jakiegokolwiek innego tematu), znajdź mnie na Super User Chat , wątki komentarzy nie są świetnym sposobem na rozmowę :(
Der Hochstapler
1
@OliverSalzburg Próbowałem zasugerować, że gvim jest dostępny w systemie Windows, ponieważ zrozumiałem, że twój komentarz oznacza, że ​​nie był. Myliłem się.
TankorSmash
-jest często używane w znaczeniu „czytać ze standardowego wejścia”, więc nie jest to ściśle ograniczone do vim. Inni redaktorzy używają -i(np kate.).
Bakuriu
8

oto krótki program systemu Windows, który robi to poprawnie (bez blokowania schowka). Powinien być przystosowany do programu PowerShell i mogę zaktualizować tę odpowiedź, jeśli będę mieć czas, ale możesz również użyć tego programu bezpośrednio.

A co powiesz na PowerShell? Nie ma potrzeby instalowania innej aplikacji. Niestety, będzie trzeba utworzyć plik skryptu gdzieś w twojej PATH...

Krótka wersja, której możesz użyć

Jeśli utworzysz plik wsadowy (np. ShowInNotepad.bat) Z następującą zawartością i umieścisz go PATHgdzieś:

@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');

możesz wtedy zadzwonić echo blah | ShowInNotepadz dowolnego miejsca!

Należy pamiętać, że to nie zakładamy, że używasz najnowszej-owski wersji systemu Windows Vista (+) i nie niepełnosprawnej PowerShell lub odinstalowane .NET Framework. Innymi słowy, będzie działać domyślna instalacja systemu Windows.


Długie wyjaśnienie i alternatywy

Najłatwiejszym sposobem jest zautomatyzowanie operacji wklejania ( Ctrl+ V). Która co najmniej jedna odpowiedź już działa, ale ta korzysta z AHK - możesz mieć więcej szczęścia, jeśli PowerShell będzie działał w zamkniętym środowisku korporacyjnym.

Przejdźmy do scenariusza, tak?

#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');

Jest to dość proste, więc nie będę zawracał sobie głowy wyjaśnianiem skryptu bardziej niż komentarze.

Stosowanie

Aby go użyć, wystarczy umieścić skrypt w .ps1pliku (np. ShowInNotepad.ps1), Umieścić go gdzieś w swoim, PATHa następnie wywołać powershell ShowInNotepad.ps1po umieszczeniu tekstu, który chcesz wyświetlić w schowku.

Przykład:

echo blah | clip && powershell ShowInNotepad.ps1

Niestety wykonywanie skryptów PowerShell może być czasami trudne (zasady wykonywania i wszystkie inne). Dlatego skondensowałem ten skrypt do jednowierszowego, który można wywołać bezpośrednio z wiersza polecenia, a nawet umieścić w pliku wsadowym:

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');

Jeśli utworzysz plik wsadowy (np. ShowInNotepad.bat) Z następującą zawartością i umieścisz go PATHgdzieś:

@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');

możesz wtedy zadzwonić echo blah | ShowInNotepadz dowolnego miejsca!

Kok
źródło
Szczerze mówiąc, jeśli masz zamiar napisać skrypt PS, po prostu utworzę plik z nazwą Guid w folderze plików tymczasowych i usunę go, gdy skończę. Automatyzacja wklejania wydaje się zbyt krucha (na przykład, jeśli stracisz koncentrację w niewłaściwym czasie lub coś takiego)?
Casey
@emodendroket Niestety, kiedy próbujesz wymusić wejście strumienia do programu, który nie obsługuje go natywnie, nic nie jest naprawdę czyste. Tworzenie pliku tymczasowego ma swoje (drobne) wady: w rzeczywistości nie dostajesz „nowego pliku”, więc zmiany Savezachowań i wyjścia są inne. Oprócz zastąpienia samego Notatnika lub bezpośredniego wstrzykiwania tekstu do kontrolki edycji, nie ma wielu innych opcji. Oczywiście ta metoda ma wadę polegającą na zapychaniu zawartości schowka (choć i tak powinny one być efemeryczne). Nie sądzę, żeby utrata koncentracji była poważnym problemem; to jest ...
Bob
... bardzo mało prawdopodobny stan wyścigu (między ShowWindownaciśnięciem klawisza a wysłaniem). I ta metoda wymaga nieco więcej konfiguracji (tworzenia pliku skryptu) do użycia, tak.
Bob
5

Co powiesz na używanie AutoHotkey ?

Zapisz następujące stdin.ahki umieść w katalogu 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 = 
        }
}

Następnie wiersz poleceń:

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

Przesyła dane wyjściowe polecenia do Notatnika, o ile okno jest otwarte i nosi tytuł Untitled - Notepad. W przypadku, gdy okno nie jest aktywne, wesoło buforuje w tle, dopóki okno nie będzie aktywne. Możesz nawet przejść do innego programu, który ponownie będzie buforował.

Wydaje się, że to umiera, gdy umiera program wyjściowy na nasze standardowe wejście ...

(Dla informacji kod stdin () został bezwstydnie w połowie wprowadzony tutaj )

Mokubai
źródło
...łał. Jeśli masz zamiar przejść w tym zakresie, równie dobrze możesz napisać cały skompilowany program! Prawdopodobnie też będzie bardziej wydajny: P Upvote za wysiłek.
Bob
Głosujcie za mną, boję się. Nadmierna inżynieria w sensie klasycznym. Kto kontroluje wersję tego skryptu? Czy autohotkey wymaga licencji na aplikacje komercyjne? Kto to monitoruje?
Gusdor
7
@Gusdor Cały Internet jest pełen niekodowanych fragmentów kodu. Mamy tę zaletę, że mamy nawet historię zmian tego postu. Nie rozumiem też, w jaki sposób licencje komercyjne mają coś wspólnego z tym pytaniem? AHK jest używany przez wiele osób, które mogą uznać tę odpowiedź za przydatną.
slhck
@slhck Po prostu zwracałem uwagę na pułapki tego rozwiązania, a nie na jego ważność.
Gusdor
@slhck: Treści na tej stronie są objęte licencją Creative Commons.
Brian
4

Jest to całkowicie możliwe; Właśnie tego spróbowałem. Zakładam, że Notatnik jest domyślnie ustawiony na otwieranie plików txt:

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

OK, technicznie tworzysz plik, ale nie jest on zapisywany.

Pipowanie w więcej jest również opcją.

Casey
źródło
4
Uważaj - jeśli już go masz, output.txtto go zablokuje. Byłoby marginalnie bezpieczniejsze %temp%/somerandomstring.txt.
Bob
Bezpieczniej jest zapisać plik wyjściowy w katalogu tymczasowym - spójrz na odpowiedź.
Lu55
1

Oto brzydki, ale skuteczny sposób na osiągnięcie tego:

$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)

Tylko pamiętaj, aby wysłać tylko tekst. Inne dane będą potencjalnie interpretowane jako znaki kontrolne (CTRL, ALT, DEL itp.).

Sean
źródło
0

Oto kilka rozwiązań opartych na VBScript, które mogą działać (choć .. polegają trochę na aplikacjach otwieranych na czas):

pipe2key.vbs - otwiera aplikację określoną jako pierwszy argument, a następnie wysyła do niej StdIn jako naciśnięcia klawiszy. Musi być używany z cscript.exe, ponieważ wscript nie zapewnia dostępu StdIn. Prawdopodobnie dość długie w przypadku długich dokumentów - ale nie zapycha schowka

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

Przykładowe użycie: diff file1.txt file2.txt | cscript pipe2key.vbs notepad.exe

Lub pasteinto.vbs. Automatyzuje działanie CTRL-V po uruchomieniu aplikacji (w ten sposób używa polecenia „clip”, jak wspomniano w poprzednich odpowiedziach). Znacznie szybszy i czystszy (moim zdaniem) niż pipe2key.vbs, ale proces zastąpi schowek

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"

Przykładowe użycie: diff file1.txt file2.txt | clip && pasteinto notepad.exe

Jason Musgrove
źródło
-1

Coś takiego „może” zadziałać.

Aw, nie zdawałeś sobie sprawy, że robisz to ręcznie za każdym razem (z dźwięków tego). Możesz za każdym razem zrobić coś w rodzaju makra lub zrobić coś takiego, aby przyspieszyć proces. Nie jestem tego pewien.

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

Musiałby zakończyć zapisywanie zawartości pliku diff do pliku.txt, aby załadować całą operację porównania, czego nie jestem pewien, czy to zrobi. W takim przypadku może istnieć sposób na przerwanie między operacją potoku.

Codezilla
źródło
5
Chodzi o to, aby nie utworzyć pliku tymczasowego i jestem pewien, że coś jest nie tak z twoją składnią;)
Der Hochstapler
„dla łatwiejszego przeglądu i edycji później” Pomyślałem, że tego właśnie chcesz? I jak wskazano i poprawiono do Rev1.0, to działa. Jednak nie jestem pewien, czy cygwin miałby takie same wyniki.
Codezilla
3
Chyba dlatego, że & byłby odpowiedni, ponieważ tak naprawdę nic nie trzeba „potokować” między tymi połączeniami.
Rev 1.0
3
@ Rev1.0 Prawidłowe. &, &&I ||są operatorom poleceń łańcucha razem. Wszystkie 3 zachowują się inaczej, jeśli komenda generuje inną niż 0 wartość zwracaną. |jest całkowicie różny, jak to jest stosowane do rur wyjściu z jednego programu do drugiego. Wynik może być taki, jaki chciałeś, ale użycie jednego z operatorów łańcuchowych czyni intencję bardziej zrozumiałą, ponieważ w tym przykładzie nie jest pożądane faktyczne orurowanie. Dodatkowe informacje: microsoft.com/resources/documentation/windows/xp/all/proddocs/…
Der Hochstapler
1
@Codezilla Myślę, że pomysł w moim poście jest dość podobny do twojego, ale jest to poprawna składnia wiersza poleceń.
Casey
-3

Mój język nie jest angielski, więc przepraszam za błędy.

Myślę, że nie możesz bezpośrednio umieścić danych wyjściowych w otwartym Notatniku. Może się mylę co do tego. Musisz stworzyć plik z danymi wyjściowymi, aby nad nim pracować. Trójnik poleceń może przesyłać dane wyjściowe do dwóch lub może być więcej poleceń lub plików w tym samym czasie.

koszulka męska

Nie zapomnij użyć >> zamiast>, gdy ponownie wykorzystasz dane wyjściowe do pliku. > Nadpisze plik, >> doda wynik po tym, co już ma w tym pliku.

użytkownik338167
źródło
1
teezazwyczaj nie jest dostępny w systemie Windows i nawet gdyby tak było, nie pomogłoby to z tym problemem.
Der Hochstapler
-4

Nie możesz, Notatnik jest na to zbyt ograniczony! Jeszcze lepiej ... zainstaluj Cygwin i obejdź ten „brak funkcji” systemu Windows. Następnie możesz użyć polecenia, które już znasz.

AFAIK, bardzo niewiele programów Windows obsługuje potokowanie, jeszcze gorzej w przypadku programów GUI.

Możesz spróbować otworzyć żądania funkcji w jednym z programów „Windows tail”, aby je dodać.

higuita
źródło
2
Już używam cygwina. To jest naprawdę problem specyficzny dla interakcji z Notatnikiem.
Der Hochstapler
1
@ emodendroket czasami ludzie używają niewłaściwego narzędzia do pracy ... i prawie w każdym przypadku notatnik jest niewłaściwym narzędziem, jest tak prosty i ograniczony :)
higuita
1
@higuita Jestem oddanym użytkownikiem Emacsa, ale czasami Notatnik jest lepszym narzędziem do tego, co chcę robić.
Casey