I have a Windows service that uses net.pipe as a WCF server and a Windows forms client to connect to it. There is a class called ConfigSettings that has values I want the client to query.
I want to have the client read the current values inside the serviceConfig instance that the service uses. Ultimately, I want the client to change values in it, but baby steps first.
The form can talk to the server via named pipes, but 'return serviceConfig is sending a new empty instance back to the client. I want the data that the service is actively using (that is, serviceConfig.Setting1 = x; serviceConfig.Setting2 = "foo"; )
The Windows service and WCF server code is (updated to working version):
using System.IO;
using System.ServiceModel;
using System.ServiceProcess;
namespace WindowsServiceTest
{
public partial class Service1 : ServiceBase
{
internal static ServiceHost myServiceHost = null;
//this is the master config that the service uses
public static ConfigSettings serviceConfig = new ConfigSettings();
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
if (myServiceHost != null)
{
myServiceHost.Close();
}
myServiceHost = new ServiceHost(typeof(WCFService1));
myServiceHost.Open();
//set active default settings
serviceConfig.Setting1 = 1;
serviceConfig.Setting2 = "initial.Setting2:" + serviceConfig.Setting1;
}
protected override void OnStop()
{
if (myServiceHost != null)
{
myServiceHost.Close();
myServiceHost = null;
}
}
}
public partial class WCFService1 : IService1
{
public ConfigSettings GetConfig()
{
return Service1.serviceConfig;
}
public void SetConfig(ConfigSettings sentConfig)
{
Service1.serviceConfig = sentConfig;
}
}
[ServiceContract]
public interface IService1
{
[OperationContract]
ConfigSettings GetConfig();
[OperationContract]
void SetConfig(ConfigSettings sentConfig);
}
public class ConfigSettings
{
public int Setting1 { get; set; }
public string Setting2 { get; set; }
public ConfigSettings() { }
}
}
The client retrieves the config like this (updated with some changes):
using System;
using System.ServiceProcess;
using System.Windows.Forms;
using WindowsServiceTest;
namespace WindowsServiceTestForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
ConfigSettings config = new ConfigSettings();
//GetConfig()
private void button1_Click(object sender, EventArgs e)
{
ServiceReference1.Service1Client myService = new ServiceReference1.Service1Client();
ServiceControllerPermission scp = new ServiceControllerPermission(ServiceControllerPermissionAccess.Control, Environment.MachineName, "Service1");//this will grant permission to access the Service
//get the current config and display
config = myService.GetConfig();
MessageBox.Show(config.Setting1 + "\r\n" + config.Setting2, "config");
myService.Close();
}
//SetConfig(ConfigSettings)
private void button2_Click(object sender, EventArgs e)
{ //make changes to values
config.Setting1 += 1;
config.Setting2 = "new.Setting2:" + config.Setting1;
ServiceReference1.Service1Client myService = new ServiceReference1.Service1Client();
ServiceControllerPermission scp = new ServiceControllerPermission(ServiceControllerPermissionAccess.Control, Environment.MachineName, "Service1");//this will grant permission to access the Service
//send the new config
myService.SetConfig(config);
myService.Close();
}
}
}
Update: Maybe what I'm thinking needs to be done is overkill. It seems that I'm hitting a membrane between WCF and the Windows Service.
How would YOU approach this problem?
- Windows Service that needs a Form for configuration.
- When service starts, it loads a config.xml file from disk. (a serialized class)
- When GUI starts, I want to:
- retrieve its current configuration,
- make some changes to it,
- push it back to the service,
- trigger service to re-read and react to the new configuration.
I was trying to avoid statically/writing the config file to disk and telling service to re-read it again. It "seemed" like WCF was the way to go.
Update 2 It seems that by just changing the master config in the service to static, the WCF service can access it directly. I could have sworn I did that originally before I posted, but I guess not.
I also separated the naming of Service1 to WCFService1 above, but it turns out that doesn't matter and works either way.
New complete code has been updated above.