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.
Related
I have a WPF (.NET Framework 4.6) application that uses websocket-sharp (version 3.0.0) to create a websocket server.
I have a WebsocketServer and using EventHandler to tranfer event to MainWindow.xaml.cs but it not working. The MainWindow.xaml.cs listened to a RaiseOnScanDevice event but not any event invoked here.
I think this issue is relative to different thread. I try using Dispatcher.Invoke but it still not working.
System.Windows.Application.Current.Dispatcher.Invoke(new System.Action(() =>
{
RaiseOnScanDevice(this, new EventArgs());
}));
I found an issue (https://github.com/sta/websocket-sharp/issues/350) but the answers do not resolve my issue.
Please help me a solution for this issue.
WebsocketServer.cs file
public class WebsocketServer : WebSocketBehavior
{
private static readonly Lazy<WebsocketServer> lazyInstance = new Lazy<WebsocketServer>(() => new WebsocketServer());
public static WebsocketServer Instance
{
get
{
return lazyInstance.Value;
}
}
private const string TAG = "WebsocketServer";
private const string HOST_IP_ADDRESS = "127.0.0.2"; // localhost
private const int PORT = 38001;
public WebSocketServer socket;
private PacketHandler packetHandler = new PacketHandler();
public event EventHandler<EventArgs> RaiseOnScanDevice = new EventHandler<EventArgs>((a, e) => { });
public WebsocketServer()
{
Initialize();
}
public void Initialize()
{
socket = new WebSocketServer(IPAddress.Parse(HOST_IP_ADDRESS), PORT);
socket.AddWebSocketService<WebsocketServer>("/");
StartServer();
}
public void StartServer()
{
socket.Start();
}
public void StopServer()
{
socket.Stop();
}
protected override Task OnOpen()
{
return base.OnOpen();
}
protected override Task OnClose(CloseEventArgs e)
{
return base.OnClose(e);
}
protected override Task OnError(ErrorEventArgs e)
{
return base.OnError(e);
}
protected override Task OnMessage(MessageEventArgs e)
{
System.IO.StreamReader reader = new System.IO.StreamReader(e.Data);
string message = reader.ReadToEnd();
//Converting the event back to 'eventName' and 'JsonPayload'
PacketModel packet = packetHandler.OpenPacket(message);
HandleMessageFromClient(packet);
return base.OnMessage(e);
}
private void HandleMessageFromClient(PacketModel packet) {
var eventName = packet.EventName;
var data = packet.Data;
if (eventName == null || eventName.Equals(""))
{
return;
}
switch (eventName)
{
case SocketEvent.Hello:
Send("OK");
break;
case SocketEvent.ScanDevice:
ScanDevice();
break;
default:
break;
}
}
private void ScanDevice()
{
try
{
RaiseOnScanDevice(this, new EventArgs());
// or dispatch to Main Thread
System.Windows.Application.Current.Dispatcher.Invoke(new System.Action(() =>
{
RaiseOnScanDevice(this, new EventArgs());
}));
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
}
MainWindow.xaml.cs file
public partial class MainWindow : Window
{
public WebsocketServer WebsocketConnection
{
get { return WebsocketServer.Instance; }
}
public MainWindow()
{
InitializeComponent();
WebsocketConnection.RaiseOnScanDevice += SocketConnection_RaiseOnScanDevice;
}
private void SocketConnection_RaiseOnScanDevice(object sender, EventArgs e)
{
Console.WriteLine("SocketConnection_RaiseOnScanDevice");
}
The queue of messages is a good idea but you may want to use a lock to guard access to it. Most likely it won't be an issue but if you don't, you leave yourself open to the possibility of an error if the coroutine is reading from the queue as the websocket is writing to it. For example you could do something like this:
var queueLock = new object();
var queue = new Queue<MyMessageType>();
// use this to read from the queue
MyMessageType GetNextMessage()
{
lock (queueLock) {
if (queue.Count > 0) return queue.Dequeue();
else return null;
}
}
// use this to write to the queue
void QueueMessage(MyMessageType msg)
{
lock(queueLock) {
queue.Enqueue(msg);
}
}
I'm new in Microsoft Message Queue in Windows Server, I need to push, if the EmployeeID is NULL.
The Employee Model Class is
public class Employee
{
public string EmployeeID { get; set; }
public string EmployeeName { get; set; }
}
public void ValidationProcess(Employee emp)
{
if((emp != null) || (emp.EmployeeID == null))
{
// Push into Validation Exception Queue using MSMQ
}
}
Once the Data pushed into that Validation Exception Queue, it should be processed by separate process. Every 1hr the process need to initiate and it should call the following method
public void ValidationExceptionProcess(object obj)
{
// Some Inner Process
// Log the Error
}
Kindly guide me how to create and process it.
First Step:
Install MSMQs as a windows feature on the server/pc
Then:
- Create the queue if it does not exist
- Push the message in the queue asynchronously
Useful guide
Code example for pushing and retrieving messages from msmq:
public class ExceptionMSMQ
{
private static readonly string description = "Example description";
private static readonly string path = #".\Private$\myqueue";
private static MessageQueue exceptionQueue;
public static MessageQueue ExceptionQueue
{
get
{
if (exceptionQueue == null)
{
try
{
if (MessageQueue.Exists(path))
{
exceptionQueue = new MessageQueue(path);
exceptionQueue.Label = description;
}
else
{
MessageQueue.Create(path);
exceptionQueue = new MessageQueue(path);
exceptionQueue.Label = description;
}
}
catch
{
throw;
}
finally
{
exceptionQueue.Dispose();
}
}
return exceptionQueue;
}
}
public static void PushMessage(string message)
{
ExceptionQueue.Send(message);
}
private static List<string> RetrieveMessages()
{
List<string> messages = new List<string>();
using (ExceptionQueue)
{
System.Messaging.Message[] queueMessages = ExceptionQueue.GetAllMessages();
foreach (System.Messaging.Message message in queueMessages)
{
message.Formatter = new XmlMessageFormatter(
new String[] { "System.String, mscorlib" });
string msg = message.Body.ToString();
messages.Add(msg);
}
}
return messages;
}
public static void Main(string[] args)
{
ExceptionMSMQ.PushMessage("my exception string");
}
}
An other widely used way to do that would also be to use out of the box loggers which already contains this functionality like Enterprise Library or NLog which provide easy interfaces to do that.
For retrieving messages I would recommend a separate windows service which would periodically read messages and process them. An good example on how to do that is given here: Windows service with timer
Update: Windows Service Example:
MSMQConsumerService.cs
public partial class MSMQConsumerService : ServiceBase
{
private System.Timers.Timer timer;
public MSMQConsumerService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
this.timer = new System.Timers.Timer(30000D); // 30000 milliseconds = 30 seconds
this.timer.AutoReset = true;
this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.ProcessQueueMessages);
this.timer.Start();
}
protected override void OnStop()
{
this.timer.Stop();
this.timer = null;
}
private void ProcessQueueMessages(object sender, System.Timers.ElapsedEventArgs e)
{
MessageProcessor.StartProcessing();
}
}
and the MessageProcessor.cs
public class MessageProcessor
{
public static void StartProcessing()
{
List<string> messages = ExceptionMSMQ.RetrieveMessages();
foreach(string message in messages)
{
//write message in database
}
}
}
I am trying to raise an event in a DLL file refrenced to a windows forms project.
I have the following message when I run the program "Object is not set to an instace of an object":
namespace Server
{
public delegate void messageHnadler();
public class ClassServer
{
public event messageHnadler messageForChat
public string Message { get; set; }
public Socket listenerSocket;
public BinaryFormatter transBinary;
public Thread threadingServer;
public TcpListener listenerServer;
private List<TcpClient> connectedClients = new List<TcpClient>();
public bool OpenServer(string ipAddress, int PortNumber)
{
try
{
listenerServer = new TcpListener(IPAddress.Parse(ipAddress), PortNumber);//creating listener for clients to connect
listenerServer.Start();
threadingServer = new Thread(LoopThroughClients);
threadingServer.Start();
threadingServer = new Thread(GetMessage);
threadingServer.Start();
return true;
}
catch (Exception)
{
return false;
}
}
public void LoopThroughClients()
{
listenerSocket = listenerServer.AcceptSocket();
}
public void GetMessage()
{
while (true)
{
if (listenerSocket != null)
{
NetworkStream streamWithClient = new NetworkStream(listenerSocket);
transBinary = new BinaryFormatter();
string stringFromClient = (string)transBinary.Deserialize(streamWithClient);
if (stringFromClient != null)
{
Message = stringFromClient;
messageForChat();
}
streamWithClient = new NetworkStream(listenerSocket);
BinaryFormatter tranBinary = new BinaryFormatter();
tranBinary.Serialize(streamWithClient, stringFromClient);
stringFromClient = null;
}
}
}
In the windows forms project I signed the event to a function:
namespace Chat_Project_Server_UI
{
public partial class SeverUI : Form
{
OpenServerForm openServer = new OpenServerForm();
ClassServer serverForEvent = new ClassServer();
public SeverUI()
{
InitializeComponent();
openServer.ShowDialog();
serverForEvent.messageForChat += new messageHnadler(serverForEvent_messageForChat);
OpenningServer();
}
public void OpenningServer()
{
if(openServer.IsConnected)
{
ChatTextBox.AppendText("SERVER OPEN!\n");
}
else
{
ChatTextBox.AppendText("Faild to open server...\n");
}
}
private void test_Click(object sender, EventArgs e)
{
ChatTextBox.AppendText("aaaaa");
}
public void EventHolder()
{
}
void serverForEvent_messageForChat()
{
ChatTextBox.AppendText(serverForEvent.Message);
}
}
Always check if a handler has been assigned first as follows:
var handler = messageForChat;
if (handler != null)
handler()
Standard Way to handle Events inside the Class that defines it Is to Create A Method Named OnXxx and Always Check whether the Event is Assigned Handler Or Not
in your case define new function as following:
protected void OnMessageForChat(){
//protected modifier allows subclasses to raise the event by calling this method
if (messageForChat!=null)messageForChat();
}
And WhenEver you want to raise the event Just Call this Function
I've been trying to implement a windows service that would keep vpn connection alive. I've found that it is possible to achieve using DotRas library by subscribing to RasConnectionWatcher.Disconnected event:
public class SampleService {
public SampleService() {
this.shutdownEvent = new ManualResetEvent(false);
this.connectionWatcher = new RasConnectionWatcher();
this.connectionWatcher.Disconnected += onVpnDisconnected;
}
// redial
void onVpnDisconnected(Object sender, RasConnectionEventArgs e) {
this.DialUp();
}
void DialUp() {
// connection setup is omitted
// keep the handle of the connection
this.connectionWatcher.Handle = dialer.Dial();
}
public void Start() {
this.thread = new Thread(WorkerThreadFunc);
this.thread.IsBackground = true;
this.thread.Start();
}
public void Stop() {
this.shutdownEvent.Set();
if(!this.thread.Join(3000)) this.thread.Abort();
}
private void WorkerThreadFunc() {
this.DialUp();
while(!this.shutdownEvent.WaitOne(0)) Thread.Sleep(1000);
}
}
When I start the service vpn connection opens without any problem, but when I manually interrupt the connection it seems that Disconnected event doesn't fire up.
solution 1
Found similar question/answer here:
http://social.msdn.microsoft.com/Forums/en-US/56ab2d0d-2425-4d76-81fc-04a1e1136141/ras-connection-application-and-service?forum=netfxnetcom.
solution 2
Got an answer from Jeff Winn yesterday:
https://dotras.codeplex.com/discussions/547038
public class VpnKeeperService : IService {
private ManualResetEvent shutdownEvent;
private RasConnectionWatcher connWatcher;
private Thread thread;
public VpnKeeperService() {
this.shutdownEvent = new ManualResetEvent(false);
this.connWatcher = new RasConnectionWatcher();
this.connWatcher.EnableRaisingEvents = true;
this.connWatcher.Disconnected += (s, args) => { this.DialUp(); };
}
Boolean DialUp() {
try {
using(var phoneBook = new RasPhoneBook()) {
var name = VpnConfig.GetConfig().ConnectionName;
var user = VpnConfig.GetConfig().Username;
var pass = VpnConfig.GetConfig().Password;
var pbPath = VpnConfig.GetConfig().PhoneBookPath;
phoneBook.Open(pbPath);
var entry = phoneBook.Entries.FirstOrDefault(e => e.Name.Equals(name));
if(entry != null) {
using(var dialer = new RasDialer()) {
dialer.EntryName = name;
dialer.Credentials = new NetworkCredential(user, pass);
dialer.PhoneBookPath = pbPath;
dialer.Dial();
}
}
else throw new ArgumentException(
message: "entry wasn't found: " + name,
paramName: "entry"
);
}
return true;
}
catch {
// log the exception
return false;
}
}
public void Start() {
this.thread = new Thread(WorkerThreadFunc);
this.thread.Name = "vpn keeper";
this.thread.IsBackground = true;
this.thread.Start();
}
public void Stop() {
this.shutdownEvent.Set();
if(!this.thread.Join(3000)) {
this.thread.Abort();
}
}
private void WorkerThreadFunc() {
if(this.DialUp()) {
while(!this.shutdownEvent.WaitOne(0)) {
Thread.Sleep(1000);
}
}
}
}
Hope it helps someone.
Im trying to forward an event OnClientMessage from my class Client over the class Server to outside my libary.
Client.cs
public class Client
{
private TcpClient tcpClient;
private StreamWriter writer;
private Boolean alive = true;
private int id;
public delegate void OnClientMessageHandler(Client sender, String message);
public delegate void OnClientDisconnectHandler(Client sender);
public event OnClientMessageHandler OnClientMessage;
public event OnClientDisconnectHandler OnClientDisconnect;
public Client(TcpClient tcpClient, int id)
{
this.tcpClient = tcpClient;
this.id = id;
writer = new StreamWriter(tcpClient.GetStream());
new Thread(() =>
{
Listen(new StreamReader(tcpClient.GetStream()));
}).Start();
}
void Listen(StreamReader reader)
{
while (tcpClient.GetStream().DataAvailable && alive)
{
OnClientMessage(this, reader.ReadLine());
Thread.Sleep(150);
}
}
public void Write(String message)
{
writer.WriteLine(message);
writer.Flush();
}
public int GetID()
{
return id;
}
public void Close()
{
alive = false;
writer.Close();
tcpClient.Close();
OnClientDisconnect(this);
}
}
Server.cs
public class Server
{
private IPAddress serverIP;
private short serverPort;
private TcpListener serverListener;
private int serverClientCount;
public List<Client> serverClients = new List<Client>();
private Boolean running;
public delegate void OnClientMessageHandler(Client sender, String message);
public delegate void OnClientDisconnectHandler(Client sender);
public event OnClientMessageHandler OnClientMessage;
public event OnClientDisconnectHandler OnClientDisconnect;
public Server(IPAddress ip, short port, Boolean autoStart = true)
{
this.serverIP = ip;
this.serverPort = port;
if(autoStart)
OpenServer();
}
public void OpenServer()
{
serverListener = new TcpListener(serverIP, serverPort);
serverListener.Start();
running = true;
while (running)
{
if (serverListener.Pending())
{
TcpClient tcpClient = serverListener.AcceptTcpClient();
new Thread(() =>
{
Client client;
client = new Client(tcpClient, serverClientCount);
client.OnClientMessage += new Client.OnClientMessageHandler(OnClientMessage);
client.OnClientDisconnect += new Client.OnClientDisconnectHandler(OnClientDisconnect);
serverClients.Add(client);
serverClientCount++;
}).Start();
}
else
{
Thread.Sleep(150);
}
}
}
public void WriteToClient(Client client, String message)
{
client.Write(message);
}
public void WriteToAll(String message)
{
serverClients.ForEach(client => client.Write(message));
}
public void Shutdown()
{
running = false;
serverClients.ForEach(client => client.Close());
serverListener.Stop();
}
}
Now when the event is firing the application crashes with Delegate to an instance method cannot have null 'this'.
Are I'm doing something wrong or isn't this the right way to forward an event?
This is pretty unique, never once seen anybody do this. It is a regression in the .NET Framework, 3.5 gives you a much better exception. Basic problem is that you made the event subscribe itself. A simple version to repro that crash:
using System;
class Program {
public static event Action Kaboom;
static void Main(string[] args) {
Kaboom += new Action(Kaboom); // 3.5 raises an exception here
var handler = Kaboom;
if (handler != null) handler(); // kaboom
}
}
You are not actually "forwarding" the event. Untangle your names and code. Add, say, a Fire() method.