Calling a public method on windows service - c#

I have a timer in a windows service (.NET C#). I need to be able to change the elapsed value from an external program. If the timer is currently running, I need to be able to shorten the time elapsed value from an external program. I was thinking of having a public method in the service that would change the timer elapsed value and restart the timer, but can an external program call a public method on a windows service?

In short, it's not possible to directly call functions in another process. The process containing the function you want to access (in this case, your Windows service) will need to expose it through some sort of IPC (inter-process communication). What type of IPC you choose will probably depend on how complex the communication needs to be, and whether or not the "client" is a .NET application.
If your needs are simple (e.g. just setting a timer value), or if your client does not use .NET, using named pipes (or TCP, if you need to access the service from another physical machine) is probably your best bet. Both named pipes and TCP give you a Stream that you can write messages to and read on the other end.
If you need to expose many different functions or send and receive complex data types, and if you are using .NET on both ends, .NET Remoting or WCF is probably best. .NET Remoting is simpler but has more constraints; WCF is very flexible but has a steeper learning curve.

Yes this is possible.
You might want to consider created a NetNamedPipe endpoint on your service and controlling the service through that interface.
NetNamedPipeBinding binding = new NetNamedPipeBinding();
MyService myService = new MyService(binding,
new EndpointAddress("net.pipe://localhost/MyService"));
myService.ResetTimer(30);

You cannot call a method in a Windows service process directly, but you can have the Windows service expose this function as a WCF service, for instance. The Windows service would be acting as a service host as well. That's possible and not complicated.

Older (non WCF) services can use .NET Remoting. Have a look here for some info on how to get started. This is the pre-WCF way of communicating between applications across process boundaries.

Related

Interprocess communication between 3 modules

I am looking for advice on the best approach for doing inter-process communication.
The solution consists of 3 projects.
GUI: This will only display messages to the user and get user input
Windows Service: Communicates with the UI and runs the 3rd module using elevated credentials
Worker: Internal DLL that will perform the actual work
I need a way to make the worker communicate with the GUI directly to send and receive updates.
I have two ways in mind to do it (will be happy to see more suggestions):
Use two named pipes. One for the GUI<>Service communication. And the other for GUI<>Worker communication
Raise an event from Worker to Service. And use WCF callback from service to UI
What will be the best way to implement the communication?
NOTE: The problem here is the GUI<>Worker communication. Not the UI<>Service communication.
1) WCF is officially recommended way to implement interprocess communication (tcp or named pipes are fastest), it replaces remoting (but always use serialization/deserialization).
In advanced scenarios communication can be implemented using
Memory mapped files;
Service Bus. (Service Bus allows to create loosely coupled components/communication. Google for nservicebus, rabbitmq, masstransit etc);
Something like Web Sockets or SignalR (consider using this if you have browser/javascript client/GUI).
2) If your Worker is just library (.net assembly) - it will work within Service process. In this case you dont need to invent something to pass data/events from Worker to GUI, all communication (duplex, I suppose, with subscribing to service events) will be perfomed between GUI and Service (Service only delegate some work to Worker via regular .net calls)
3) Sometimes we need something like dispatcher between services, client and server. You can find some information here.

can't find main static main method in WCF

I created WCF service and faced with a problem. I need to update database periodically, but i couldn't find static method like Main, that whould do it without client interaction. What can i do??? What wold you suggest in such case?
There is no Main method (or similar entry point) in WCF. You need to host your WCF service in another process (such as a Windows service, or IIS or self host) to "activate" it and make it available to other processes.
One of the concepts in WCF is that you write your service code to do the function you need without having to worry about infrastructure and hosting. Once you have written your service logic, you can then decorate and configure your service to expose it to other processes. Using this approach means you can change how your service is exposed to other processes without re-writing the actual service logic - you essentially just change your configuration. Hence, a main entry point is specific to how you choose to host and expose your WCF service to the outside world.
Just Google around for "WCF hosting" and you will find lots of information.
If you don't need to expose your service logic to an external process (which sounds like maybe the case from your question) then maybe you don't need to use WCF and you can just write a plain old Windows Service.
If your wcf service is self hosted then you can do it in your application before publishing the service.
If it is in IIS then there really isn't application_start kind of thing since the host may be created on first request. See WCF application start event

How to call Windows services created with .NET?

I have a basic windows service which does some conversions of data. There's decoupled GUI which allows user to changes some configuration and this needs to be proprogated to the Windows Serivice running. Both of them are running the same box and implemented using C# .NET. Which is the best way to communicate to the service other than interprocess communication mechanisms like mutex, events etc.
Also I'd like to avoid to implement it as a web service because it's not a webservice.
I would use a WCF Service to communicate.
You can use netNamedPipe binding but that might not work on Windows 2008/Windows 7 since the Service runs in session 0 and all user code runs in sessions >0 and they would not be able to communicate.
So I used netTcpBinding in my own project.
If the processes are not going to move to different machines, you can use memory mapped files as the communication mechanism.
If that's not the case, WCF is a good option.
Since you're dealing with configuration data for the service, I would persist it somewhere. Database, file, registry, etc. UI writes the information and the service reads it when appropriate (e.g. each run).

How can I tell if another app has registered an IPC Remoting channel?

So I have an application which has a .NET API available. Their API library communicates with their main application through .NET remoting calls. In order to use the API, the application must be up and running already.
So, I have an instance where I need to programmatically start the application and then instantiate one of the API objects, which attempts to open an IPC remoting channel to the main app. The problem is, after I start the process, there are a few seconds between startup and when the application registers the channel. If I try to instantiate an API object before the channel is registered, it biffs out.
It doesn't help that I know very little about .NET remoting.
How do I determine from MY application which uses their API if THEIR application has registered the channel for communication so I know it's okay to instantiate their API object?
Try this:
using System.Net.NetworkInformation;
using System.Net;
private static bool IsPortAvailable(int port)
{
IPGlobalProperties globalProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] activeListeners = globalProperties.GetActiveTcpListeners();
if (activeListeners.Any(conn => conn.Port == port))
{
return true;
}
return false;
}
Pass in the port and you should get a value indicating whether there is a listener on that port.Hope this helps
Just to get out of the box for a moment, have you thought about using WCF with MSMQ? I am not sure that I fully understand you're architecture, but it sounds like the client of the API has to spin up another process that hosts the API. There may be a timing issue between when you start the API host, and when the client tries to make calls. Microsoft has recently deprecated .NET Remoting (as well as all their other previous communications technologies such as ASMX web services) as legacy, and is highly recommending that developers move to the WCF platform.
If you use WCF with MSMQ, you shouldn't have a problem with timing. Your client application can drop messages in a durable queue regardless of whether the API host is running or not. The API host can be started at any time, and it will pick up and process any messages waiting in the queue. Even if you still have the client application start up the API host, the timing problem would no longer be an issue because you are using queuing to transfer the messages rather than .NET Remoting. WCF provides a nice, convenient, easy to use wrapper around MSMQ, so the barrier to entry is relatively low.
The other beautiful thing about using WCF over .NET Remoting is that you can easily move the API host to a different physical server without having to change the client app(s). You could even move to a different queuing platform if you so desired (such as RabbitMQ on AMQP), without changing either the client or API host apps. WCF handles all of that interaction for you, providing a much cleaner decoupling and more dependable communications between your client app and API host.
If moving to WCF is not an option, you should be able to explicitly set the port with .NET Remoting. I am not sure how you are configuring your API host, but the URL for any given remoted object is usually in the form of:
tcp://<hostname>[:<port>]/<object>
If you add the port, then you should be able to use Abhijeet's solution to determine if the port is open or not. You won't gain the loose coupling and dependable communications benefits of WCF, but it would definitely be less work. ;)
Have you considered wrapping the attempt to instantiate API object into a try-catch block? Then you can analyze the exception and see if it was caused by the server not listening. And if it was, you can just wait and retry.
Makes sense?
Just a small typo in the code.
Correction is as follows:
using System.Net.NetworkInformation;
using System.Net;
private static bool IsPortAvailable(int port)
{
IPGlobalProperties globalProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] activeListeners = globalProperties.GetActiveTcpListeners();
if (activeListeners.Any(conn => conn.Port == port))
{
return true;
}
return false;
}
When you register a IpcServerChannel it makes a Named Pipe to communicate over with the name of the Port Name you chose for your IpcServerChannel. You can look at the list of Named Pipes to see if your Port Name is there.
System.IO.Directory.GetFiles(#"\\.\pipe\").Any((path) => path.Contains(#"\\.\pipe\" + pipeName));

Access the same running code from a Windows Service and a console application?

I have an application that is built as a Windows Service and a c# library assembly (.dll.) In order to manage and maintain this service, I'd like to add the ability to run a command-line application that tells the last time the service archived files, the next time it's scheduled to do so, the status of the last run, and the location of a file created by the service.
What's the best architecture for writing a service and library that can share data with another application? I'm using .net 2.0.
The way that inter-process communication happens in .net is through remoting (even if both processes are on the same machine). Other responses have suggested alternatives to inter-process communication which would not require remoting.
The best architecture is probably to make your service be a "server" that can report on it's status (and whatever information you want). Using WCF for this like ocdecio suggested would make it pretty simple.
I use WCF for that and create a contract definition for the commands/events I want to support.
Options that spring to mind that I've applied in the past:
Save the information to a database
(if you have one to hand)
Implement a
"status monitor" type thread on the
service that the client can connect
to and query via TCP/IP etc.
A fairly simple approach is to store that information in either a local config / text file which both apps have access to. Or even to place it in a registry key.
+1 for just having the service provide that (and any other data) when it is queried (simple tcp, RPC, web service, or whatever)
I'd make it pretty generic - like
QueryInfo(some identifier)
with a response as some string and a return value or other indicator that the service does not know what you are talking about, cannot get the info, or give back the info

Categories