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

Dmi*_*nov 11 .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);
}
Run Code Online (Sandbox Code Playgroud)

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

更新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;
}
Run Code Online (Sandbox Code Playgroud)

小智 13

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