Wednesday, January 16, 2013

.NET Microsoft Performance Counter does not match Task Manager

I have been struggling with this for a while now. I was asked to display the CPU usage for a list of windows servers remotely from one machine. So I wrote a piece of code that does just that using the Performance Counter. Only to find out that it returns inaccurate CPU data. I tried reading more than once, taking the normal distribution of a list of values nothing worked.

After a while it appears that you have to read .netValue once then sleep a while then read it again . Yes that is it. This fixed the problem.
Here is the code to get the real value of CPU matching the Task Manager

    Public Function getCPUPerformance(ByVal remoteHost As String) As String

        Dim userHandle As New IntPtr(0)
        LogonUser("username", "domain", "password", LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, userHandle)
        Dim identity As New WindowsIdentity(userHandle)

        Dim context As WindowsImpersonationContext = identity.Impersonate()
        Dim cpuUsage As PerformanceCounter

        cpuUsage = New PerformanceCounter("Processor", "% Processor Time", "_Total", remoteHost)

        Dim val1 As Single = cpuUsage.NextValue()

        val1 = cpuUsage.NextValue()

        Thread.Sleep(50) 'You have to Sleep, otherwise you will get kinky results    
        val1 = cpuUsage.NextValue()

        Return val1

    End Function