16

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

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

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

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

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

4 ответа4

11

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

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

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

8

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


Именованные трубы

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

asdf.exe | NamedPipeServer.exe "APipeName"

В другом окне консоли:

NamedPipeClient.exe "APipeName"

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

Вы можете скачать сервер и клиент.

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

Исходный код

Они написаны на 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 в этот файл

Это обеспечивает желаемый эффект одного окна консоли для просмотра stdout (и обеспечения stdin), а другого - для просмотра stderr .

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

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

1

Не со стандартной оболочкой (CMD.EXE). Для программистов это довольно просто. Просто возьмите две трубы процесса, который вы начали.

-2

Ваши предпочтения для канала передачи данных Windows от сервера к клиентскому окну сразу или позже могут быть удовлетворены небольшим ОЗУ. Эта же память выделяется для данных, записываемых / читаемых с именем, похожим на файловую систему. Клиент либо удаляет использованный файл и ждет другого, либо оставляет его исчезнуть при выключении компьютера.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .