如何/在哪里处理 Windows 服务中的 ConfigurationErrorsException?

发布于 2024-07-12 13:04:04 字数 766 浏览 6 评论 0原文

我有一个带有自定义配置部分的 Windows 服务。 在 configSectionHandler 类中,我使用属性上的属性来验证设置,如下所示:

    //ProcessingSleepTime Property
    [ConfigurationProperty("ProcessingSleepTime", DefaultValue = 1000, IsRequired = false)]
    [IntegerValidator(MinValue = 5, MaxValue = 60000)]
    public Int32 ProcessingSleepTime
    {
        get
        {
            if (this["ProcessingSleepTime"] == null)
                return 100;

            return (Int32)this["ProcessingSleepTime"];
        }
        set
        {
            this["ProcessingSleepTime"] = value;
        }
    }

如果配置文件中的值验证失败,则会引发 ConfigurationErrorsException。 在 Windows 服务中,这种情况发生在它尝试启动时,而且非常丑陋(它提供启动调试器)。 我怎样才能优雅地处理这个错误? 我尝试将 OnStart 方法包装在 try/catch 中,但没有效果。

谢谢。

I have a windows service that has a custom configuration section. In the configSectionHandler class I am using attributes on the properties to validate the settings like this:

    //ProcessingSleepTime Property
    [ConfigurationProperty("ProcessingSleepTime", DefaultValue = 1000, IsRequired = false)]
    [IntegerValidator(MinValue = 5, MaxValue = 60000)]
    public Int32 ProcessingSleepTime
    {
        get
        {
            if (this["ProcessingSleepTime"] == null)
                return 100;

            return (Int32)this["ProcessingSleepTime"];
        }
        set
        {
            this["ProcessingSleepTime"] = value;
        }
    }

If a value in the configuration file fails validation, a ConfigurationErrorsException is thrown. In a windows service this happens as it is trying to start and it's really ugly (it offers to launch the debugger). How can I gracefully handle this error? I tried wrapping the OnStart method in a try/catch but it had no effect.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

枫以 2024-07-19 13:04:04

或者更好(因为您可能需要多个这样的属性),使用 @Ricardo Villiamil 的代码,创建:

int GetIntFromConfigSetting(string settingName, int defaultValue)
{
   int retValue = defaultValue;
   if(this.ContainsKey(settingName))
   {
      int sleepInterval;
      if(Int32.TryParse(this[settingName], out sleepInterval)
      {
         retValue = sleepInterval;
      }
   }
   return retValue;
}

然后从您需要的任何属性中使用它。

编辑:实际上,再次重新阅读问题后,看起来这只能解决您的问题一半,就好像该值超出了定义的范围一样,无论如何它都会抛出异常。

EDIT2:您可以挂钩 AppDomain.UnhandledException 事件在配置节处理程序的静态构造函数中。 静态构造函数在访问类的任何实例或静态成员之前运行,因此即使尚未调用服务的 main 方法,它也保证您将拦截异常。

然后,当您拦截并记录错误时,您可以使用一些错误代码 != 0 (Environment.Exit(errorCode)) 退出服务,这样服务管理器就知道它失败了,但不会尝试调用调试器。

Or better yet (as you might need multiple such a properties), using the code from @Ricardo Villiamil, create:

int GetIntFromConfigSetting(string settingName, int defaultValue)
{
   int retValue = defaultValue;
   if(this.ContainsKey(settingName))
   {
      int sleepInterval;
      if(Int32.TryParse(this[settingName], out sleepInterval)
      {
         retValue = sleepInterval;
      }
   }
   return retValue;
}

Then use it from any property you need to.

EDIT: actually, after re-reading the question once more, looks like this solves your problem only half-way, as if the value is out of the defined range, it will throw exception anyway.

EDIT2: You can hook the AppDomain.UnhandledException event in the static ctor of your config section handler. The static ctor is ran before any instance or static member of a class are accessed, so it guarantees that you will intercept the exception even if the main method of your service is not yet called.

And then, when you intercept and log the error, you can exit the service with some error code != 0 ( Environment.Exit(errorCode) ), so the service manager knows it failed, but not try to invoke a debugger.

腻橙味 2024-07-19 13:04:04

好吧,我想我已经有了。 在我的服务中,我的构造函数中的代码如下所示:

config = ConfigurationManager.GetSection("MyCustomConfigSection") as MyCustomConfigSectionHandler;

这是抛出错误的地方。 我可以捕获错误并记录它。 必须重新抛出错误以阻止服务继续。 这仍然会导致丑陋的行为,但至少我可以记录错误,从而通知用户服务未启动的原因

Ok I think I have it. In my service I have code that looks like this in the constructor:

config = ConfigurationManager.GetSection("MyCustomConfigSection") as MyCustomConfigSectionHandler;

This is where the error is thrown. I can catch the error and log it. The error must be rethrown in order to prevent the service from continuing. This still causes the ugly behavior but at least I can log the error thereby informing the user of why the service did not start

↘人皮目录ツ 2024-07-19 13:04:04

首先,检查您的配置是否包含您要查找的密钥,然后将其包装在 try catch 中,然后检查它是否是有效的整数:

int retValue = 100;
if(this.ContainsKey("ProcessingSleepTime"))
{
    object sleepTime = this["ProcessingSleepTime"];
    int sleepInterval;
    if(Int32.TryParse(sleepTime.ToString(), out sleepInterval)
    {
       retValue = sleepInterval;
    }
}
return retValue;

First, check if your configuration contains the key that you're looking for, then wrap it in a try catch, then check if it's a valid integer:

int retValue = 100;
if(this.ContainsKey("ProcessingSleepTime"))
{
    object sleepTime = this["ProcessingSleepTime"];
    int sleepInterval;
    if(Int32.TryParse(sleepTime.ToString(), out sleepInterval)
    {
       retValue = sleepInterval;
    }
}
return retValue;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文