性能计数器已创建,但在Windows重新启动之前无效

时间:2010-09-17 09:51:41

标签: .net windows-server-2003

我在现有组中创建新计数器时遇到一个奇怪的问题。我有一个Windows服务,它做了一些工作,并允许我通过性能计数器监视其状态。我有性能计数器组和一些性能计数器。在服务安装阶段(具有管理员权限)创建组,并在服务启动时初始化计数器(作为LocalSystem用户)。一切正常,组存在,计数器也存在,我可以监视它们并写入性能计数器日志。服务不断运行。

然后我想添加一些性能计数器。我将它们添加到服务代码中,通过卸载以前的服务实例(卸载代码删除性能计数器组)并重新安装服务来重建和部署到服务器(在安装阶段使用所有新计数器创建性能计数器组)。然后我开始服务。

这是故事中常见的,无趣的部分的结束。奇怪的事情从这里开始。

我转到PerMon,将所有计数器添加到系统监视器视图。我可以看到我的性能计数器组,我看到所有性能计数器,包括我刚刚添加的新性能计数器。我可以将它们添加到系统监视器视图。我可以看到,旧的计数器正在工作。但新计数器不起作用,它们不收集任何数据。好吧,好吧,也许是我的错误,我切换到日志视图并尝试记录性能计数器数据。旧计数器在记录之前记录。但是当我尝试添加新计数器时,我会在事件查看器中找到警告:

  

该服务无法将计数器'\ AGENT \ MyCountersGroupName \ MyNewCounter'添加到NewCountersLog日志或警报。此日志或警报将继续,但不会收集该计数器的数据。返回的错误是:找不到指定的计数器。

我尝试重新安装服务,删除旧计数器,再次添加它们,并且没有任何更改。旧计数器正在工作,新计数器不起作用。然后我重新启动Windows,新的计数器开始工作!服务没有任何改变,我刚刚重启了服务器。我在2台服务器上遇到此问题,两者都在Windows Server 2003 SP1下运行。所有性能计数器的代码都是相同的,因为我使用泛型代码创建它们。

你可以说“嘿,不要打扰,每当你需要添加新的性能计数器时重新启动Windows”,但我不能。我的服务与其他服务一起在服务器上运行,我们需要这些服务不断工作,每次更改一项服务时都无法重启服务器。

有人可以帮忙解决这个问题吗?

更新 看起来有类似的问题:https://stackoverflow.com/questions/2180005/adding-performance-counters-to-existing-category

更新 我不认为问题出在我的代码中,但是如果它有帮助我在这里发布它。

安装和卸载代码(在安装阶段调用): PerformanceCountersManagerBase.GetCreationData()是一个通用的包装器,用于获取数据集合以创建性能计数器。

public static void Install()
{
    CounterCreationDataCollection counters = new CounterCreationDataCollection(
    PerformanceCountersManagerBase.GetCreationData<TManager>().ToArray());

    if (PerformanceCounterCategory.Exists(PerformanceCountersManagerBase.GroupName))
        PerformanceCounterCategory.Delete(PerformanceCountersManagerBase.

    PerformanceCounterCategory.Create(PerformanceCountersManagerBase.GroupName, 
        "Group description",
        PerformanceCounterCategoryType.SingleInstance, counters);
}

public static void Uninstall()
{
    if (!PerformanceCounterCategory.Exists(PerformanceCountersManagerBase.GroupName))
        return;

    PerformanceCounterCategory.Delete(PerformanceCountersManagerBase.GroupName);
}

初始化服务和更新中的计数器的代码:

internal void Initialize(string name, string groupName)
{
    _counter = new PerformanceCounter(groupName, name, false);
    _counter.RawValue = 0;
}

internal void Increment()
{
    if ((_counter == null) || _counter.ReadOnly)
        return;

    lock (_counter)
    {
        _counter.Increment();
    }
}

更新3 我更改了代码以通过.NET组件PerformanceCounterInstaller安装计数器,并且没有任何更改。旧计数器在它们工作时工作,并且新创建的不起作用并尝试记录它们导致事件日志中的确切错误(警告)消息。安装程序创建代码如下:

public static PerformanceCounterInstaller GetInstaller()
{
    PerformanceCounterGroupAttribute group
        = PerformanceCountersManagerBase.ExtractGroupSettings(typeof(TManager));

    PerformanceCounterInstaller installer = new PerformanceCounterInstaller();
    installer.CategoryName = group.Name;
    installer.CategoryHelp = group.Description;
    installer.CategoryType = PerformanceCounterCategoryType.SingleInstance;
    installer.UninstallAction = UninstallAction.Remove;
    installer.Counters.AddRange(PerformanceCountersManagerBase.GetCreationData<TManager>().ToArray());

    return installer;
}

3 个答案:

答案 0 :(得分:12)

Perf计数器基于共享内存段。当有人仍然拥有共享内存段的句柄时,我已经看到了类似的问题。这可以包括perfmon工具本身。您可以使用handle实用程序查看谁持有共享内存。 您不应该需要重新启动,因此请尝试查看此问题是否消失,先关闭perfmon然后重新创建计数器。还要确保您的服务没有运行。

答案 1 :(得分:3)

在迈克回答之前,我自己处理了这个问题。但我没时间弄清问题的原因。我通过执行以下步骤解决了这个问题:

  1. 停止perfmon日志记录(我通过perfmon记录器记录了所有计数器)
  2. close perfmon
  3. 卸载服务(服务卸载程序卸载性能计数器整个组)
  4. 使用添加的性能计数器安装服务
  5. 在这些步骤之后,新的性能计数器出现了。也许没有必要停止记录,但我现在没有时间检查它。我稍后再试。我接受迈克的答案是正确的,因为它指的是问题的原因。

答案 2 :(得分:1)

我有一个类似的情况,我为系统的不同部分创建了一些性能计数器,并将它们添加到字典中以便按名称直接访问,并且它们都写入了一个(任何一个的任何增量都会更新其余部分)。

令我惊讶的是,解决方案是关闭 性能监视器 Windows工具,然后创建计数器。问题是被锁定的二手共享内存。