65.9K
CodeProject is changing. Read more.
Home

Managing settings with encryption in a Windows Service using WCF

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (3 votes)

Apr 2, 2009

CPOL

1 min read

viewsIcon

21364

downloadIcon

192

A simple example of a method to manage settings in a Windows Service using WCF.

wcfmanagedsetting2.jpg

Introduction

The goal of this article is to provide a simple example of a method to manage settings in a Windows Service using WCF.

My first attempt to solve this situation was to develop a small Windows Dorms application which would directly edit the service EXE config file. I finally found it much more elegant to let the service itself deal with the settings savings, and provide a small WCF service inside of it to expose functionalities to my Windows Forms application.

P.S.: this is my first article, and I apologize for my rough English...

Background

This code makes use of a very basic implementation of a WCF Service. For those who have never used WCF, I would recommend the book with which I started: Microsoft Windows Communication Step By Step published by Microsoft Press and written by John Sharp.

Using the code

The demo is composed of three projects:

  • SampleService, which implements the Windows Service and the WCF Service.
  • SettingsApplication, which implements the forms app which manages the settings with a PropertyGrid control.
  • SampleServiceSetup, which is the setup project to install the Service and the Settings application.

The sample service exposes a simple WCF service contract in IAppSettingsService.cs:

[ServiceContract]
public interface IAppSettingsService
{
    [OperationContract]
    ServiceSettings GetSettings();
    [OperationContract]
    void SetSettings(ServiceSettings set);
}
[DataContract]
public class ServiceSettings
{
    [DataMember]
    public String Host { get; set; }
    [DataMember]
    public int Port { get; set; }
    [DataMember]
    public String User { get; set; }
    [DataMember]
    [PasswordPropertyText(true)]
    public String Password { get; set; }
}

The contract implementation in AppSettingsService.cs provides the GetSettings and SetSettings methods. The SetSettings method encrypts the settings using RsaProtectedConfigurationProvider :

public ServiceSettings GetSettings()
{
    try
    {
        return new ServiceSettings
        {
        Host = Settings.Default.Host,
        Password = Settings.Default.Password,
        Port = Settings.Default.Port,
        User = Settings.Default.User
        };
    }
    catch (Exception err)
    {
        throw GetErrMessage(err, "GetSettings");
    }
}
public void SetSettings(ServiceSettings set)
{
    Type type = set.GetType();
    try
    {
        var config = 
          ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        var section = (ClientSettingsSection)
            config.GetSection("applicationSettings/SampleService.Settings");
        if (section.SectionInformation.IsProtected)
            section.SectionInformation.UnprotectSection();
        foreach (SettingElement t in section.Settings)
        {
            var propertyInfo = type.GetProperty(t.Name);
            t.Value.ValueXml.InnerText = propertyInfo.GetValue(set, null).ToString();
        }
        if (!section.SectionInformation.IsProtected)
            section.SectionInformation.ProtectSection("RsaProtectedConfigurationProvider");
        section.SectionInformation.ForceSave = true;
        config.Save(ConfigurationSaveMode.Full);
        Settings.Default.Reload();
    }
    catch (Exception err)
    {
        throw GetErrMessage(err, "SetSettings");
    }
}
...

On the client application side, I defined a ClientServiceSettings class to provide additional information and possibly custom editors for the PropertyGrid:

public class ClientServiceSettings
{
    public ClientServiceSettings(ServiceSettings settings)
    {
        Host = settings.Host;
        Port = settings.Port;
        User = settings.User;
        Password = settings.Password;
    }
    [DisplayName("Host")]
    [Category("Server")]
    [Description("Enter the host name or IP address.")]
    public String Host { get; set; }
    [DisplayName("Port Number")]
    [Category("Server")]
    [Description("Enter the port number.")]
    public int Port { get; set; }
    [DisplayName("User")]
    [Category("Credentials")]
    [Description("User login to access server.")]
    public String User { get; set; }
    [DisplayName("Password")]
    [Category("Credentials")]
    [PasswordPropertyText(true)]
    [Description("The user's password. It will be encrypted " + 
                 "in the configuration settings file.")]
    public String Password { get; set; }
}

Then, retrieving the settings from the client application is as simple as:

using (var client = new AppSettingsServiceClient())
{
    set = new ClientServiceSettings(client.GetSettings());
    propertyGrid1.SelectedObject = set;
}

That's it. I hope some of you will find this modest contribution useful. Cheers and happy coding!

OSZAR »