В windows я могу перенаправить stdout на (именованный) канал в командной строке?

есть ли способ перенаправить стандартный вывод процесса консоли Win32 to a именованный канал?
Именованные каналы встроены в Windows, и хотя они были бы полезной концепцией, я никогда не видел, чтобы они использовались из командной строки.

Ie. как example.exe >.mypipe. (Этот синтаксис может быть неправильным, но вы получите точку.)
Я хотел бы быть в состоянии перенаправить stdout и stderr к различным трубам на этих же время.

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

еще одна причина, потому что традиционные окна набор инструментов не предназначены вокруг философии (текстовый) файл на основе столько как в Unix. Кроме того, именованные каналы не могут быть легко установлены в все.

В конце концов, любопытство если хорошая концепция смогла быть положена в хорошую пользу.

18
задан n611x007
16.11.2022 7:45 Количество просмотров материала 3040
Распечатать страницу

3 ответа

я не уверен, почему вы не хотите перенаправить в файл. Есть два метода, которые я приведу здесь. Первый способ-перенаправление и чтение из файла, другой набор программ.


именованные каналы

я написал две программы для .NET 4. Один отправляет выходные данные в именованный канал, другой считывает их из этого канала и выводит на консоль. Использование довольно просто:

asdf.exe | NamedPipeServer.exe "APipeName"

в другой консоли window:

NamedPipeClient.exe "APipeName"

к сожалению, перенаправить можно только stdout (или stdin, или вместе взятые), а не stderr само собой, из-за ограничений в операторе трубы (|) в командной строке Windows. Если вы выясните, как отправить stderr через оператора трубы, он должен работать. В качестве альтернативы, сервер может быть изменен, чтобы запустить программу и специально перенаправить stderr. Если это необходимо, дайте мне знать в комментарии (или сделайте это самостоятельно); это не слишком сложно, если у вас есть некоторые C# и .NET "процесс" библиотеки знаний.

можно скачать сервер и client.

если вы закроете сервер после подключения, клиент закроется немедленно. Если вы закроете клиент после подключения, сервер закроется, как только вы попытаетесь отправить что-то через него. невозможно подключить сломанную трубу, в основном потому, что я не могу быть обеспокоен тем, что делаю что-то настолько сложное правильно теперь. Он также ограничен один клиент на сервер.

исходный код

они написаны на C#. Нет особого смысла пытаться объяснить это. Они используют .NET NamedPipeServerStream и NamedPipeClientStream.

сервер:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.IO;

namespace NamedPipeServer
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                Console.Error.WriteLine("[NamedPipeServer]: Need pipe name.");
                return;
            }

            NamedPipeServerStream PipeServer = new NamedPipeServerStream(args[0], System.IO.Pipes.PipeDirection.Out);
            PipeServer.WaitForConnection();
            StreamWriter PipeWriter = new StreamWriter(PipeServer);
            PipeWriter.AutoFlush = true;

            string tempWrite;

            while ((tempWrite = Console.ReadLine()) != null)
            {
                try
                {
                    PipeWriter.WriteLine(tempWrite);
                }
                catch (IOException ex)
                {
                    if (ex.Message == "Pipe is broken.")
                    {
                        Console.Error.WriteLine("[NamedPipeServer]: NamedPipeClient was closed, exiting");
                        return;
                    }
                }
            }

            PipeWriter.Close();
            PipeServer.Close();
        }
    }
}

клиент:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.IO;

namespace NamedPipeClient
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                Console.Error.WriteLine("[NamedPipeClient]: Need pipe name.");
                return;
            }

            NamedPipeClientStream PipeClient = new NamedPipeClientStream(".", args[0], System.IO.Pipes.PipeDirection.In);
            PipeClient.Connect();
            StreamReader PipeReader = new StreamReader(PipeClient);

            string tempRead;

            while ((tempRead = PipeReader.ReadLine()) != null)
            {
                Console.WriteLine(tempRead);
            }

            PipeReader.Close();
            PipeClient.Close();
        }
    }
}

перенаправление в файл

type NUL>StdErr.temp
start powershell -c Get-Content StdErr.temp -Wait
MyExecutable.exe 2>StdErr.temp
  1. создать пустой файл
  2. запустить новое окно консоли, которое отслеживает файл
  3. запустить исполняемый файл и перенаправить stderr вывод в файл

это обеспечивает желаемый эффект одного окна консоли для просмотра stdoutstdin), а еще посмотреть stderr.

все, что имитирует tail будет работать. Метод PowerShell работает нативно в Windows, но может быть немного медленным (т. е. есть некоторая задержка между записью в файл и отображение на экране). См.это StackOverflow вопрос другие tail альтернативы.

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

6
отвечен Bob 2022-11-17 15:33

Я удивлен, что на это еще не был дан правильный ответ. Существует действительно путь UNC назначенные системой именованные каналы, доступные на любой машине в сети, которые можно использовать как обычный файл:

program.exe >\.\pipe\StdOutPipe 2>\.\pipe\StdErrPipe

предполагая, что на этой машине существуют трубы с именами "StdOutPipe" и "StdErrPipe", это пытается подключиться и записать в них. The pipe часть-это то, что указывает, что вы хотите именованный канал.

9
отвечен IllidanS4 2022-11-17 17:50

Не со стандартной оболочкой (CMD.ИСПОЛНЯЕМЫЙ.) Для программистов, это довольно легко. Просто возьмите две трубы процесса, который вы начали.

1
отвечен MSalters 2022-11-17 20:07

Постоянная ссылка на данную страницу: [ Скопировать ссылку | Сгенерировать QR-код ]

Ваш ответ

Опубликуйте как Гость или авторизуйтесь

Имя
Вверх