3

I need a named pipe to read and write.

In a program I create the pipe server using from kernel32.dll:

string PipeName = "\\\\.\\pipe\\myMT4"; 
int PipeMode = PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT; # tried too: PIPE_NOWAIT
int hPipe = CreateNamedPipeW(
            PipeName,
            PIPE_ACCESS_DUPLEX,
            PipeMode,
            PIPE_UNLIMITED_INSTANCES,1024,1024,
            NMPWAIT_USE_DEFAULT_WAIT,NULL);

The handle hPipe is valid - every things seems to be ok here!

But in a PowerShell-script I want to open a client, connect and open the writer -
and cannot connect => timed out

function connect{
    Param ([PSObject] $h)
    ...
    $h.Pipe = New-Object -TypeName System.IO.Pipes.NamedPipeClientStream "\\.\pipe\PipeTest"
    $h.Pipe.Connect( 5000 )
    $h.Writer = New-Object -TypeName System.IO.StreamWriter $h.Pipe, $h.Encode 

I really would prefer this way to have a similar access when reading and writen
either from/to the pipe and sockets e.g.:

function write{
    Param ([PSObject] $h, [string] $line )
  try {
        $h.Writer.Write($line) 
    }       

What is wrong? Thanks in advance, Gooly.

PS: It seems that the program cannot deal with pipe-servers - I have to open a pipe-client, and that works but that causes other problems:

I define for the PowerShell-pipe-server :

 $pipeName = "testpipe"
 $pipeDir  = [System.IO.Pipes.PipeDirection]::InOut
 $pipeMsg  = [System.IO.Pipes.PipeTransmissionMode]::Message
 $pipeOpti = [System.IO.Pipes.PipeOptions]::Asynchronous
 $pipe = New-Object system.IO.Pipes.NamedPipeServerStream( 
                  $pipeName, $pipeDir, 1, $pipeMsg, $pipeOpti )
 $pipe.WaitForConnection() # 
 $sw = new-object System.IO.StreamWriter $pipe
 $sw.AutoFlush = $true
 $sw.WriteLine("Server pid is $pid")
 $sw.Dispose()
 $pipe.Dispose()

1) My first problem is now that the powerShell-pipe-server is blocked by

 $pipe.WaitForConnection()

until a client connects but it must handle 2 different sockets independently meanwhile and

2) if the client closes the connection I was unable to tell the client to open the same pipe again and the client gets the Windows-error: ERROR_PIPE_BUSY 231

Form the program I connect to the server with the kernel32.dll-function:

 int CallNamedPipeW(string PipeName, 
           string outBuffer, int outBufferSz, 
           uint& inBuffer[], int inBufferSz, 
           int& bytesRead[], int timeOut
 );

Any ideas?

gooly
  • 1,241
  • 7
  • 20
  • 38
  • It seems that the program somehow cannot deal with a pipe-server been started. I have found a simple stand-alone pipe-server that will do it. – gooly Jun 08 '14 at 10:02
  • Is there a good reason you need async support? You may be able to get that to work in PowerShell but you are in for some hurt. – Keith Hill Jun 09 '14 at 15:18
  • What do you mean by `it must handle 2 different sockets independently`? Do you mean it must handle multiple clients? Are you are setting up sockets for other tasks? One way to deal with the blocking nature of WaitForConnection is to run this script in a background job e.g. `$serverJob = Start-Job -Name NamedPipeServer {$pipe = ... }`. This will spin up another PowerShell process in the background to service your script and the current PowerShell session will continue on to process other script. – Keith Hill Jun 09 '14 at 15:54
  • Thank you very much, I was thinking of that (multiple threads) but decided against it due to the the additional need to manage the communication between all the threads. I'll use socket too. – gooly Jun 09 '14 at 17:35

1 Answers1

8

Hmm, I can get named pipes to work between two different PowerShell sessions so I don't think it is an inherent PowerShell limitation:

Here is the server script:

$pipe = new-object System.IO.Pipes.NamedPipeServerStream 'testpipe','Out'
$pipe.WaitForConnection()
$sw = new-object System.IO.StreamWriter $pipe
$sw.AutoFlush = $true
$sw.WriteLine("Server pid is $pid")
$sw.Dispose()
$pipe.Dispose()

Here is the client script:

$pipe = new-object System.IO.Pipes.NamedPipeClientStream '.','testpipe','In'
$pipe.Connect()
$sr = new-object System.IO.StreamReader $pipe
while (($data = $sr.ReadLine()) -ne $null) { "Received: $data" }
$sr.Dispose()
$pipe.Dispose()

Client outputs:

Received: Server pid is 22836
Keith Hill
  • 194,368
  • 42
  • 353
  • 369
  • Is there a way that waiting for a pipe-client to connect ($pipe.WaitForConnection()) does NOT block the server because it is meant to handle 2 sockets as well independently? – gooly Jun 09 '14 at 04:53
  • Have you tried opening the client stream using `$pipe = new-object System.IO.Pipes.NamedPipeClientStream '.','myMT4','InOut'`? – Keith Hill Jun 09 '14 at 05:21
  • Gooly, I believe what you want is an increase to the parameter "number of instances" on the NamedPipeServerStream paremeters. – Rudy Hinojosa Aug 21 '14 at 21:23
  • 1
    I know this is old, but this is the only solution that worked for me: https://gist.github.com/scudette/b6a50f9756f58ed93c9f0f3bdcc01072 – DaMaxContent Oct 14 '22 at 09:15