Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Visual Basic
  4. Pipes and Files - making it work

Pipes and Files - making it work

Scheduled Pinned Locked Moved Visual Basic
questiondatabasesysadmincsharpc++
6 Posts 3 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    LurkingGryphon
    wrote on last edited by
    #1

    What I'm working on is basically creating a new version of an old server program. The server service receives messages from an oracle database and distributes those messages to all the connected users, a bit like a chat program that only the administrator can talk on. (It's used to inform the client programs when something has changed in the DB so they can always display the most current data.) Well, we need the new server to handle a whole new type of client that's running on .NET 3.5, but also be backward compatible with the old C++ client. So the point I'm getting to here is that the system uses named pipes to communicate from server to clients. The way it was designed back in the day (long before I got involved!) had the server calling CreateNamedPipe to open \\.\pipe\serverrouter, and then the clients connected to it by calling CreateFile with \\<server computer>\pipe\serverrouter as an argument. I've created a server that creates a NamedPipeServerStream and a client that can connect to it, but the old style client can't see that stream at all -- like it doesn't even exist. As a smaller-scale test I created a new VB.net application and gave it one command: Dim test As New System.IO.FileStream("\\<server computer>\pipe\serverrouter", IO.FileMode.OpenOrCreate) Now, here's what brings up my question: If I point that at the computer that's running the old style server, it throws an exception saying "Filestream was asked to open a device that was not a file..." Which is all well and good, I get that -- but when I point it at the computer running the new server program, the exception is "Could not find file". This matches the behavior of the old style client. What's going on here? Why can't I find the pipe with anything other than a NamedPipeClientStream? A pipe is a pipe, isn't it? How do I get it to at least see the thing? (Actually achieving a connection would be nice too, but I'll settle for being able to see it on the network first!)

    M G 2 Replies Last reply
    0
    • L LurkingGryphon

      What I'm working on is basically creating a new version of an old server program. The server service receives messages from an oracle database and distributes those messages to all the connected users, a bit like a chat program that only the administrator can talk on. (It's used to inform the client programs when something has changed in the DB so they can always display the most current data.) Well, we need the new server to handle a whole new type of client that's running on .NET 3.5, but also be backward compatible with the old C++ client. So the point I'm getting to here is that the system uses named pipes to communicate from server to clients. The way it was designed back in the day (long before I got involved!) had the server calling CreateNamedPipe to open \\.\pipe\serverrouter, and then the clients connected to it by calling CreateFile with \\<server computer>\pipe\serverrouter as an argument. I've created a server that creates a NamedPipeServerStream and a client that can connect to it, but the old style client can't see that stream at all -- like it doesn't even exist. As a smaller-scale test I created a new VB.net application and gave it one command: Dim test As New System.IO.FileStream("\\<server computer>\pipe\serverrouter", IO.FileMode.OpenOrCreate) Now, here's what brings up my question: If I point that at the computer that's running the old style server, it throws an exception saying "Filestream was asked to open a device that was not a file..." Which is all well and good, I get that -- but when I point it at the computer running the new server program, the exception is "Could not find file". This matches the behavior of the old style client. What's going on here? Why can't I find the pipe with anything other than a NamedPipeClientStream? A pipe is a pipe, isn't it? How do I get it to at least see the thing? (Actually achieving a connection would be nice too, but I'll settle for being able to see it on the network first!)

      M Offline
      M Offline
      Mycroft Holmes
      wrote on last edited by
      #2

      LurkingGryphon wrote:

      but also be backward compatible with the old C++ client.

      Somebody really does not like you. Going down this path is one of the reasons Crystal Reports is such a dog, the reason MS rebuilt some of their tools and completely broke backwards compatibility. I have the feeling that a lot of .net stuff is only consumable by .net. You could try wrapping it as com visible and see if that helps (probably not) I'd seriously look at the design and the need for backwards compatibility.

      Never underestimate the power of human stupidity RAH

      L 1 Reply Last reply
      0
      • L LurkingGryphon

        What I'm working on is basically creating a new version of an old server program. The server service receives messages from an oracle database and distributes those messages to all the connected users, a bit like a chat program that only the administrator can talk on. (It's used to inform the client programs when something has changed in the DB so they can always display the most current data.) Well, we need the new server to handle a whole new type of client that's running on .NET 3.5, but also be backward compatible with the old C++ client. So the point I'm getting to here is that the system uses named pipes to communicate from server to clients. The way it was designed back in the day (long before I got involved!) had the server calling CreateNamedPipe to open \\.\pipe\serverrouter, and then the clients connected to it by calling CreateFile with \\<server computer>\pipe\serverrouter as an argument. I've created a server that creates a NamedPipeServerStream and a client that can connect to it, but the old style client can't see that stream at all -- like it doesn't even exist. As a smaller-scale test I created a new VB.net application and gave it one command: Dim test As New System.IO.FileStream("\\<server computer>\pipe\serverrouter", IO.FileMode.OpenOrCreate) Now, here's what brings up my question: If I point that at the computer that's running the old style server, it throws an exception saying "Filestream was asked to open a device that was not a file..." Which is all well and good, I get that -- but when I point it at the computer running the new server program, the exception is "Could not find file". This matches the behavior of the old style client. What's going on here? Why can't I find the pipe with anything other than a NamedPipeClientStream? A pipe is a pipe, isn't it? How do I get it to at least see the thing? (Actually achieving a connection would be nice too, but I'll settle for being able to see it on the network first!)

        G Offline
        G Offline
        Gideon Engelberth
        wrote on last edited by
        #3

        We have a pair of programs using named pipes with a .NET server app and a native (Delphi, not C++, but still native) client app, so I know this is possible. During development, the programs ran on different machines and the required step to let the programs talk across different users was to use the NamedPipeServerStream overload that took a PipeSecurity. It ended up something like this (namespaces avoided for brevity):

        Dim ps As PipeSecurity
        ps.AddAccessRule(New PipeAccessRule("Everyone", PipeAccessRights.FullControl,
        AccessControlType.Allow))
        Dim New NamedPipeServerStream("PipeName", ..., ps)

        As I recall, the problem was configuring the security of the pipe to allow users from another computer to connect.

        L 1 Reply Last reply
        0
        • M Mycroft Holmes

          LurkingGryphon wrote:

          but also be backward compatible with the old C++ client.

          Somebody really does not like you. Going down this path is one of the reasons Crystal Reports is such a dog, the reason MS rebuilt some of their tools and completely broke backwards compatibility. I have the feeling that a lot of .net stuff is only consumable by .net. You could try wrapping it as com visible and see if that helps (probably not) I'd seriously look at the design and the need for backwards compatibility.

          Never underestimate the power of human stupidity RAH

          L Offline
          L Offline
          LurkingGryphon
          wrote on last edited by
          #4

          I got it figured out finally. It's a naming convention issue: in the old style named pipe calls (which are in kernel32, I believe), you have to specify the full path: \\.\pipe\pipename (and the users connect to \\servername\pipe\pipename) But in .net, you only specify the "pipename" part. It automatically prepends the "\\.\pipe" internally on the server pipe, and the client pipe's New takes either a computer name argument or not (in which case it presumes the pipe is local), and prepends either "\\computername\pipe\" or "\\.\pipe\" as appropriate. So if you use the old style address specification with the .net NamedPipeServerStream constructor, it actually ends up putting your pipe at \\.\pipe\pipe\pipename! That's fine if the other end is a NamedPipeClientStream, which will do the same manipulation and not cause a problem, but if you try to create a stream with one and connect with the other, one of them will be looking in \pipe\pipe\ and be unable to find it. Judging from the examples I've seen of how to use .net's named pipe classes, this is a very common error.

          M 1 Reply Last reply
          0
          • G Gideon Engelberth

            We have a pair of programs using named pipes with a .NET server app and a native (Delphi, not C++, but still native) client app, so I know this is possible. During development, the programs ran on different machines and the required step to let the programs talk across different users was to use the NamedPipeServerStream overload that took a PipeSecurity. It ended up something like this (namespaces avoided for brevity):

            Dim ps As PipeSecurity
            ps.AddAccessRule(New PipeAccessRule("Everyone", PipeAccessRights.FullControl,
            AccessControlType.Allow))
            Dim New NamedPipeServerStream("PipeName", ..., ps)

            As I recall, the problem was configuring the security of the pipe to allow users from another computer to connect.

            L Offline
            L Offline
            LurkingGryphon
            wrote on last edited by
            #5

            I did add that code; it didn't fix anything by itself, but once I got the naming convention straightened out (see previous post) everything worked correctly. I don't know if that security specification was really needed, but the thing works with it in, so thanks for posting it.

            1 Reply Last reply
            0
            • L LurkingGryphon

              I got it figured out finally. It's a naming convention issue: in the old style named pipe calls (which are in kernel32, I believe), you have to specify the full path: \\.\pipe\pipename (and the users connect to \\servername\pipe\pipename) But in .net, you only specify the "pipename" part. It automatically prepends the "\\.\pipe" internally on the server pipe, and the client pipe's New takes either a computer name argument or not (in which case it presumes the pipe is local), and prepends either "\\computername\pipe\" or "\\.\pipe\" as appropriate. So if you use the old style address specification with the .net NamedPipeServerStream constructor, it actually ends up putting your pipe at \\.\pipe\pipe\pipename! That's fine if the other end is a NamedPipeClientStream, which will do the same manipulation and not cause a problem, but if you try to create a stream with one and connect with the other, one of them will be looking in \pipe\pipe\ and be unable to find it. Judging from the examples I've seen of how to use .net's named pipe classes, this is a very common error.

              M Offline
              M Offline
              Mycroft Holmes
              wrote on last edited by
              #6

              Put i a tip & trick, make sure there are the right key word and save it for posterity, or some other poor bugger running up against it.

              Never underestimate the power of human stupidity RAH

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups