0

I have read the documentation on the Microsoft Page about inter process communication on Windows platform so I started doing some demo projects to test how does it work etc. Because all I want to do is to copy some files from Windows Share from local network to the PC I've decided to choose WPF as GUI and some "other" method which will do the logical work.

My idea was to achieve successful communication between GUI and Windows Service. On MSDN I read and found in other posts on stack that the best way is to use Windows Communication Foundation.

Problem:

The communication is established. I've prepared an endpoint which is working. Returning small portion of data is OK, but when some more complicated action is done like looping through NFS share or some files in directory, then the exception 'There was an error reading from the pipe: The pipe has ended. (109, 0x6d).' is thrown.

This is my project structure(4 solutions):

  • Windows Service - which is hosting WCFService,
  • WCFService - includes interface and class with "available" methods for GUI to call,
  • Shared Class library - includes classes for logic, app settings, "models" like DirToCopy,
  • GUI - simple button for checking directories on share and list with those directories available to "copy".

Windows Service & WCFService:

  • app.config(same configuration on both sides):

    <system.serviceModel>
            <services>
                <service name="WCFService.MyService">
                    <endpoint address="net.pipe://localhost/copy" binding="netNamedPipeBinding"
                        bindingConfiguration="" contract="WCFService.IMyService" />
                </service>
            </services>
    </system.serviceModel>

WindowsService:

  • MyServiceHost.cs:

    protected override void OnStart(string[] args)
            {
                if (serviceHost != null)
                {
                    serviceHost.Close();
                }
    
                serviceHost = new ServiceHost(typeof(MyService));
                serviceHost.Open();
            }
    
            protected override void OnStop()
            {
                if (serviceHost != null)
                {
                    serviceHost.Close();
                    serviceHost = null;
                }
            }

WCFService:

  • IMyService.cs:

    [ServiceContract]
        public interface IMyService
        {   
            //In SharedClasses solution. Included in using.    
            [OperationContract]
            MyServiceSettings GetSettings();
    
            //In SharedClasses solution. Included in using.
            [OperationContract]
            List<DirToCopy> GetDirs();
        }

  • MyService.cs:

    public class MyService : IMyService
        {
            // SharedClasses lib
            private MyServiceSettings Settings;
            // SharedClasses lib
            private DirToCopyService DirService;
    
            public MyService()
            {
                Settings = new MyServiceSettings();
                DirService = new DirService(Settings);
            }
    
            public MyServiceSettings GetSettings()
            {
                return Settings;
            }
    
            public List<DirToCopy> GetDirs()
            {
                return DirService.GetDirs();
            }
        }

SharedClasses lib:

  • DirToCopyService.cs:

    public class DirToCopyService
        {
            private MyServiceSettings _Settings;
            public List<DirToCopy> dirs;
    
            public DirToCopyService() { }
    
            public DirToCopyService(MyServiceSettings Settings) 
            {
                _Settings = Settings;
            }
    
            public List<DirToCopy> GetDirs()
            {
                DirectoryInfo directoryInfo = new DirectoryInfo(_Settings.nfsAddress);
    
                FileInfo[] files = directoryInfo.GetFiles("*.txt");
    
                dirs = new List<DirToCopy>();
    
                foreach(FileInfo file in files)
                {
                    DirToCopy dirToCopy = new DirToCopy();
                    dirToCopy._filename = file.FullName;
                    dirToCopy._size = new System.IO.FileInfo(Path.Combine(_Settings.nfsAddress, file.FullName)).Length;
                    dirs.Add(DirToCopy);
                }
                return dirs;
            }
        }

GUI:

  • ServiceClient.cs:

    public class ServiceClient
        {
            private IMyService _serviceProxy;
            private ChannelFactory<IMyService> _channelFactory;
            private const string NamedPipeAddress = "net.pipe://localhost/copy";
    
            public ServiceClient()
            {
                _channelFactory = new ChannelFactory<IMyService>(new NetNamedPipeBinding(), new EndpointAddress(NamedPipeAddress));
                _serviceProxy = _channelFactory.CreateChannel();
            }
            
            public MyServiceSettings GetSettings()
            {
                return _serviceProxy.GetSettings();
            }
    
            public List<DirToCopy> GetDirs()
            {
                return _serviceProxy.GetDirs();
            }
    
        }

  • MainViewModel.cs: Im creating here an instance of ServiceClient and passing it to DirsToCopyVM(View Model). Then the button click which is calling GetDirs() is handled and the error with the "Pipe" is thrown.

Summary: After initialization of the GUI the MyServiceSettings are correctly passed to it and I can use any of the properties of this class in GUI. But when I want to do some more complicated stuff like retrievieng a List<DirsToCopy>, after action handling dedicated to Click method, then the error: 'There was an error reading from the pipe: The pipe has ended. (109, 0x6d).' occurs.

I dont know if it's caused of the size of a passed data or any additional settings. Also I'm not sure if my approach is OK or should I change it. Does someone have similar problem?

1 Answer 1

1

Sometimes this error caused by polymorphic feature of objects.

You can try putting the ServiceKnownType attribute into the method or service declaration, as shown in the following code:

[OperationContract]
[ServiceKnownType(typeof(Supervisor))]
List<Person> GetEmployee();

Links that may be useful: WCF NamedPipe CommunicationException - "The pipe has been ended. (109, 0x6d)."

4
  • In DirToCopy model class I have field of type List<FilesInDir> filesInDir. When I've tried to comment it out it started to working. But I'm wondering what I need to do to avoid the problem and include that fully to GUI.
    – kalview
    Commented Apr 4 at 7:38
  • Have you tried the methods I mentioned?
    – Lan Huang
    Commented Apr 5 at 5:31
  • Definying [ServiceKnownType] to FilesInDir helped, but I've also had to create additional constructor for this class without any parameter.
    – kalview
    Commented Apr 5 at 7:31
  • Because you have provided one or more initializing constructors, you will also need to add a parameterless (default) constructor.You need to create that work because the default constructor disappears when you add an explicit constructor.You can try using the [OnDeserialized] attribute to initialize your properties.Details:learn.microsoft.com/en-us/previous-versions/dotnet/fundamentals/…
    – Lan Huang
    Commented Apr 8 at 9:33

Not the answer you're looking for? Browse other questions tagged or ask your own question.