WCF NamedPipes Service and WPF Client - c#

I'm working with a windows service where i want to add a GUI too it. I made a proof of concept with my service creating a ServiceHost object and hosting the WCF Named pipes service and then i Console application to consume the WCF service and also getting callback responses from the service (messages sent from server to connected clients). This works great my console application runs and get responses from the service with no interruption or delays.
However when doing the same thing in my WPF GUI application when clicking a button that then calls the WCF service it freezes the whole UI thread and then after a couple of minutes throws an exception and then the UI is updated with the message callback (server sends message to connected clients) but any return values from service is lost since the exception was thrown.
The two exception messages i have gothen is theses (the most common is the first):
1: The requesting action sent to net.pipe :/ / localhost / PipeGUI did not receive a response within the specified timeout (00:00:59.9989999). The time allotted to this operation may have been a portion of a longer timeout. This may be because the service is still processing the operation or because the service was unable to send a reply message. Raise the deadline for action (by entering the channel / proxy to Icon Text Channel and set the property Operation Timeout) and verify that the service can connect to the client.
2: Communication object System.ServiceModel.Channels.ServiceChannel, can not be used for communication because it has been canceled.
Anyone got any ideas why this is happeing ?
I can post more code if neccessary.
UPDATE , added code for reference
public interface IClientCallback
{
[OperationContract(IsOneWay = true)]
void MessageRecived(string message);
}
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IClientCallback))]
public interface IPipeServiceContract
{
[OperationContract]
string Hello();
[OperationContract]
void Message(string msg);
[OperationContract(IsInitiating = true)]
void Connect();
[OperationContract(IsTerminating = true)]
void Disconnect();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, IncludeExceptionDetailInFaults = true, UseSynchronizationContext = false)]
public class PipeService : IPipeServiceContract
{
List<IClientCallback> _clients = new List<IClientCallback>();
public string Hello()
{
PublishMessage("Hello World.");
return "Return from method!";
}
public void Connect()
{
_clients.Add(OperationContext.Current.GetCallbackChannel<IClientCallback>());
}
public void Disconnect()
{
IClientCallback callback = OperationContext.Current.GetCallbackChannel<IClientCallback>();
_clients.Remove(callback);
}
void PublishMessage(string message)
{
for (int i = _clients.Count - 1; i > 0; i--)
{
try
{
_clients[i].MessageRecived(message);
}
catch (CommunicationObjectAbortedException coae)
{
_clients.RemoveAt(i);
}
catch(CommunicationObjectFaultedException cofe)
{
_clients.RemoveAt(i);
}
}
}
public void Message(string msg)
{
PublishMessage(msg);
}
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged, IClientCallback
{
public ServiceController Service { get; set; }
protected IPipeServiceContract Proxy { get; set; }
protected DuplexChannelFactory<IPipeServiceContract> PipeFactory { get; set; }
public ObservableCollection<ServerActivityNotification> Activity { get; set; }
public override void BeginInit()
{
base.BeginInit();
PipeFactory = new DuplexChannelFactory<IPipeServiceContract>(this, new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/PipeGUI"));
}
public MainWindow()
{
InitializeComponent();
Activity = new ObservableCollection<ServerActivityNotification>();
Service = ServiceController.GetServices().First(x => x.ServiceName == "Server Service");
NotifyPropertyChanged("Service");
var timer = new DispatcherTimer();
timer.Tick += new EventHandler(OnUpdate);
timer.Interval = new TimeSpan(0, 0, 0, 0, 850);
timer.Start();
if (Service.Status == ServiceControllerStatus.Running)
{
Proxy = PipeFactory.CreateChannel();
Proxy.Connect();
}
}
void OnUpdate(object sender, EventArgs e)
{
Service.Refresh();
NotifyPropertyChanged("Service");
StartButton.IsEnabled = Service.Status != ServiceControllerStatus.Running ? true : false;
StopButton.IsEnabled = Service.Status != ServiceControllerStatus.Stopped ? true : false;
if (PipeFactory != null && Service.Status == ServiceControllerStatus.Running)
{
Proxy = PipeFactory.CreateChannel();
Proxy.Connect();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
private void OnStart(object sender, RoutedEventArgs e)
{
try
{
Service.Start();
}
catch
{
Service.Refresh();
}
}
private void OnStop(object sender, RoutedEventArgs e)
{
try
{
if (Proxy != null)
{
Proxy.Disconnect();
PipeFactory.Close();
}
Service.Stop();
}
catch
{
Service.Refresh();
}
}
public void MessageRecived(string message)
{
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
ServerActivityNotification log = new ServerActivityNotification { Activity = message, Occured = DateTime.Now };
Activity.Add(log);
ListBoxLog.ScrollIntoView(log);
NotifyPropertyChanged("Activity");
}));
}
private void OnHello(object sender, RoutedEventArgs e)
{
try
{
Proxy.Message(txtSendMessage.Text);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
}

Try setting the UseSynchronizationContext property of the service behaviour to false:
[ServiceBehavior(UseSynchronizationContext = false)]
class MyService
{
}
[ServiceContract]
public interface IMyService
{
}
I believe that by default this is set to true, so you are currently attempting to consume and run the WCF service on the same thread resulting in a deadlock.
In any case, it sounds like you are trying to consume the WCF service on the UI thread of the WPF application. Generally it is recommended that you perform potentially long running tasks on the background thread as this keeps the interface responsive even if your service call takes a few seconds/minutes.
EDIT:
I tried and succeeded in replicating your problem. Trying to call the service on the UI thread results in the UI freezing. However, when I changed my code to call the service on a background task (see below), I was able to call the service and receive the callback:
private void Button_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
var myService = DuplexChannelFactory<IMyService>.CreateChannel(new CallbackImplementation(),
new WSDualHttpBinding(),
new EndpointAddress(
#"http://localhost:4653/myservice"));
myService.CallService();
string s = "";
});
}
I have to confess, I am not entirely sure why this is so, and any clarification on exactly how WCF manages the thread hosting the service instance would be great in working out why this works.

Related

C# Windows Service Events

So I am just messing around here nothing production just proof of concept with my first ever Windows Service.
I am trying to essentially create a windows service that sits as the listener for a signalr connection. In essence, I will have a windows application and a windows service. The win service will handle connecting to the signalr hub and on signalr calls fire an event. The windows application will listen for these events and perform actions based on them.
Currently I cannot get this to work. I have never worked with events, or windows services before. In my windows application my events never hit their break points, as well I log an error of null reference exception from the
ConnectToHub()
Alright if I comment out the OnConnected() method call I log a successful connection to the hub. I have never worked with events before so is my mistake with the events?
I debated that this approach was a bit overkill. However, for me it was a proof of concept that I could find a use for a long running windows service, and adding some events into the mix.
Code for service:
public delegate void MessageRecievedEventHanlder(object sender, MessageRecievedArgs e);
public delegate void ConnectedToHubEventHandler(object sender, ConnectedArgs e);
public partial class SignalRService : ServiceBase
{
IHubProxy _hub;
HubConnection connection;
string url = #"http://localhost:8080/";
private Message LastMessage;
public static event MessageRecievedEventHanlder NewMessage;
protected virtual void OnNewMessage(MessageRecievedArgs e)
{
NewMessage(null, e);
}
public static event ConnectedToHubEventHandler Connected;
protected virtual void OnConnected(ConnectedArgs e) {
System.IO.File.WriteAllText(#"C:\Users\Bailey Miller\Desktop\FTP\Logg.txt", "Hit OnConnected " + e.Success +" " + Connected != null ? "Isn't null" : "Null event");
Connected(null, e);
}
public SignalRService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
ConnectToHub().Wait();
}
private async Task ConnectToHub()
{
try
{
//Connecting
if (connection == null)
{
connection = new HubConnection(url);
}
if (_hub == null)
{
_hub = connection.CreateHubProxy("ChatHub");
}
await connection.Start();
//Connected
//Configure all the incoming options
_hub.On<Message>("RecieveMessage", IncomingMessage);
System.IO.File.WriteAllText(#"C:\Users\Bailey Miller\Desktop\FTP\Succes.txt", "Connected");
OnConnected(new ConnectedArgs(true));
}
catch (Exception ex)
{
//Failed
//OnConnected(new ConnectedArgs(false));
System.IO.File.WriteAllText(#"C:\Users\Bailey Miller\Desktop\FTP\Fail.txt", "Failed to connect " + ex.Message.ToString());
}
}
private void IncomingMessage(Message state)
{
DateTime? lmt;
//Determine if has lastmessagetime
if (LastMessage == null) {
lmt = null;
}
else {
lmt = LastMessage.RecievedAt;
}
LastMessage = state;
//New Message
//OnNewMessage(new MessageRecievedArgs(state, lmt));
}
protected override void OnStop()
{
}
}
public class MessageRecievedArgs : EventArgs
{
public Message NewMessage { get; }
public DateTime? LastMessageTime { get; }
public MessageRecievedArgs(Message msg, DateTime? lmt) {
this.NewMessage = msg;
this.LastMessageTime = lmt;
}
}
public class ConnectedArgs : EventArgs {
public bool Success { get; }
public ConnectedArgs(bool suc) {
this.Success = suc;
}
}
My windows application as of now:
public MainWindow()
{
InitializeComponent();
SignalRService.SignalRService.NewMessage += SignalRService_NewMessage;
SignalRService.SignalRService.Connected += SignalRService_Connected;
}
private void SignalRService_Connected(object sender, SignalRService.ConnectedArgs e)
{
throw new NotImplementedException();
}
private void SignalRService_NewMessage(object sender, SignalRService.MessageRecievedArgs e)
{
throw new NotImplementedException();
}
Your question is a bit broad- you don't describe exactly what isn't working, so I am guessing that when you start your service, it says "starting..." for a long while and eventually windows service manager gives you an error saying your service didn't start in a timely fashion. The issue is that OnStart() is expected to return- you can't block the thread there with the Wait() call. My suggestion would be to spawn a new background thread here to perform the waiting, then exit. That should get you past the first hurdle.
As another aside... You can add a regular main method to a windows service project, change the project type to Console Application, and run it that way to reduce your debugging cycle time. Then when you are sure it basically works, change the project type back to Windows Service and install it.
EDIT: Now that you have a better error description, I see the real problem. The issue is that you are raising an event without checking for null first. Event fields are null until you attach a listener. So change your code as follows:
protected virtual void OnConnected(ConnectedArgs e) {
System.IO.File.WriteAllText(#"C:\Users\Bailey Miller\Desktop\FTP\Logg.txt", "Hit OnConnected " + e.Success +" " + Connected != null ? "Isn't null" : "Null event");
ConnectedToHubEventHandler connectedEvent = Connected;
if (connectedEvent != null) // This event might be null, so check first
connectedEvent(null, e);
}

WCF Named Pipe Error: The pipe has been ended. (109, 0x6d)

I have looked at the other posts dealing with "The pipe has been ended. (109, 0x6d)" but none of them have solved my problem. I have a relatively simple setup bases off of this blog: http://tech.pro/tutorial/855/wcf-tutorial-basic-interprocess-communication
I feel like I follow it pretty closely, only removing the HTTP binding.
Here is the server code:
public class InterProcessServer : IInterProcessServer
{
private ServiceHost _host = null;
public event EventHandler<CommandLineArgsEventArgs> CommandLineArgsReceived;
protected InterProcessServer(Uri serverAddress, string serviceName)
{
IPassCommandLineArgs passArgs = null;
passArgs = CreatePassCommandLineArgs();
passArgs.CommandLineArgsReceived += new EventHandler<CommandLineArgsEventArgs> passArgs_CommandLineArgsReceived);
_host = new ServiceHost(passArgs, new Uri[] { serverAddress });
_host.AddServiceEndpoint(typeof(IPassCommandLineArgs), new NetNamedPipeBinding(), serviceName);
_host.Open();
}
public static IInterProcessServer CreateInterProcessServer(Uri serverAddress, string serviceName)
{
return new InterProcessServer(serverAddress, serviceName);
}
public void Dispose()
{
try
{
_host.Close();
}
catch { }
}
private void passArgs_CommandLineArgsReceived(object sender, CommandLineArgsEventArgs e)
{
EventHandler<CommandLineArgsEventArgs> handler = CommandLineArgsReceived;
if (handler != null)
handler(sender, e);
}
protected virtual IPassCommandLineArgs CreatePassCommandLineArgs()
{
return new PassCommandLineArgs();
}
}
Here is the client code:
public class InterProcessClient : IInterProcessClient
{
private IPassCommandLineArgs _pipeProxy = null;
private ChannelFactory<IPassCommandLineArgs> _pipeFactory = null;
protected InterProcessClient(Uri serviceAddress)
{
_pipeFactory = new ChannelFactory<IPassCommandLineArgs>(new NetNamedPipeBinding(), new EndpointAddress(serviceAddress));
_pipeProxy = _pipeFactory.CreateChannel();
}
public static IInterProcessClient CreateInterProcessClient(Uri serviceAddress)
{
return new InterProcessClient(serviceAddress);
}
public void SendArgs(string[] args)
{
_pipeProxy.PassArgs(args);
}
public void Dispose()
{
try
{
if (_pipeFactory != null)
_pipeFactory.Close();
}
catch { }
}
}
I have ensured that the address the client is connecting to is correct. Can anyone provide an idea why I might be getting the error when _pipeProxy.PassArgs(args); is called from the client? The test is just between two console apps on the same machine running in different processes.
Framework 4.0 btw.
Thanks!
EDIT Here is the service interface and implementation:
[ServiceContract]
public interface IPassCommandLineArgs
{
event EventHandler<CommandLineArgsEventArgs> CommandLineArgsReceived;
[OperationContract]
void PassArgs(string[] args);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class PassCommandLineArgs : IPassCommandLineArgs
{
public event EventHandler<CommandLineArgsEventArgs> CommandLineArgsReceived;
public void PassArgs(string[] args)
{
EventHandler<CommandLineArgsEventArgs> hander = CommandLineArgsReceived;
if (hander != null)
hander(this, new CommandLineArgsEventArgs() { Args = args });
}
}
OK. This was an issue of the calling code passing in an address that had an invalid character to the client. Nothing more.

Handling events after receiving a MSMQ message (thread issue?)

I created two separate Windows Forms applications in C# that use MSMQ for communicating. Here's how it works, it looked simple enough though:
App1 sends a details request to App2.
App2 creates an event to open the window.
App2 opens a "details" window.
The only problem I have is that when received the message, the "details" window freezes after appearing.
As I handle MSMQ messages handling in an object that uses threads, I suspect the problem comes from there... But I have no experience in handling MSMQ messages or specific events handling between parts of an application.
Here's part of the code I use for App2:
/*Class declared in the Core namespace*/
public class TaskMessageQueueHandler
{
public TaskMessageQueueHandler()
{
this.Start();
}
private Thread m_thread;
private ManualResetEvent m_signal;
public event System.EventHandler messageReceived;
public void Start()
{
m_signal = new ManualResetEvent(false);
m_thread = new Thread(MSMQReceiveLoop);
m_thread.Start();
}
public void Stop()
{
m_signal.Set();
}
protected virtual void SendEvent(object sender, EventArgs e)
{
if (messageReceived != null)
messageReceived(this.message, e);
}
public string message;
private void MSMQReceiveLoop()
{
bool running = true;
MessageQueue queue = new MessageQueue(#".\Private$\queue1");
while (running)
{
try
{
var message = queue.Receive();
message.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });
this.message = message.Body.ToString();
string m = this.message;
SendEvent(m, System.EventArgs.Empty);
if (m_signal.WaitOne(10))
{
running = false;
}
}
catch
{
Console.WriteLine("ERROR");
running = false;
}
}
}
}
/*Main process, in the Program namespace*/
[...]
Core.TaskMessageQueueHandler tmqh = new Core.TaskMessageQueueHandler();
EventListener el = new EventListener();
tmqh.messageReceived += new System.EventHandler(el.ShowDetails);
[...]
/* Class in the Program namespace */
class EventListener
{
public void ShowDetails(object sender, EventArgs e)
{
int numero = int.Parse(sender as string);
Details details = new Details(numero);
details.Show();
}
}
Where did I go wrong? Where did I go right?
Thanks a lot,
Stephane.P
EDIT: if the MSMQ handler is stopped with Stop() anywhere around the event sending, the details window appears then disappears right away...
EDIT2: After the workaround given by Slugart, I managed to make this work:
class EventListener
{
Main control;
public EventListener(Main main)
{
control = main;
}
public void ShowDetails(object sender, EventArgs e)
{
int numero = int.Parse(sender as string);
control.Invoke((Action)(() => ShowDetails(numero)));
}
private void ShowDetails(int numero)
{
Details details = new Details(numero);
details.Show();
}
}
Which is used like:
Core.TaskMessageQueueHandler tmqh = new Core.TaskMessageQueueHandler();
EventListener el = new EventListener(this);
tmqh.messageReceived += new System.EventHandler(el.ShowDetails);
You're creating and displaying a form Details on a thread other than the main GUI thread and not an STA thread at that.
Your EventListener should have a reference to a running form (your main form perhaps) and then call form.Invoke() on it.
class EventListener
{
Control control; // A valid running winforms control/form created on an STA thread.
public void ShowDetails(object sender, string message)
{
int numero = int.Parse(message);
control.Invoke(() => ShowDetails(numero))
}
private void ShowDetails(int numero)
{
Details details = new Details(numero);
details.Show();
}
}
Also sending your event data as the sender is not really following the Event pattern that has been put in front of you. You want to use the EventArgs parameter for this, use the EventHandler delegate (EventHandler in your case).

How identify that form is consuming a Data Service

I have a C# WinForms application with using of WCF Data Services and I can't find a way to know if the application is doing a process to a web service. I have tried to implement IClientMessageInspector, etc. but it seems that it doesn't work.
Is there any other way to catch when a Windows Form app is consuming a web service? The purpose is to display a "running process" icon when the communication to a service is opened and then hide it when it's close.
Thanks.
you should add event in place where you calling WcfService methods and then listen to this event in UI layer. With custom event argument in this event, you should provide more info for consuming UI layer like enum values Connected, TransferStarted, TransferEnded, Closed,...
I think there are two main possible cases:
Wcf communication take place synchronous - you are calling some wrapper methods of object which handles connection/requests/responses with wcf service - in this case i think its trivial, you make UI actions before every call of wrapper for example
try
{
WcfEx.IwcfS5ExtensionClient client = new IwcfS5ExtensionClient("MyEndpointConfigurationName");
client.Open();
if (client.State == CommunicationState.Opened)
{
//change UI to Connected
}
else
{
//change ui to Connection Error
}
Application.DoEvents();
//Change UI to Transfering data
Application.DoEvents();
client.DoWork();
//change UI to transfer done
Application.DoEvents();
client.Close();
//change ui to Closed
}
catch (Exception e)
{
//change ui to Comunication error
}
Second is if wcf communication is async
-i will add more sofisticated sample later today
EDIT: Example with async work and notifying form
using System;
using System.ComponentModel;
using System.Threading;
using WcfEx;
public class MyForm : Form
{
public MyForm()
{
WcfHandler WcfConnection = new WcfHandler();
WcfConnection.ProgressChanged += WcfConnectionOnProgressChanged;
}
private delegate void WcfConnectionOnProgressChangedDelegate(object Sender, WcfHandler.ProgressChangedEventArgs EventArgs);
private void WcfConnectionOnProgressChanged(object Sender, WcfHandler.ProgressChangedEventArgs EventArgs)
{
//multi thread synchronization check
if (this.InvokeRequired)
{
object[] Parameters = new object[2];
Parameters[0] = Sender;
Parameters[1] = EventArgs;
this.Invoke(new WcfConnectionOnProgressChangedDelegate(WcfConnectionOnProgressChanged), Parameters);
}
else
{
if (EventArgs == null)
return;
switch (EventArgs.StateValue)
{
case WcfHandler.ProgressChangedEventArgs.State.Started:
{
this.Text = "Starting connection...";
break;
}
case WcfHandler.ProgressChangedEventArgs.State.Processing:
{
this.Text = "Downloading updates...";
break;
}
case WcfHandler.ProgressChangedEventArgs.State.Finished:
{
this.Text = EventArgs.Succes ? "Update completed" : "Update failed";
break;
}
}
Application.DoEvents();
}
}
public class WcfHandler
{
public class ProgressChangedEventArgs : EventArgs
{
public enum State : int
{
Started,
Processing,
Finished
};
public bool Succes { get; set; }
public State StateValue { get; set; }
}
public delegate void ProgressChangedEventHandler(object sender, ProgressChangedEventArgs EventArgs);
public event ProgressChangedEventHandler ProgressChanged;
protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
{
if (ProgressChanged != null)
{
ProgressChanged(this, e);
}
}
public void StartChecking()
{
BackgroundWorker bWorker = new BackgroundWorker();
bWorker.DoWork += CheckStatesAsync;
bWorker.RunWorkerCompleted += BWorkerOnRunWorkerCompleted;
bWorker.RunWorkerAsync();
}
private void CheckStatesAsync(object sender, DoWorkEventArgs e)
{
while (true)
{
WcfEx.IwcfS5ExtensionClient client = new IwcfS5ExtensionClient("MyWcfBindingConfig");
ProgressChangedEventArgs Controller = new ProgressChangedEventArgs();
Controller.StateValue = ProgressChangedEventArgs.State.Started;
Controller.Succes = true;
this.OnProgressChanged(Controller);
try
{
client.Open();
Controller.StateValue = ProgressChangedEventArgs.State.Processing;
Controller.Succes = true;
this.OnProgressChanged(Controller);
//do some work
}
catch (Exception)
{
this.OnProgressChanged(new ProgressChangedEventArgs()
{
StateValue = ProgressChangedEventArgs.State.Finished,
Succes = false
});
}
Thread.Sleep(8000);
}
}
private void BWorkerOnRunWorkerCompleted(object Sender, RunWorkerCompletedEventArgs RunWorkerCompletedEventArgs)
{
ProgressChangedEventArgs Controller = new ProgressChangedEventArgs();
Controller.StateValue = ProgressChangedEventArgs.State.Finished;
Controller.Succes = true;
this.OnProgressChanged(Controller);
}
}

WCF Service host receives null object

Environment: .net 4.6.1 on Windows 10 x64
Problem:
1. WCF Contract implemented with an event.
2. Service host will fire the event every time an event log entry is logged and called by the client.
3. The host application triggers properly however the object (EventLogEntry) does not get posted properly and is always null.
4. I have checked during debug the client side Winforms application passes a instantiated object. This somehow doesn't make it to the
server side.
5. at this Stage both the client and the server are on the same machine.
Question:
Why is object null and how can I fix this?
WCF Service Code:
[ServiceContract]
public interface IloggerWCFServiceContract
{
[OperationContract(IsOneWay = true)]
void WriteEvent(EntryWrittenEventArgs e);
[OperationContract(IsOneWay = true)]
[ServiceKnownType(typeof(EventLogEntry))]
void OnEventWritten(EntryWrittenEventArgs e);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class wcf_logger_servicebase : IloggerWCFServiceContract
{
public event EventHandler<EntryWrittenEventArgs> eventwritten;
public void OnEventWritten(EntryWrittenEventArgs e)
{
if (eventwritten != null)
this.eventwritten(this, e);
}
public void WriteEvent(EntryWrittenEventArgs e)
{
OnEventWritten(new EntryWrittenEventArgs(e.Entry));
}
}
Wcf Winforms Server code:
wcf_logger_servicebase loggerWCFService = new wcf_logger_servicebase();
ServiceHost loggerServiceHost = new ServiceHost(loggerWCFService, new Uri(loggerGlobalStatics.namedPipeServerAddress));
loggerWCFService.eventwritten += new EventHandler<EntryWrittenEventArgs>(eventhandler_entryWritten);
.....
loggerServiceHost.AddServiceEndpoint(typeof(IloggerWCFServiceContract), new NetNamedPipeBinding(), loggerGlobalStatics.namedPipeServerAddress);
loggerServiceHost.Open();
......
private void eventhandler_entryWritten(object sender, EntryWrittenEventArgs e)
{
--->textBox1.Text += e.Entry.ToString() + "\r\n" ;
}
WCF Winforms Client code:
ChannelFactory<IloggerWCFServiceChannel> loggerChannelFactory;
IloggerWCFServiceChannel loggerServiceChannel = null;
wcf_logger_servicebase loggerWCFService = new wcf_logger_servicebase();
EndpointAddress serverEndpoint;
System.ServiceModel.Channels.Binding binding;
public client()
{
InitializeComponent();
serverEndpoint = new EndpointAddress(new Uri(loggerGlobalStatics.namedPipeServerAddress));
binding = new NetNamedPipeBinding();
loggerChannelFactory = new ChannelFactory<IloggerWCFServiceChannel>(binding, serverEndpoint);
loggerChannelFactory.Open();
loggerServiceChannel = loggerChannelFactory.CreateChannel();
loggerServiceChannel.Open();
....
private void eventLog1_EntryWritten(object sender, System.Diagnostics.EntryWrittenEventArgs e)
{
loggerServiceChannel.WriteEvent(e);
}
The reason is that EntryWrittenEventArgs has no setter for Entry.
See this SO question for more details.
Why not just send Entry directly without encapsulating it in EntryWrittenEventArgs?

Categories

Resources