开发者

Send string commands or bytes to a Windows Service? (When running)

Is there any way to 开发者_开发百科give string or byte array commands to a Windows Service? (When running)


I will sometimes host a WCF service within a Windows service for the purpose of controlling the behavior of the service at runtime.

If you really just want to send raw data to the service and you don't want to deal with configuring a WCF service (which really isn't that difficult to do, by the way), you could probably accomplish that using Named Pipes or by listening for socket connections on some port.


You need some form of IPC (Inter-Process Communication). Which one you choose can depend greatly upon what you want to allow, and what you don't want to allow. For instance you need to consider the following:

  1. Should any computer be able to send this request to the service, or just the local machine?
  2. Should any user be able to send this request, or just specific users/roles?
  3. If the message contents is seen by other users is this a potential security violation?
  4. Does the service need to acknowledge the message or send a response?
  5. Does the message need to be tamper proof?
  6. How many processes/threads will be sending messages at the service at a time?

As you can see, there are just a host of issues you open up when you introduce IPC. Consider the questions above and research the following possible solutions:

  1. .Net Remoting - Easy, but has security & reliability issues.
  2. WCF Services - (.Net 3 or above) Easy to code, not entirely robust under heavy loads.
  3. Sockets - Hard to code, difficult to get right, but can be made to work.
  4. DCOM - Hosting a COM object in your .Net process and allow Windows to marshal the call.
  5. Win32 RPC - Raw Win32 libraries exist in C#, or you can write your own.

All of these have ups and downs, pros and cons. It really depends what your specific needs are.

Since you indicated your trying to call the service from the local machine, the easiest way is to either use WCF over Named Pipes (which attempts to limit communications to the local machine). If you just want to transport binary data in and out of the service then the RPC libarary linked above will work fine.

The following example demonstrates using the above RPC library:

Put this in your service:

Guid iid = new Guid("{....}");
using (RpcServerApi server = new RpcServerApi(iid))
{
    server.OnExecute += 
    delegate(IRpcClientInfo client, byte[] arg)
    {
        byte[] response;
        //do whatever
        return response;
    };

    server.AddProtocol(RpcProtseq.ncalrpc, "MyServiceName", 5);
    server.AddAuthentication(RpcAuthentication.RPC_C_AUTHN_WINNT);
    server.StartListening();
    ...

And here is the client code:

Guid iid = new Guid("{....}");
using (RpcClientApi client = new RpcClientApi(iid, RpcProtseq.ncalrpc, null, "MyServiceName"))
{
    client.AuthenticateAs(null, RpcClientApi.Self, RpcProtectionLevel.RPC_C_PROTECT_LEVEL_PKT_PRIVACY, RpcAuthentication.RPC_C_AUTHN_WINNT);
    byte[] input, output;
    output = client.Execute(input);
}


You can send start, restart and stop commands to the service, and I belive you can execute other defined commands as well.

Here is an example of programatically starting a registered service called "myService"

using System.ServiceProcess;
//...
            System.ServiceProcess.ServiceController Service;
            Service = new ServiceController("myService");
            if (Service != null && Service.Status == ServiceControllerStatus.Stopped)
                    Service.Start();
//...

Look in SeviceController. You are probably looking for:

    //
    // Summary:
    //     Executes a custom command on the service.
    //
    public void ExecuteCommand(int command);

It's my understanding though that these commands need to be predefined. You cannot pass arbrary commands to the services, i.e., this is not a method of passing data.


As @Derrick mentioned, .Start() can be used, which can also accept arguments that can be passed to the service (but this is at run-time not during execution).

If you're looking to pass information while the service is executing you have a few options:

  1. Create a service listener and use endpoints to communicate (WCF, Named pipes, etc)
  2. Use windows' built in OnCustomCommand but then you're limited to an integer.
  3. Windows has some information on dynamically configuring a windows service but looks like configuration file changes and taking advantage of OnConfigurationChange (if that's an option)

There are inevitably more, but those are what I can think of off the top of my head.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜