i'd like to create a windows service that would be accessible via WCF from a web application.
The workflow would be:
Windows Service starts and would hold a default value in memory.
A web app would connect the windows service via wcf and take the value and after some processing set the value back in the memory.
In a while would happend the same as in point 2., and so on,so on
This value would be hold only in memory.
The point is I dont know where put the variable that would be hold in the memory of the windows service.There is a Service class wich is instancied in a Program class wich is static class. So whats the best place to put a variable that would be hold in the memory as long as the service is running ?
And second question,is it correct to reference the exe of the windows service in a DLL ??
There is a service class for every windows service that also contains the start and stop methods. However, for your service, I'd simply create a singleton class that is accessed from the class that handles the WCF client requests.
There's no need to reference the exe of the service (and I strongly recommend you not to do that), as when you're using WCF you'll insert a service reference into your client project and just need two methods to get and set the data.
I suggest: Design your operation and data contracts for the service and then create the service reference within your client project. That'll make things clear.
If you don't know what I'm talking about, I recommend googleing for WCF samples.
EDIT
You write in the comment that you created a service class with a private field. I suppose you didn't actually do what I suggested :-) I said: Create a singleton class that is accessed by the class that handles the get/set requests.
public class ValueHolder
{
private static ValueHolder m_singleton = null;
private int m_someValue;
private ValueHolder()
{
m_someValue = 0;
}
public static ValueHolder Instance
{
get
{
if (m_singleton = null)
m_singleton = new ValueHolder();
return m_singleton;
}
}
public int SomeValue
{
get { return m_someValue; }
set { m_someValue = value; }
}
}
So now you have a window service class that you use to host a WCF service. The WCF service contains methods to get/set the value from ValueHolder.Instance.SomeValue. These methods are exposed to the client using the data contract.
Start your service and add a service reference to the client using the respective option in Visual Studio (not a reference to the DLL, but a service reference!!). The client now accesses the get/set methods of the service.
Job done, where's my money? :-D
It almost sounds like a separate service might be a little overkill for what you're after - maybe you should take a look at Inter-Process shared memory.
Take a look at #3 in this article.
http://www.codeproject.com/KB/threads/csthreadmsg.aspx
Related
This is my first WCF Library and I created it within a Windows Service, which I can access just fine and process through it, but unlike a normal library, I can't seem to access any of it's method classes outside of the Web Interface. The WCF Library has some threading within it that stays up until it needs to shutdown and I need the ability to tell this library the service is shutting down and it needs to close out the threads within itself gracefully. I'm guess I'm missing something simple, but maybe I can capture the Close() being called from within the WCF Library?
ServiceHost oServiceHost = new ServiceHost(typeof(WCFListener.MyClass));
oServiceHost.Open();
//wait until shutdown is called.
while (!_shutDownEvent.WaitOne(Timeout.Infinite));
//HERE I NEED TO TELL THE LIBRARY TO STOP ANY THREADS OR
//WITHIN THE WCF CAPTURE CLOSE() WAS CALLED.
if (oServiceHost != null)
{
//close out the WCF Listener service.
oServiceHost.Close();
oServiceHost = null;
}
I know how to launch the WCF Library as it's working and processing, but there are threads that are created within the WCF Libray and stay OPEN in the WCF Library. I need the WCF Library to start closing threads property when Windows tells my Windows Service it needs to stop. serviceHost.Close() doesn't kill the threads that have been created nor do I want it to. This is causing the Windows service to freeze waiting for the threads to stop.. I'm trying to figure out how I can tell the WCF Library this as it doesn't have a interface like an object. I'm sure this is simple and I'm overthinking it.
It is a little hard to understand what your problem actually is, but generally, you would proceed as follows:
Update I have assumed hypothetical MyLibraryClass.Initialize() and MyLibraryClass.Shutdown() methods, that your library provides, below.
So, your library would provide something like this:
public static class MyLibraryClass
{
public static void Initialize(ServiceHost serviceHost)
{
serviceHost.Closed += (...) {
// Cleanup when host closes.
Shutdown();
}
}
public static void Shutdown()
{
// Cleanup. E.g. stop threads, etc.
}
}
If that is not correct, you need to provide more source/context in your question about what you can do or can't do. In general, it is always a good idea to not have explicit active components in a library (like threads, etc.); if required to do so, than you should provide an "initialize" and/or "shutdown" method for the users of your library.
public class MyService : ServiceBase
{
private ServiceHost serviceHost;
protected override void OnStart(string[] args)
{
serviceHost = /* new, etc. */
// Somehow pass the serviceHost reference to your library,
// then subscribe to `Closed`, e.g.
MyLibraryClass.Initialize(serviceHost);
serviceHost.Open();
}
protected override void OnShutdown()
{
serviceHost.Close();
// Do additional cleanup, e.g. stopping your "library threads"
// Alternative to the event-approach in "OnStart", simply call
MyLibraryClass.Shutdown();
}
}
That is, you would open your host when the service starts, and close it when the service ends. There should be no reason to do any extra "waiting", etc. on a service shutdown.
The Windows Service Control Manager will call (via P/Invoke, etc.) the OnStart and OnShutdown methods when it starts / stops the service.
The important thing is, that you do your actual work in a background thread, i.e. exit the OnStart and OnShutdown methods as quick as possible - that is a trait that you get for free with ServiceHost in this case.
Using WCF, .NET 4.5, Visual Studio 2015, and want to use per-session instancing, not singleton. The services provided are to be full-duplex, over tcp.net.
Suppose I have two machines, A & B...
B as a client, connects to a "service" provided as a WCF service on same machine B, and starts talking to it, call it object “X”. It ALSO connects to another instance of the same service, call it object “Y”
A as a client, wants to connect to, and use, exact same objects B is talking to, objects “X” and “Y”, except now it’s remote-remote, not local-remote.
“X” and “Y” are actually a video servers, and both have “state”.
Can I do this? How, when I’m a client, do I specify WHICH service instance I want to connect to?
Obviously, on machine "B", I could kludge this by having the services just be front-ends with no "state", which communicate with some processes running on "B", but that would require I write a bunch of interprocess code, which I hate.
Machine B is expected to be running 100's of these "video server" instances, each one being talked to by a local master (singleton) service, AND being talked to by end-user machines.
I realize this question is a bit generic, but it also addresses a question I could not find asked, or answered, on the Internets.
I just thought of one possible, but kludge-y solution: since the master service is a singleton, when service instance "X" is created by the end-user, it could connect to the singleton master service, through a proxy to the singleton. Then, the singleton can talk back to instance "X" over a callback channel. Yeah, that would work! messy, but possible.
I'd still like to know if end user A and end user B can both talk to the same (non-singleton) service instance on machine C through some funky channel manipulation or something. As I understand the rules of WCF, this simply isn't possible. Perhaps maybe if you're hosting the service yourself, instead of IIS, but even then, I don't think it's possible?
I've faced the same problem and solved it by creating two service references, one for the local one for the remote. Let's call it LocalServiceClient and RemoteServiceClient.
In a class, create a property called Client (or whatever you like to call it):
public LocalServiceClient Client {
get {
return new LocalServiceClient();
}
}
Okay this is for only one of them. Just create another now, and set which one to use with a compiler flag:
#if DEBUG
public LocalServiceClient Client {
get {
return new LocalServiceClient();
}
}
#else
public RemoteServiceClient Client {
get {
return new RemoteServiceClient();
}
}
#endif
Instantiate any instances of your Client using var keyword, so it will be implicitly-typed, or just use Client directly:
var client = Client;
client.DoSomething...
//or
Client.DoSomething...
This way, when you are working locally, it will connect to the local service, and on release configuration (make sure you are on Release when publishing) it will compile for the remote one. Make sure you have the exact same signature/code for both services though at the WCF-side.
There are also methods that you can dynamically do it in code, or like in web.config, they would also work for sure, but they are usually an overkill. You probably need to connect to local one in debugging, and the remote one in production, and this is going to give you exactly what you need.
I am deploying a client app to a mobile laptop that is configured to use one of two network servers. The network servers are identical but with different IP addresses as each is in a different office.
When the client app is first started, it needs to determine only once which office it is in and therefore which dataservice to connect to. So, using the client machine's ip address, I wish to do
something like this:
internal TYPE??? dataservice = new ResolveDataService();
NovaDataServiceClient ResolveDataService()
{
if (localip == xxx.xxx.xxx.xxx)
{
retrun new DataService.NovaDataServiceClient();
}
else
{
return new LibraryWebService.NovaDataServiceClient();
}
}
Furthermore, since it only has to be done once, a static constructor would be preferred. But the real problem is that the namespace "DataService" and "LibraryWebService" were given to the Add Service Reference of the client project so in the above code
internal TYPE??? dataservice
The Type is not known until ResolveDataService is called.
How is this done correctly? Thanks
If these two services are exactly the same and just differ by IP address the right thing to do is to only have one service reference and set the endpoint when you create the service. The easiest way in your case would probably be to add a second endpoint configuration with a different name attribute to the app.config and supply that in the client's constructor.
I have a Windows Service that hosts a WCF service and I am successfully able to connect to it using WCFTestClient and a Custom Client. The windows service is based upon what used to be an exe, but since the program will be used for a long running process on a server, the service is a better route. The problem is that I cannot access static variables in the application from the WCF service.
In the .exe (I switched this to a .dll which is the server application) I use a global class implemented as such:
public static class Globals
{
....
}
This holds references to the major parts of the program so that if any part needs to reference another I can use the syntax Globals.JobManager.RunJob().
The problem that I am encountering is that the WCF service is not able to reference Globals at run-time. One example of where I need this to be done is in the GetJob method:
public class ConsoleConnection : IConsoleConnection
{
public string[] RetrieveJobList()
{
string[] jobs = Globals.JobManager.GetAllJobNames().ToArray();
return jobs;
}
}
This method returns null when tested in WCFTestClient and throws an exception in the created client.
I believe this issue to be caused by the way the Windows Service, WCF Service, and the application DLL are initiated. The current method is such:
public class ETLWindowsService : ServiceBase
{
....
protected override void OnStart(string[] args)
{
if (serviceHost != null)
{
serviceHost.Close();
}
Globals.InitializeGlobals();
serviceHost = new ServiceHost(typeof(ConsoleConnection));
serviceHost.Open();
}
....
}
Here the Windows Service starts, Calls the Globals.InitializeGlobals() that creates all the necessary parts of the application, then starts the WCF service (If this is the wrong way to do this, let me know. I'm piecing this together as I go). I'm assuming that these actions are being done in the wrong order and that is the cause of the problems.
Do I need to have the Windows Service create the WCF Service which in turn creates the application (this doesnt make sense to me), or do I have the Windows Service create the application which then creates the WCF Service? Or is there a third option that I am missing?
The application is in a .dll with the WCF in a separate .dll
I totally agree with Andy H.
If I review this kind of code, I won't try to make the stuff work with the global static variable (even if in the end this is probably possible). A static global class is smelly. First of all, I will figure out to make it work without it.
There are several solution: dependency injection, messaging communication, event driven...
To help you: a long running process in a web service is very common, youy have a good description
here. But in any case, it never uses a static class to synchronize the jobs :)
Improve your design, and you will see that your current problem won't exist at all.
I need to run a bunch of pluggable processes in a windows service on my server and want to create a user interface that allows me to interact with each of the plugins in use by the service.
What is the most common method (or methods) for communication between a user interface and a long-running windows service? I am thinking of providing a go-between location such as a database and using some sort of messaging queue to issue commands to the service. Have any of you implemented such an approach, or some other superior approach? WHat problems have you come across in the process?
Do not use remoting! While it will certainly work, Microsoft says that remoting is a legacy technology and that all new distributed applications should be developed using WCF. See here for more details.
Windows Communication Foundation (WCF) is the recommended way for two .NET processes to communicate with each other. WCF provides a unified programming model that greatly simplifies distributed development by abstracting many of the complexities associated with specific communication mechanisms, e.g., sockets, pipes, etc.
Given the details of your situation, I would suggest making each Windows service plugin a WCF service. For each WCF service, i.e., plugin, define the interface that it needs to expose to your UI. The interface is simply a C# interface adorned with the ServiceContract attribute. This interface contains the methods, each of which is adorned with the OperationContract attribute, that your UI will use to communicate with the WCF service (plugin). These methods can accept and return any serializable .NET type or, as is often the case, your own custom types. To use custom types with WCF, simply decorate them with the DataContract attribute and mark the members that you want to be exchanged via WCF with the DataMember attribute.
Once you have your ServiceContract interface defined, define a class that implements that interface. Each OperationContract method does whatever it needs to do, e.g., interact with database, calculate some value, etc. Once you've done this, you have effectively defined a WCF service. Here's a short, but working, example:
using System.ServiceModel;
namespace AdditionServiceNamespace
{
[DataContract]
public class Complex
{
[DataMember]
public int real;
[DataMember]
public int imag;
}
[ServiceContract]
public interface IAdditionService
{
[OperationContract]
Complex Add(Complex c1, Complex c2);
}
public class AdditionService : IAdditionService
{
public Complex Add(Complex c1, Complex c2)
{
Complex result = new Complex();
result.real = c1.real + c2.real;
result.imag = c1.imag + c2.imag;
return result;
}
}
}
The next step is to host this WCF service so that it is available to be used by your UI. Since you will be using a Windows service, hosting your WCF service is done easily enough in the OnStart() callback of your Windows service, like so:
using System.ServiceModel;
using System.ServiceProcess;
using AdditionServiceNamespace;
namespace WindowsServiceNamespace
{
public class WindowsService : ServiceBase
{
static void Main()
{
ServiceBase[] ServicesToRun = new ServiceBase[]
{ new WindowsService() };
ServiceBase.Run(ServicesToRun);
}
private ServiceHost _host;
public WindowsService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
_host = new ServiceHost(typeof(AdditionService));
_host.Open();
}
protected override void OnStop()
{
try
{
if (_host.State != CommunicationState.Closed)
{
_host.Close();
}
}
catch
{
// handle exception somehow...log to event viewer, for example
}
}
}
}
The only thing left to do is to define an app.config file for your Windows service that will configure certain required aspects of your WCF service. This may seem like overkill, but keep two things in mind. First of all, Visual Studio gives you a basic app.config file automatically when you add a WCF service class to your project. Second, the app.config file gives you a tremendous amount of control over your WCF service without requiring changes to the code. Here's the companion app.config file for the example above:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="AdditionServiceNamespace.MyAdditionService"
behaviorConfiguration="default">
<endpoint name="AdditionService"
address="net.pipe://localhost/AdditionService"
binding="netNamedPipeBinding"
contract="AdditionServiceNamespace.IAdditionService" />
<endpoint address="net.pipe://localhost/AdditionService/MEX"
binding="mexNamedPipeBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="default">
<serviceMetadata />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Note that the AdditionService WCF service has two endpoints. The metadata exchange endpoint is used for code generation by the client, so ignore it for now. The first endpoint is configured to use the NetNamedPipeBinding. This is the binding to use if your UI and Windows service will be running on the same machine (see here for a flowchart on selecting the appropriate binding to use). However, this binding cannot be used if your UI and Windows service will be running on different machines. In that case, you could use the NetTcpBinding as a replacement. To substitute the NetTcpBinding for the NetNamedPipeBinding, you would simply need to change the address and binding of the endpoint, like this:
<endpoint name="AdditionService"
address="net.tcp://<machine hostname here>/AdditionService"
binding="netTcpBinding"
contract="AdditionServiceNamespace.IAdditionService" />
No code changes are required! Make the change, restart your service, and your WCF service is now available to remote machines. You can even allow multiple endpoints for the same WCF service if you so desired. The point is, the app.config file offers a tremendous amount of flexibility without requiring changes to the code.
That's it! You now have a WCF service hosted inside your Windows service available for use by your UI.
So how does the UI side, i.e., the client side, work?
This is where the real power of WCF comes into play. When getting started with WCF, the easiest thing to do is leverage Visual Studio's code generation capabilities. Make sure that your Windows service (the one hosting the AdditionService) is running. In your UI project, right-click on your project in the Solution Explorer and select the Add Service Reference... menu option. In the Address box, type net.pipe://localhost/AdditionService, and click the Go button. You should see the AdditionService show up in the Services list. In the Namespace box, type AdditionService and click the OK button.
Performing these steps will generate a client proxy and a properly defined app.config file that are added to your UI project. This client proxy becomes your client-side AdditionService API, and you use it like this:
using TestConsoleApp.AdditionService;
namespace TestConsoleApp
class Program
{
static void Main(string[] args)
{
AdditionServiceClient client = new AdditionServiceClient();
Complex c1 = new Complex(), c2 = new Complex();
c1.real = 3; c1.imag = 5;
c2.real = 1; c2.imag = 7;
Complex result = client.Add(c1, c2);
}
}
}
Notice how simple this is. Basically, a client proxy, AdditionServiceClient, is instantiated. Then two Complex objects are created. Finally, the Add() method on the client proxy is invoked, and a Complex result is returned.
What is going on behind the scenes is that the Add() method of the client proxy is actually passing the two Complex objects to the AdditionService WCF service hosted in the Windows service. The AdditionService performs the addition and then returns the result. All of this happens over a named pipe, but notice that there is no named pipe-specific code here at all! WCF has abstracted all of that complexity behind a programming model that is defined by the IAdditionService interface.
I know this is a lot of information to digest, but I hope it is evident just how powerful and easy-to-use WCF can be. Of course, this example only hits a small subset of everything that is available within WCF.
In the end, though, WCF should be the mechanism you use to communicate between your UI and your Windows service. For more information, I would highly recommend Juval Lowy's book Programming WCF Services for all things WCF. You can also visit his website, IDesign.net, for free WCF code samples. For more introduction to WCF, watch this free video at dnrTV. It covers the purpose of WCF and demonstrates WCF programming through some easy-to-follow examples.
Your best bet is to use .NET remoting over an IPC channel.
While it seems complicated to setup, it is rather easy the second time around.
I suggest you play with a few samples first on exposing remotable objects from one application to another.
I have not used Message queues before, so I can't comment on that.