Announcement

Collapse
No announcement yet.

problem with anonymous pipe

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • problem with anonymous pipe

    Hi,
    I am relatively new to PB (used VB for years before) so may be a "stupid" question. I created two programs in PB Win 8, one creating an anonynous pipe, another one reading it. Comes basically from Appleman. The programs run without errors, the only problem is that the string that I write to the pipe is not read that way by the client.
    PeekNamedPipe correctly detects that there is text in the pipe, including the number of bytes, ReadFile reads the number of bytes and stores it in the variable I want but this is not the text that the server sends. I guess it has something to do with character sets but I have no idea to convert what into what. Appleman (for VB) says the output has to be converted into unicode but as far as I know VB handles string internally different than PB, or am I wrong?

    Chunk of code:

    RetValL=PeekNamedPipe(hPipeRead,ByVal 0&,0,nRead,nAvail,nMessage)'this works

    If nAvail>0 Then
    T$=Space$(nAvail)
    RetValL=ReadFile(hPipeRead, ByVal StrPtr(T$),nAvail,nRead,ByVal 0)'this returns something, but what?
    MsgBox "text: " & T$ 'something ununderstandably
    End If


    Any suggestions?
    Wilko

  • #2
    With anonymous pipes, you have to get the two handles returned by CreatePipe to the other process somehow, and it has to be valid in that other process (use DuplicateHandle() function).

    How are you exchanging those handles between the programs?

    Here's an anonymous pipe demo I created a long time ago... it's not inter-process, it's intra-process, but maybe it will give you some ideas about how to format, read and write data to be exchanged via pipe.

    Anonymous Pipe as Job Queue Demo 10-29-03


    MCM
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      Thanks for your fast reply. Unlike your example, I use two separate programs. The server first creates the pipe (bInheritHandle set to True), then calls SetStdHandle, finally invokes the client using CreateProcess.
      The first thing the client does is to determine the pipe handle using GetStdHandle. That all seems to work.
      Also, PeekNamedPipe in the client determines the number of written bytes correctly so apparently the handles are OK.

      But the string returned by the client is not the string the server wrote. Sort of "high" ASCII characters, that's why I thought I had to do with character sets (ANSI/Unicode/anything else?)

      Wilko

      Comment


      • #4
        Character sets is NOT your problem here. Stop looking for problems with those.

        Show failing code, both the read and the write snippets.

        Also show the params to the CreateProcess() call. There is an inherit flag in there, too, which has to be set or the handle is not inherited.

        What I do not understand is how GetStdHandle() can return a pipe handle, unless you have called CreateProcess() with overrides to the standard handles. (Code not shown).

        Also... if the read is failing on invalid handle and you are not checking (Code not shown), whatever is in your read buffer is 'undefined' and often looks a lot like "garbage."


        MCM
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          This is the (server) code to create the pipe and the child process:
          Local PI As PROCESS_INFORMATION
          Local RetValL As Long
          Local SA As SECURITY_ATTRIBUTES
          Local SI As STARTUPINFO

          SA.nLength =Len(SA)
          SA.bInheritHandle=%True
          RetValL=CreatePipe(hPipeRead,hPipeWrite,SA,0)
          If RetValL=0 Then MsgBox "pipe not created " & Str$(RetValL)

          Call SetStdHandle(%STD_INPUT_HANDLE,hPipeRead)
          SI.cb=Len(SI)
          RetValL=CreateProcess("child.exe","",SA,SA,%True,%NORMAL_PRIORITY_CLASS,ByVal 0&,"",SI,PI)
          If RetValL=0 Then MsgBox "CreateProcess failed " & Str$(RetValL)
          CloseHandle PI.hProcess
          CloseHandle PI.hThread

          This is the (server) code to write to the pipe:
          Local RetValL As Long
          Local Written As Dword
          Local T$

          T$="ababcdcd"
          RetValL=WriteFile(hPipeWrite,T$,Len(T$),Written,ByVal 0)

          MsgBox "writefile returns " & Str$(RetValL) & Str$(Written)
          CloseHandle hPipeRead
          CloseHandle hPipeWrite
          (note: correctly displays 8 bytes written)

          in the client:
          During handling of "create" message:
          hPipeRead=GetStdHandle(%STD_INPUT_HANDLE)

          on button click:
          Local nAvail As Long
          Local nMessage As Long
          Local nRead As Long
          Local RetValL As Long
          Local T$
          Local T2$

          RetValL=PeekNamedPipe(hPipeRead,ByVal 0&,0,nRead,nAvail,nMessage)'this works

          If nAvail>0 Then
          T$=Space$(nAvail)
          RetValL=ReadFile(hPipeRead, ByVal StrPtr(T$),nAvail,nRead,ByVal 0)'this returns something, but what?
          MsgBox "text: " & T$
          End If


          Hope this helps to make my problem clear.
          Thanks for any suggestions.
          Wilko

          Comment


          • #6
            You have to set the standard handle info in STARTUP_INFORMATION before your call to CreateProcess. Otherwise your line here...
            Code:
            hPipeRead=GetStdHandle(%STD_INPUT_HANDLE)
            ... will not be using the pipe, it will be using 'something else'

            I can't remember if you have to SetStdHandle() yourself to the value in STARTUP_INFO or if it's automatic.

            Also, if the child is a PB/CC program, I'd be careful using the STDIN and STDOUT functions.... I have not tested recently but I had problems with PB/CC child programs respecting standard handle overrides in the past.

            MCM
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              Michael, the problem turned out to be the string that I wrote to the pipe. Had to be a BYTE variable. When I changed the writing part to:
              Code:
                Local TB As Byte
                Local ToWrite$
                
                ToWrite$="abcdefgh"
                                                            
                For I=1 To Len(ToWrite$)
                  TB=Asc(Mid$(ToWrite$,I,1))
                  RetValL=WriteFile(hPipeWrite,TB,1,Written,ByVal 0)
                Next I
              everything worked fine. Maybe it can be made more efficient than writing one byte at at time but at least this works.
              Thanks

              Comment


              • #8
                >RetValL=WriteFile(hPipeWrite,T$,Len(T$),Written,By Val 0)

                I missed that. If T$ were an ASCIIZ variable it would have worked, assuming you are using the provided DECLARE for WriteFile, with the second param 'AS ANY'

                The part where you were sure the write was OK also was throwing me off.
                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment

                Working...
                X