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?