How to package MSMQ (or similar) server into an application? - c#

I'm putting together an application that is intended to install copies of itself in a downstream server(s). I've been reading about RabbitMQ, and am very interested in using message queueing when the upstream/downstream applications talk to each other. From what I can tell with both RabbitMQ and MSMQ, the server/broker component needs to be installed first either from an installer or a script. I'd like to use a NuGet package or similar so the upstream application can remotely install a copy of itself downstream without having someone (or a script) install the prerequisite, as this is meant to be unattended all the time.
My question - is there a message queueing library available where I can embed it into my application for both the client and server components of MQ?
The idea is to do something like this (psuedo-code):
class Program
{
static void Main(string[] args)
{
MyQueueServer.Start();
MyQueueServer.MessageReceived += FancyCallback;
}
static void FancyCallback(object sender, CustomEventArgs e)
{
ReadMessageAndDoStuff(e);
}
static void SendMessage()
{
string message = "hello server";
var sender = new MyQueueClient(serverConfigDetails);
sender.Send(message);
}
}
UPDATE:
Looks like ZeroMQ may be the way to go, but it looks like I'm missing out on durability bit by persisting stuff to disk. I'm also unclear if ZeroMQ will keep trying to deliver a message if the remote host is offline. The Google says you need to roll your own implementation for these kinds of things. I'm willing to do this, but still hopeful for a different solution that I can take advantage of.

Related

Azure Service Bus - How to Add Topic Subscriber Programmatically

I'm trying to implement a basic pub/sub system with dynamic subscribers. I need to dynamically register a topic subscriber in my .NET APIs, but it seems like I can only do that manually from the Azure Portal. When my program starts, I want to be able to register a subscriber to a topic in the format of subscribername-{timestamp} because I want to be able to deploy as many staging/dev versions as I want without having to manually create these subscribers each time.
I feel like this is a fundamental feature that I'm just blindly missing. I can do this when working with queues, but if I try to do the same with a topic, I get continuous errors of that subscriber path not found. I have searched the internet to no end and while I have found SOME solutions, they are very old and often not compatible with .NET 5 or the package is deprecated. I'm feeling like I'm going against the grain and missing something with what I'm coming up with, so I'd like to get some input on what the proper practice is for this.
I'm using Azure.Messaging.ServiceBus for publishing and subscribing currently. Below is some code -
var processor = ServiceBusClient.CreateProcessor(TopicName, $"DynamicSubscriber-{DateTime.Now}");
try
{
processor.ProcessErrorAsync += ErrorHandler;
processor.ProcessMessageAsync += MessageHandler;
await processor.StartProcessingAsync();
}
catch (Exception e)
{
await processor.DisposeAsync();
await ServiceBusClient.DisposeAsync();
}
finally
{
Console.WriteLine("Press a key to exit.");
Console.ReadLine();
}
Thank You #PeterBons! Yes, when updating/creating/fetching/deleting the Service Bus entities, ServiceBusAdministrationClient is the client Class to be used.
Also, There are few error details given this article when using the method of Queue with ServiceBusAdministrationClient and this SO Thread.
The ServiceBusTopicSubscription class is used to setup the Azure Service bus subscription. The class uses the ServiceBusClient to set up the message handler, the ServiceBusAdministrationClient is used to implement filters and add or remove these rules. The Azure.Messaging.ServiceBus Nuget package is used to connect to the subscription.

Transfer data from Windows Service to Console Application repeatedly

Here is my scenario, I have a windows service that runs a task every 20 minutes, the task is: requesting updates from an API hosted by a remote website.
The response is a list of JSON objects, When the Service receives the list, it carries out a set of operations then appends more JSON objects, finally the service must push the list to a running console application.
My very specific question is: how to transfer this data from the windows service to the console App both directly and professionally
By directly I mean without intermediate solution like writing in a temp file or saving in SQL table ... etc.
By professionally I mean the best optimal solution especially without p/Invoke from the service to the console App.
You would definitely need a medium to communicate between these two processes. The communication can be done in a lot of ways on the same system.
With your explanation in Question it looks like one way communication. May be you can go for Inter-process communication via sockets(raw level) or Use a messaging framework for communication(WCF/SignalR) or you can even use a Message Queue system(MSMQ/RabbitMQ) etc.
You can get a specific answer if you can narrow down your question.
A nice, clean, 'modern' way of doing this, would be to host a Web API directly in the console application, and accept JSON input.
This is relatively easy to set up, and very easy to test and use.
Other methods include .NET remoting (which is not very modern any more), some other kind of service, like WCF, or any of the multitude of windows IPC methods.
I wrote an answer here that has some applicable code. Basically, the OP there wanted to send strings from a Windows Forms application to a console application and have the console application print the strings.
My recommendation is to use a Message Queue.
A few quick notes: first, you may have to enable the feature in Windows if you've never done so. Also, I guess under certain configurations of Windows you can't create the Message Queue directly from C#; if that's the case for you, you can create it manually (or there's probably a way to do it as part of an install script or something).
Here's the Windows Forms code:
private void button1_Click(object sender, EventArgs e)
{
// Or whatever name you end up calling it if you created the queue manually
const string myQueue = ".\\myQueue";
// It's possible that this won't work on certain computers
// If not, you'll have to create the queue manually
// You'll also need to turn the Message Queueing feature on in Windows
// See the following for instructions (for Windows 7 and 8): https://technet.microsoft.com/en-us/library/cc730960(v=ws.11).aspx
if (!MessageQueue.Exists(myQueue))
{
MessageQueue.Create(myQueue);
}
using (MessageQueue queue = new MessageQueue(myQueue))
{
queue.Formatter = new XmlMessageFormatter(new[] { typeof(string) });
queue.Send("Test");
}
}
Console application:
static void Main(string[] args)
{
// Or whatever name you use
const string myQueue = ".\\myQueue";
// See my comment on the corresponding line in the Windows Forms application
if (!MessageQueue.Exists(myQueue))
{
MessageQueue.Create(myQueue);
}
MessageQueue queue = new MessageQueue(myQueue);
queue.Formatter = new XmlMessageFormatter(new[] { typeof(string) });
while (true)
{
Message message = queue.Receive();
string messageText = message.Body.ToString();
// Close if we received a message to do so
if (messageText.Trim().ToLower() == "exit")
{
break;
}
else
{
Console.WriteLine(messageText);
}
}
}

C# windows service subscribed to webserver

I'm working on an intranet website.
All users should get desktop popups from the webserver whenever something new is posted on the website.
I was looking to make my own windows service that would subscribe to the server ( Making use of something like SignalR ) and then this service would show a simple popup notifying the user whenever the server sends out a message.
But instead of building this myself i was wondering if something like this isn't already out there. I've been looking around a bit but couldn't find anything.
I'm mainly a web developer and have never built a windows service or C# desktop application so i would prefer using some existing code.
Does anyone know of such a thing ?
For building a Windows Service try Top Shelf: http://docs.topshelf-project.com/en/latest/
In general it is easy as one, two, three...
public class TownCrier
{
readonly Timer _timer;
public TownCrier()
{
_timer = new Timer(1000) {AutoReset = true};
_timer.Elapsed += (sender, eventArgs) => Console.WriteLine("It is {0} and all is well", DateTime.Now);
}
public void Start() { _timer.Start(); }
public void Stop() { _timer.Stop(); }
}
public class Program
{
public static void Main()
{
HostFactory.Run(x =>
{
x.Service<TownCrier>(s =>
{
s.ConstructUsing(name=> new TownCrier());
s.WhenStarted(tc => tc.Start());
s.WhenStopped(tc => tc.Stop());
});
x.RunAsLocalSystem();
x.SetDescription("Sample Topshelf Host");
x.SetDisplayName("Stuff");
x.SetServiceName("Stuff");
});
}
}
I'm working on an intranet website. All users should get desktop
popups from the webserver whenever something new is posted on the
website.
using timer is not a good technique over here as updates are not guaranteed in particular interval or session .but you can take that as an option based on the need.
I was looking to make my own windows service that would subscribe to
the server ( Making use of something like SignalR ) and then this
service would show a simple popup notifying the user whenever the
server sends out a message.
Yes exactly like a chat application that would frequently have messages and users get a pop up.ASP.NET SignalR is a library for ASP.NET developers that simplifies the process of adding real-time web functionality to applications. Real-time web functionality is the ability to have server code push content to connected clients instantly as it becomes available, rather than having the server wait for a client to request new data.
But instead of building this myself i was wondering if something like
this isn't already out there. I've been looking around a bit but
couldn't find anything.
References for SignalR Link1,Link2,Link3
I'm mainly a web developer and have never built a windows service or
C# desktop application so i would prefer using some existing code.
Making C# desktop or windows service is not a big deal as you already are a programmer.Some existing codes for updations pop up is here.
for the signalr Server side, I would suggest you use a C# winform.
for the client side, you can use JavaScript inside any html file to 'receive' the message from the signalr Server, then you can popup an alert message or whatever you want, however, in this case you have to make sure the users are browsing that html file in a browser, otherwise the message won't be received.
there's no ready code since signalr support different types of servers as well as different types of clients, I believe you need to write your own code. Actually Signalr is quite easy to use, write your own code may be faster than using the others.
This question: SignalR Chat App in WinForm With Remote Clients looks like it might point you inthe right direction. Specifically this article:
https://damienbod.wordpress.com/2013/11/01/signalr-messaging-with-console-server-and-client-web-client-wpf-client/
you could probably use DesktopToast: https://github.com/emoacht/DesktopToast
or Growl: http://www.growlforwindows.com/

Using Static Wrapper Class

In my search for a WebSockets library, I came across this website that provides Delphi and C# versions in download section. It grabbed my attention especially because the client-side of my application is developed using Delphi, and I'm trying to develop the server-side using C#.
Looking at the Chat sample for C#, I realized that it uses a wrapper class (sgcWebSocketLib) around the unmanaged DLL written in Delphi. Here is an excerpt from sgcWebSocketLib.cs:
public sealed class sgcWebSocketLib
{
private static volatile sgcWebSocketLib instance;
private static object syncRoot = new Object();
private sgcWebSocketLib()
{
}
public static sgcWebSocketLib Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new sgcWebSocketLib();
}
}
return instance;
}
}
... //the rest is omitted
}
and the code from Start button in Chat server (a typical WinForms application):
private void btnStart_Click(object sender, EventArgs e)
{
string vOptions = "";
... //setting options according to UI values
sgcWebSocketLib.Instance.Server_LoadOptions(vOptions);
sgcWebSocketLib.Instance.Server_Start();
}
Now, here is the actual question: this Chat server uses a static property of sgcWebSocketLib class, and starts sending/receiving WebSocket stuff. Can I use the same approach in an ASP.Net application (WebForms or MVC)? Can I write the Chat server in ASP.Net using this wrapper class?
PS: I know there is SignalR and maybe others. But it has some limitations (IIS 8, Windows Server 2012 requirement for WebSocket) beside the unanswered communication problem with a Delphi VCL client.
Yes you can.
You will just have to pay attention to the Idle Time-out settings for your worker process (defaults to 20 minutes) as well as your Recycling settings (default is once every 29 hours). You may want to disable both settings if you want your application to never be recycled / go idle regardless of other parameters.
Recycling / idling will cause the worker process to shutdown, thus you'll lose any static variable and they'll have to be re instantiated when the process starts back up.
Check this answer for more info.
In IIS < 8 you won't be able of bind the WebSocket port to the same port than the web application (that is exactly what IIS8 can do)
Even with IIS8, the AppDomain is unable to recycle if there are WebSockets connected. So using the info that #Xeaz provided may be good idea. Usually I keep them in separate applications, since there is no point in mixing a connection oriented app (WebSockets), with a request-response one (regular HTTP). The only favorable point in doing that with IIS8 is the fact that both can share the port, but that is not really an issue aside of open/map an additional TCP port in the network, since cookies do not mind the port and WebSocket is not even affected by the SOP.
If the client is using the WebSocket protocol RFC6455 correctly, it should not matter which implementation is connecting to. I develop a websocket server for .NET/Mono 4.5 that works on Windows 7, take it a look if you go with the .NET server option.

.NET Remoting - How can the Server update the client?

Right now, I am in prototyping phase. So I am just getting started.
Situation:
Server - Will be run tests and publish progress to Client, must be low impact, no webserver, possibly running xp embedded or xp home.
Client - Initiate tests and receive progress report. running xp pro.
The two machines are connected via ethernet. I would like to use .NET remoting to communicate between the two machines, and I would like to use events to update the client with new results from the server, but I've read that events are unreliable in these conditions. How should I do this? Could the Server connect to the client and use remoting to publish the events? Would that work okay?
I once deployed a system wich used remoting, and where the server launched some events to which the client could subscribe to.
In order to make it possible, you have to set the typeFilterLevel to full, and, you also have to create an 'intermediate' object that is known on the client and on the server in order to be able to handle your events.
For instance:
This is the class that is known on the server & on the client side.
public abstract class MyDelegateObject : MarshalByRefObject
{
public void EventHandlerCallback( object sender, EventArgs e )
{
EventHandlerCallbackCore(sender, e);
}
protected abstract void EventHandlerCallbackCore(object sender, EventArgs e );
public override object InitializeLifetimeService() { return null; }
}
At the client-side, you create another class which inherits from the above class, and implements the actual logic that must be performed when the event is raised.
public class MyConcreteHandler : MyDelegateObject
{
protected override EventHandlerCallbackCore(object sender, EventArgs e)
{
// do some stuff
}
}
You simply attach the eventhandler to the event of the remote object like this:
MyConcreteHandler handler = new MyConcreteHandler();
myRemoteObject.MyEventOccured += new EventHandler(handler.EventHandlerCallback);
Offcourse, if you update Winform controls in your EventHandler class, that class should also implement ISynchronizeInvoke.
Since you're still in the prototyping stage, you might want to consider using Windows Communication Foundation (WCF) rather than remoting. WCF has built-in support for publish-subscribe scenarios, and already contains all the functionality of .NET remoting and web services (from what I understand).
By the Server connecting to the client, you are actually inverting the model and causing the server to become the client and vice versa.
You are better off having the client initiate tests, and poll the server for status updates.
Your choice of remoting is not really a big deal (and makes no impact on the opinion I offered), but you may want to investigate its replacement (WCF) instead of spending time on a 'replaced but still supported' technology.

Categories