web-dev-qa-db-fra.com

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

J'exécute une application à l'aide de la commande Invite ou d'un Git Shell, et j'aimerais que le résultat soit enregistré dans le Bloc-notes afin de pouvoir le consulter et le modifier ultérieurement sur.

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é à effectuer une tuyauterie dans Vim ou moins sur des systèmes autres que Windows.

46
Der Hochstapler

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

Cependant, vous pouvez accéder à clip puis à coller dans le bloc-notes, comme suit:

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

Puis appuyez simplement sur Ctrl+V dans le bloc-notes.

61
Der Hochstapler

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 -
31
Benjamin Goodacre

ici est un court programme Windows qui le fait correctement (sans surcharger le presse-papiers). 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 fichier de script quelque part 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 placez-le dans votre PATH quelque 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 simplement appeler echo blah | ShowInNotepad de n'importe où!

Notez que suppose que vous utilisez une version récente de Windows (Vista +) et que vous n'avez pas désactivé PowerShell ni désinstallé 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 le collage (Ctrl+V) action. 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 fichier .ps1 (par exemple, ShowInNotepad.ps1), de le placer quelque part dans votre PATH, puis d'appeler powershell ShowInNotepad.ps1 après avoir placé le texte à 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 placez-le dans votre PATH quelque 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 simplement appeler echo blah | ShowInNotepad de n'importe où!

8
Bob

Que diriez-vous d'utiliser AutoHotkey ?

Enregistrez les éléments suivants sous stdin.ahk et 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 sans vergogne à moitié ici )

5
Mokubai

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.

4
Casey

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

1
Sean

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 sous forme de touches. 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

0
Jason Musgrove