Transfer data from Windows Service to Console Application repeatedly - c#

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);
}
}
}

Related

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.

How to invoke WCF method programmatically from windows service

I have successfully compiled and run Windows Service with WCF. With installutil, the Windows Service is successfully getting installed and started. I think I am at the end of my development and just need to invoke/call the method DoJobs() inside WCF. I don't need any user interaction and so I don't have any Windows forms or anything. I just want to invoke/call my WCF function programmatically just after serviceHost.Open();
The base address in app.config file is
http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary1/Service1/
I am deploying my WCF from Windows service with the following code.
// Create a ServiceHost for the CalculatorService type and provide the base address.
serviceHost = new ServiceHost(typeof(WcfServiceLibrary1.Service1));
// Open the ServiceHostBase to create listeners and start listening for messages.
serviceHost.Open();
I have also added the service reference and created the below proxy, but not sure of its use.
WcfServiceLibrary1.WCFServiceRef.Service1Client
I have searched tutorials, the examples show how to invoke the WCF function on button_click event of any form after running Windows service. I just want to do that programmatically on start-up of Windows Service.
EDIT: The code inside my DoJobs() fetches the active tab url of firefox with DDE Client, which throws exception when done only in a Windows Service project but runs successfully when done in WCF project. Please see this for reference.
So I made a C#.Net solution with WCF called from a Windows Service and then I called DoJobs() inside Windows Service as shown below.
WcfServiceLibrary1.WCFServiceRef.Service1Client wcfObj = null;
...
protected override void OnStart(string[] args)
{
if (serviceHost != null)
{
serviceHost.Close();
}
serviceHost = new ServiceHost(typeof(WcfServiceLibrary1.Service1));
serviceHost.Open();
if (wcfObj == null)
{
wcfObj = new WcfServiceLibrary1.WCFServiceRef.Service1Client();
wcfObj.DoJobs();
}
}
But, it makes the call happen at the windows service layer, and is throwing the same DdeClient exceptions.
Can the base address url help any way to programmatically invoke DoJobs() in Web-Service? OR there are some other solutions.
Any help is highly appreciated.
Thanks.
This is my aggregated answer from my various comments I made to your post and to Noctis's answer (specifically that we did not know you were using DDE in the OP):
You can't use Dynamic Data Exchange (DDE) in a Windows Service because the latter does not have a message pump. Also DDE requires a Window handle to be passed as a parameter to DDE functions. You can use DDE in programs which do have a message pump does as a WinForms app. See this article for more information
Once your GUI app is running you can either minimize it to a Sys Tray icon or hide the app completely so the user is unaware. Regardless of its visible nature you should have no problem utilising DDE since it will have a message pump.
Now it may be the case you could add a message pump to a Windows Service but I wouldn't recommend it because it falls into the category of because you can do a thing, does not mean you should do a thing. A topic for another time. It's very similar to a recent SO question about how to display a WinForm in a console app - by default you can't and if you managed to you end up with an odd hybrid with much re-inventing of wheels. Not to mention its an ugly hack.
In summary, my best advice is to proceed with a GUI app.
Assuming you have :
// I'm assuming this is your proxy?
var proxy = WcfServiceLibrary1.WCFServiceRef.Service1Client;
// All you need to do is :
proxy.DoJobs() ;
Having seen your update and Micky`s answers, I'm just wondering why you're using DDE. Not sure what your requirements look like, but you can always use your MSMQ to send messages and queue things.

Get information about internal state of Windows Service

I have a Windows Service that I am writing in .NET C#. The service is going to act as a file processor. It just watches a directory for File Created events and adds these files to a queue for processing. A separate thread pulls files from the queue and processes them.
My question is whether there is a way to query the windows service to get its "state". I would like to be able to query the service some way and see a list of the files currently waiting in the queue etc.
I know this can be done in Linux via the /proc file system and I was wondering if there is anything similar for Windows. Any tips/pointers would be greatly appreciated.
If you are looking for a non-UI method (eg to write the names to a file or to standard output), it is possible to use the ExecuteCommand Method on the service.
ServiceController sc = new ServiceController("ServiceName");
sc.ExecuteCommand(255);
This simply passes this command to your your service and your service will handle it via the OnCustomCommand
protected override void OnCustomCommand(int command)
{
base.OnCustomCommand(command);
if (command == 255
{
... // Your code here
}
}
You may need to store your queue/service status in a static variable so you can access it from the OnCustomCommand routine.
You could create a hosted WCF service inside of the windows service with whatever methods you need to access the state.
http://msdn.microsoft.com/en-us/library/ms733069.aspx
WCF would be good to do that, especially it can be hosted inside of Windows Service. Might be in your case it makes sense to use XML-RPC with WCF

C#: GUI to display realtime messages from Windows Service

I've written a C# windows service which can write messages to a custom EventLog or to any number of files. These messages are all marked with some priority (so, for example, only ERRORs and WARNINGs get stored in the EventLog, but if desired a lot more can be stored to a file).
What I'd like to do now is create a GUI that can listen for these messages and display them in real-time. Allowing a user to watch the current messages (at whatever their desired priority level), without the need to store everything to a file. I assume this is a separate program with some form of hook into the service, but I'm unsure of where to start.
This is my first real windows service, so I seem to be missing some keywords for finding out how to do this... Are there any code samples, tutorials, references, etc. for how to do something like this?
UPDATE
A lot of helpful answers, I love it when there's many ways to solve a problem! I think I'm going to implement a self-hosting WCF based solution. I'm still very light on the details as I'm trying to learn about WCF (I believe it will prove quite useful for me in other projects)... but thus far, I've found the videos here to be the most helpful as an intro how-to.
What you can do is have the windows service have way of registering for an event (you can do this through using Windows Communication Foundation). When your error comes up, it fires that event, and your winforms app will be notified. It's called a duplex contract:
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/0eb69998-0388-4731-913e-fb205528d374/
http://msdn.microsoft.com/en-us/library/ms731184.aspx
Actually the really cool thing is that you can have multiple applications listening this way too. So you can display it on screen, and have another application log it etc. without the two external apps knowing anything about each other.
I know this has already been mentioned, but use Windows Communication Foundation (WCF). Specifically, use the Publish-Subscribe Framework developed by Juval Lowy, author of Programming WCF Services. The details are described in this excellent MSDN article, and the source code is available for free at Lowy's website.
The neat thing about this framework is that it decouples the publisher, e.g., your Windows service, from any subscribers, e.g., your GUI. The publisher "publishes" events that are of interest to the Pub/Sub Service, which is always available. From the publisher's point of view, it doesn't matter if there are any subscribers or not. The Pub/Sub Service takes care of routing events to any and all registered subscribers. In this way, your Windows service publishes events as they occur, your GUI will subscribe/unsubscribe to the Pub/Sub Service when it loads/exits, and the Pub/Sub Service will notify your GUI as events occur.
I have used this setup in my project, and it works extremely well.
I've actually used the BitFactory Logger that has a socket logger that you can use for this purpose.
What you're describing is inter-process communication, which can get messy.
The easiest and most elegant, but probably least reactive, is to have the service write entries as small text files (or append to a log), and have your GUI use a FileSystemWatcher to detect new files or updates to the log file, and read the file. You have to ensure that the service opens the file for appending in a "shared" manner, allowing read-only access while it's writing. Otherwise, you'll block one process or the other, probably causing lost messages.
Processes can communicate through some built-in pipelines. if your service writes messages to its StandardOutput pipe, the GUI can remotely attach a listener and receive events when messages are written. This is probably the most elegant non-file way to do what you want. Research the Process class, especially the OutputDataReceived event. You'll have to go look for the process from your GUI by some uniquely identifying information, using GetProcess().
You need to look for "synchronization" and "inter-process communication". In your case the service would use the global event or semaphore to signal presence of data, and GUI process would check event/semaphore state and read the updates from event log or from file.
There exist more complicated scenarios, but the above is a good starting point.
Observer pattern!
Perhaps a delegate for all observable models that you can hook into with your service?
.NET remoting over IPC channel.
I've found that a Named Pipe communication with a System Tray application was the simplest way to display notifications from a Windows Service. This is because in Windows 10 services run with different permissions than the logged in user, so the notification app needs to perform IPC with the service.
Here you could put this into the server:
using System;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleServerApp
{
class Program
{
static void Main(string[] args)
{
StartServer();
Task.Delay(1000).Wait();
}
static void StartServer()
{
Task.Factory.StartNew(() =>
{
var server = new NamedPipeServerStream("PipesOfPiece");
server.WaitForConnection();
StreamReader reader = new StreamReader(server);
StreamWriter writer = new StreamWriter(server);
while (true)
{
var line = reader.ReadLine();
writer.WriteLine(String.Join("", line.Reverse()));
writer.Flush();
}
});
}
}
}
Then put this into your client:
using System;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleClientApp
{
class Program
{
static void Main(string[] args)
{
//Client
var client = new NamedPipeClientStream("PipesOfPiece");
client.Connect();
StreamReader reader = new StreamReader(client);
StreamWriter writer = new StreamWriter(client);
while (true)
{
string input = Console.ReadLine();
if (String.IsNullOrEmpty(input)) break;
writer.WriteLine(input);
writer.Flush();
Console.WriteLine(reader.ReadLine());
}
}
}
}
Then change your ConsoleServerApp to a Winforms application so that it can display the notification whenever the windows service sends it a message:
public Form1()
{
InitializeComponent();
StartServer();
Task.Delay(_threadJoinTimeout).Wait();
}
public void DisplayMessage()
{
this.notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
this.notifyIcon1.BalloonTipText = "Welcomd!";
this.notifyIcon1.BalloonTipTitle = "Title";
this.notifyIcon1.ShowBalloonTip(2000);
}
void StartServer()
{
Task.Factory.StartNew(() =>
{
var server = new NamedPipeServerStream("PipesOfPiece");
server.WaitForConnection();
StreamReader reader = new StreamReader(server);
while (true)
{
var line = reader.ReadLine();
DisplayMessage();
}
});
}
Then put the ConsoleClientApp into your Windows Service.
For details on the pipe please see Example of Named Pipes
For the System Tray application please see http://www.tutorialspanel.com/create-system-tray-icon-windows-forms-application-using-c-vb-net/#:~:text=Below%20is%20an%20example%20of%20how%20to%20create,Step%203.%20Add%20an%20icon%20to%20the%20NotifyIcon
Here are tips on using the TopShelf NuGet package which allows you to debug your Windows Service as a Console Application: https://www.codeproject.com/Articles/881511/SignalR-with-Self-hosted-Windows-Service

Categories