Comment canaliser la sortie de la console directement vers le Bloc-notes?

47

J'exécute une application à l'invite de commande ou dans un shell Git et j'aimerais importer le résultat dans Notepad afin de pouvoir le consulter et le modifier ultérieurement.

J'ai essayé ce qui suit, mais je reçois toujours une instance vide du Bloc-notes:

diff file1.txt file2.txt | notepad

Je suis conscient que je peux rediriger la sortie vers un autre fichier, puis l'ouvrir dans le Bloc-notes. J'aimerais éviter cette étape supplémentaire, car je suis juste habitué à utiliser Vim ou moins sur des systèmes autres que Windows.

Der Hochstapler
la source
2
Bien sûr, vous pouvez également utiliser moreWindows.
Gabe
1
Pourquoi ne pas diriger vers un fichier et exécuter simplement le nouveau chemin du fichier en mode shell - laissez le système d'exploitation gérer l'application de présentation. Est - ce qu'il a à être bloc - notes?
Gusdor
@Gusdor La question concerne principalement d'éviter de créer un fichier (temporaire).
Der Hochstapler le
1
Les fonctionnalités du Bloc-notes sont tellement limitées que vous ne pouvez pratiquement plus rien en faire. Puisque vous êtes familier avec vim, pourquoi ne pas l'installer?
Siyuan Ren
@CR Je pourrais le faire sur mes propres ordinateurs, mais je travaille régulièrement sur des ordinateurs que je ne possède pas. Il est donc utile de connaître les options disponibles sans installer de logiciel tiers.
Der Hochstapler

Réponses:

63

D'après ce que je peux dire, il n'y a aucun moyen d'entrer directement dans Notepad.

Cependant, vous pouvez diriger clipet coller dans le bloc-notes, comme suit:

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

Ensuite, appuyez simplement sur Ctrl+ Vdans le Bloc-notes.

Der Hochstapler
la source
3
Cela fonctionnerait-il si vous redirigiez la sortie vers file3.txt, et ensuite && notepad file3.txt?
Konerak
4
@Konerak Oui, cela fonctionnerait et c'est exactement ce que j'essayais d'éviter (comme expliqué dans la question);)
Der Hochstapler
32

Pensez à utiliser Vim ou, dans votre cas, gVim si vous préférez un environnement graphique.

Vous pouvez ensuite y accéder avec un seul trait d'union comme argument, ce qui indique à Vim / gVim de lire à partir de l'entrée standard.

diff file1.txt file2.txt | gvim -
Benjamin Goodacre
la source
1
Installez-le, le bloc-notes est vraiment limité, vous ne pouvez pas l'utiliser pour cela. vous pouvez même l'avoir dans des applications portables
higuita
3
Peut également le faire depuis vim::%!diff file1.txt file2.txt
SlightlyCuban, le
@TankorSmash Alors moi aussi, mais ce n'est pas le but de la question;) Pour les discussions plus ou moins favorables à propos de vim (ou de tout autre sujet), retrouvez-moi sur le chat Super User , les commentaires ne sont pas un excellent moyen d'avoir une conversation. :(
Der Hochstapler
1
@OliverSalzburg J'essayais de suggérer que gvim est disponible sur Windows, car j'ai compris que votre commentaire voulait dire que ce n'était pas le cas. J'avais tort.
TankorSmash
-est souvent utilisé pour signifier "lu à partir de stdin", donc ce n’est pas strictement limité à vim. D'autres éditeurs utilisent -i(par exemple kate).
Bakuriu
8

voici un petit programme Windows qui le fait correctement (sans entraver le presse-papier). Il devrait être adaptable à PowerShell, et je pourrais mettre à jour cette réponse si le temps me le permet, mais vous pouvez également utiliser ce programme directement.

Eh bien, qu'en est-il de PowerShell? Pas besoin d'installer une autre application. Malheureusement, vous aurez besoin de créer un endroit de fichier script dans votre PATH...

Version courte que vous pouvez utiliser

Si vous créez un fichier de commandes (par exemple ShowInNotepad.bat) avec le contenu suivant et le placez PATHquelque part:

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

vous pouvez alors appeler echo blah | ShowInNotepadde n'importe où!

Notez que cela ne suppose que vous utilisez une version récente de Windows ish (Vista +) et pas désactivé PowerShell ou désinstaller le framework .NET. En d'autres termes, une installation Windows par défaut fonctionnera.


Longue explication et alternatives

Le moyen le plus simple auquel je puisse penser est d'automatiser l'action de collage ( Ctrl+ V). Au moins une autre réponse est déjà en cours, mais celle-ci utilise AHK - vous auriez peut-être plus de chance que PowerShell fonctionne dans un environnement d'entreprise verrouillé.

Passons au script, oui?

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

C'est assez simple, je ne vais donc pas m'expliquer le script plus que ne le font déjà les commentaires.

Usage

Pour l'utiliser, il vous suffit de placer le script dans un .ps1fichier (par exemple ShowInNotepad.ps1), de le placer quelque part dans votre PATH, puis d'appeler powershell ShowInNotepad.ps1après avoir placé le texte que vous souhaitez afficher dans le Presse-papiers.

Exemple:

echo blah | clip && powershell ShowInNotepad.ps1

Malheureusement, il peut parfois être difficile d’exécuter des scripts PowerShell (règles d’exécution, etc.). Par conséquent, j'ai condensé ce script en une ligne que vous pouvez appeler directement à partir de l'invite de commande, ou même placer dans un fichier de traitement par lots:

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

Si vous créez un fichier de commandes (par exemple ShowInNotepad.bat) avec le contenu suivant et le placez PATHquelque part:

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

vous pouvez alors appeler echo blah | ShowInNotepadde n'importe où!

Bob
la source
Honnêtement, si vous allez écrire un script PS, je créerais simplement un fichier avec un nom Guid dans le dossier de fichiers temporaire et le supprimerais lorsque j'aurais terminé. L'automatisation de la pâte semble trop fragile (comme ce qui se passe si vous perdez la mise au point au mauvais moment ou à un moment quelconque)?
Casey
@emodendroket Malheureusement, lorsque vous essayez de forcer l'entrée de flux dans un programme qui ne le prend pas en charge de manière native, rien n'est vraiment propre. La création d'un fichier temporaire a ses propres inconvénients (mineurs): vous n'obtenez pas réellement de "nouveau fichier", de sorte que les Savecomportements de modification et de sortie sont différents. À part de remplacer le Bloc-notes lui-même ou d'injecter directement le texte dans son contrôle d'édition, il n'y a pas beaucoup d'autres options. Bien sûr, cette méthode a l’inconvénient d’empiéter sur le contenu du presse-papier (même s’il est supposé de toute façon être éphémère). Je ne pense pas que perdre le focus soit un problème majeur; c'est un ...
Bob
... condition de course extrêmement improbable (entre la ShowWindowfrappe et la frappe d'envoi). Et cette méthode nécessite un peu plus de configuration (création du fichier de script) à utiliser, oui.
Bob
5

Que diriez-vous d'utiliser AutoHotkey ?

Enregistrez les éléments suivants sous stdin.ahket placez-les dans votre répertoire 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 = 
        }
}

Puis la ligne de commande:

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

Transmet le résultat de la commande dans le Bloc-notes, tant que la fenêtre est ouverte et intitulée Untitled - Notepad. Si la fenêtre n’est pas active, elle se mettra volontiers en arrière-plan jusqu’à ce que la fenêtre soit active. Vous pouvez même vous en aller à un autre programme et celui-ci continuera une fois de plus.

Cela semble mourir lorsque le programme qui sort de notre entrée standard meurt cependant ...

(Pour information, le code stdin () était ici sans vergogne . )

Mokubai
la source
...sensationnel. Si vous voulez en arriver là, écrivez tout un programme compilé! Probablement plus efficace aussi: P vote positif pour l’effort.
Bob
Downvote de moi j'ai peur. Suringénierie au sens classique. Qui contrôle la version de ce script? Autohotkey a-t-il besoin d'une licence pour les applications commerciales? Qui surveille ça?
Gusdor
7
@Gusdor L'Internet entier est plein d'extraits de code non contrôlés par la version. Nous avons même l'avantage d'avoir un historique de révision pour ce post. Je ne vois pas non plus comment les licences commerciales ont un lien avec cette question? AHK est utilisé par beaucoup de gens et ils pourraient trouver cette réponse utile.
Slhck
@slhck Je ne faisais que remarquer les pièges de cette solution, pas sa validité.
Gusdor
@slhck: le contenu de ce site est couvert par Creative Commons.
Brian
4

C'est totalement possible. Je viens d'essayer. Je suppose que Notepad est configuré pour ouvrir les fichiers txt par défaut:

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

D'accord, vous créez techniquement un fichier, mais il n'est pas enregistré.

Piping en plus est également une option.

Casey
la source
4
Faites attention - si vous en avez déjà un, output.txtcela le gênera. Marginalement plus sûr serait d'utiliser %temp%/somerandomstring.txt.
Bob le
Il est plus sûr de sauvegarder un fichier de sortie dans le répertoire temporaire - jetez un oeil à cette réponse.
Lu55
1

Voici un moyen laid, mais efficace pour y parvenir:

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

Assurez-vous d’envoyer uniquement une sortie texte. D'autres données seront potentiellement interprétées comme des caractères de contrôle (CTRL, ALT, DEL, etc.).

Sean
la source
0

Voici quelques solutions basées sur VBScript qui peuvent fonctionner (bien que .. elles reposent un peu sur les applications qui s'ouvrent à temps):

pipe2key.vbs - ouvre l’application spécifiée comme premier argument, puis envoie StdIn au clavier. Doit être utilisé avec cscript.exe car wscript ne fournit pas d'accès StdIn. Probablement assez lent pour les longs documents - mais n'empiétera pas le presse-papiers

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

Exemple d'utilisation: diff file1.txt file2.txt | cscript pipe2key.vbs notepad.exe

Ou, pasteinto.vbs. Automatise l'opération CTRL-V après le lancement d'une application (utilise donc la commande "clip" comme indiqué dans les réponses précédentes). Beaucoup plus rapide et plus propre (à mon avis) que pipe2key.vbs, mais le processus écrasera le presse-papiers

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"

Exemple d'utilisation: diff file1.txt file2.txt | clip && pasteinto notepad.exe

Jason Musgrove
la source
-1

Quelque chose comme ça "pourrait" fonctionner.

Aw, vous n'avez pas réalisé que c'est quelque chose que vous feriez manuellement à chaque fois (d'après le son). Vous pourrez peut-être créer une sorte de macro ou quelque chose à faire pour vous à chaque fois pour accélérer le processus. Pas sûr sur celui-là.

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

Il faudrait terminer l'écriture du contenu du fichier diff dans fichier.txt pour pouvoir charger l'intégralité de l'opération diff, ce que je ne suis pas sûr de pouvoir faire. Il pourrait y avoir un moyen de faire une pause d'une manière ou d'une autre entre l'opération de conduite si tel est le cas.

Codezilla
la source
5
Le but est de ne pas créer de fichier temporaire et je suis presque sûr qu'il y a quelque chose qui cloche dans votre syntaxe ici;)
Der Hochstapler
"pour faciliter la révision et l'édition plus tard" J'ai pensé que c'était ce que tu voulais? Et comme Rev1.0 l'a signalé et modifié, cela fonctionne. C'est pour dos cependant, je ne suis pas sûr si cygwin aurait les mêmes résultats.
Codezilla
3
Je suppose que parce que & serait suffisant car en réalité rien ne doit être "raccordé" entre ces appels.
Rev1.0
3
@ Rev1.0 Correct. &, &&Et ||sont des opérateurs aux commandes de chaîne ensemble. Tous les 3 se comportent différemment dans leur manière de procéder si une commande génère une valeur de retour non-0. |est complètement différent car il est utilisé pour diriger la sortie d'un programme à un autre. Le résultat pourrait être ce que vous souhaitiez, mais l'utilisation de l'un des opérateurs de chaînage rend l'intention plus claire, car aucune canalisation n'est souhaitée dans cet exemple. Pour une référence supplémentaire: microsoft.com/resources/documentation/windows/xp/all/proddocs/…
Der Hochstapler
1
@ Codezilla Je pense que l'idée dans mon message est assez similaire au vôtre, mais c'est une syntaxe de commande valide.
Casey
-3

Ma langue n'est pas l'anglais alors désolé pour les erreurs.

Je pense que vous ne pouvez pas directement mettre la sortie dans le bloc-notes ouvert. Peut-être que je me trompe à ce sujet. Vous devez créer un fichier avec la sortie afin de pouvoir y travailler. La commande tee peut rediriger la sortie vers deux ou peut-être plusieurs commandes ou fichiers en même temps.

tee shirt homme

N'oubliez pas d'utiliser >> à la place> lorsque vous redurectez la sortie dans le fichier. Le> écrasera le fichier, >> ajoutera la sortie après tout ce qui se trouve déjà dans ce fichier.

utilisateur338167
la source
1
teen'est généralement pas disponible sous Windows et même si c'était le cas, le problème ne serait pas résolu.
Der Hochstapler le
-4

Vous ne pouvez pas, le Bloc-notes est trop limité pour cela! Mieux encore ... installez Cygwin et contournez tout ce "manque de fonctionnalités" de Windows. Vous pouvez ensuite utiliser la commande que vous connaissez déjà.

Autant que je sache, très peu de programmes Windows prennent en charge le pipeline, encore pire pour les programmes à interface graphique.

Vous pouvez essayer d'ouvrir les demandes de fonctionnalités à l'un des programmes "windows tail" pour l'ajouter.

higuita
la source
2
J'utilise déjà cygwin. C’est vraiment un problème spécifique à l’interaction avec Notepad.
Der Hochstapler
1
@emodendroket parfois, les gens utilisent le mauvais outil pour un travail ... et pour presque tous les cas, le bloc-notes est le mauvais outil, il est si simple et limité :)
higuita
1
@higuita Je suis un utilisateur Emacs dévoué, mais parfois, Notepad est le meilleur outil pour ce que je veux faire.
Casey