65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 WCF 在 Windows 服务中管理带加密的设置

2009年4月2日

CPOL

1分钟阅读

viewsIcon

21703

downloadIcon

208

一个简单的示例,演示如何使用 WCF 在 Windows 服务中管理设置。

wcfmanagedsetting2.jpg

引言

本文的目标是提供一个简单的示例,演示如何使用 WCF 在 Windows 服务中管理设置。

我最初尝试解决这个问题的方法是开发一个小型的 Windows Forms 应用程序,直接编辑服务 EXE 配置文件。我最终发现让服务本身处理设置保存,并在其中提供一个小的 WCF 服务来暴露功能给我的 Windows Forms 应用程序,这要优雅得多。

顺便说一句:这是我的第一篇文章,为我的粗糙的英语道歉...

背景

这段代码使用了非常基础的 WCF 服务实现。对于那些从未用过 WCF 的人,我推荐我开始学习的书籍:Microsoft Windows Communication Step By Step,由微软出版社出版,约翰·夏普 (John Sharp) 编写。

使用代码

该演示由三个项目组成

  • SampleService,它实现了 Windows 服务和 WCF 服务。
  • SettingsApplication,它实现了用于使用 PropertyGrid 控件管理设置的表单应用程序。
  • SampleServiceSetup,是用于安装服务和设置应用程序的安装项目。

示例服务在 IAppSettingsService.cs 中暴露了一个简单的 WCF 服务契约

[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; }
}

AppSettingsService.cs 中的契约实现提供了 GetSettingsSetSettings 方法。SetSettings 方法使用 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");
    }
}
...

在客户端应用程序侧,我定义了一个 ClientServiceSettings 类,以提供其他信息,并可能为 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; }
}

然后,从客户端应用程序检索设置就像这样简单

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

就这样了。我希望我的这些微薄的贡献对您有所帮助。祝您编码愉快!

© . All rights reserved.