Get memory size usage using WMI and .NET 2.0.

by Steve Schofield

This article shows how to retrieve Physical and Virtual memory usage on a specific process using WMI.  Most administrators are familiar with viewing information in task manager.  One of the most common things I look for are memory settings.   Note: the example below shows the Physical memory usage for the ‘sqlserver.exe’ process at 43,716 K and Virtual memory size of 55,376 K.   This is a ‘moment in time’ setting and can change often.

Using this code sample can help query a remote machine on a periodic basis to identify offending processes.  I use this technique to monitor ‘W3WP.exe’ processes on shared web servers to identify high memory application pools.   The code sample returns all the information in the Win32_Process class regarding just the ‘W3WP.exe’ process.  You could do this for other processes too.  The one additional function also returns the ‘owner’ of the thread which I found required an additional step to query with the ‘thread handle’  The other feature in the component is the ability to pass custom user id and password to the remote machine.  This can be handy to not assume the user id credentials the process is running under.  Happy WMI coding!

Imports System.Management
Imports System.Data.SqlClient

Public Class GetStats
    Private _ComputerName As String
    Private _UserName As String
    Private _Password As String
    Private _SelectQuery As String = “SELECT * FROM Win32_Process WHERE name=’w3wp.exe'”
    Private _DateEntered As DateTime

  Sub Main(ByVal strComputerName As String, ByVal strUserName As String, ByVal strPassword As String)
        Try
            SelectQuery = System.Configuration.ConfigurationManager.AppSettings(“SelectQuery”)
            _ComputerName = strComputerName
            _UserName = strUserName
            _Password = strPassword
            _DateEntered = System.DateTime.Now()
            ‘LogInfo(“Starting Process: ” & strComputerName & ” – ” & System.DateTime.Now())
            ‘Console.WriteLine(“Starting Process: ” & strComputerName & ” – ” & System.DateTime.Now())
            GetProcessInfo()
           
            ‘Console.WriteLine(“Finishing Process: ” & strComputerName & ” – ” & System.DateTime.Now())
            ‘LogInfo(“Finishing Process: ” & strComputerName & ” – ” & System.DateTime.Now())
        Catch f As Exception
            ErrorHandler(f)
        End Try
    End Sub

    Sub GetProcessInfo()
        Try
            Dim options As New ConnectionOptions()
            options.Username = _UserName
            options.Password = _Password

            Dim scope As New ManagementScope(“\” & _ComputerName & “rootcimv2”, options)
            Dim selectQuery As New SelectQuery(_SelectQuery)
            Dim searcher As New ManagementObjectSearcher(scope, selectQuery)

            Try
                scope.Connect()
            Catch f As Exception
                ErrorHandler(f)
                Exit Sub
            End Try


            For Each queryObj As ManagementObject In searcher.Get()
                  ‘Memory Usage = WorkingSetSize (WMI Property)
                  ‘Peak Memory Usage = PeakWorkingSetSize (WMI Property)
                  ‘VM Size = PageFileUsage
                  ‘Peak VM Size = PeakPageFileUsage
                Console.Writeline(obj.WorkingSetSize / 1024)
                Console.Writeline(obj.PeakWorkingSetSize / 1024)
                Console.Writeline(obj.PageFileUsage / 1024)
                Console.Writeline(obj.PeakPageFileUsage / 1024)
                Console.Writeline(GetOwnerObject(queryObj(“Handle”)))
            Next
        Catch f As Exception
            ErrorHandler(f)
        End Try
    End Sub

    Function GetOwnerObject(ByVal strHandle As String) As Object
        Dim options As New ConnectionOptions()
        options.Username = _UserName
        options.Password = _Password

        Dim s As New ManagementScope( _
           “\” & _ComputerName & “rootcimv2”, options)
        Dim p As New ManagementPath( _
            “Win32_Process.Handle='” & strHandle & “‘”)

        Dim opt As ObjectGetOptions
        opt = New ObjectGetOptions()

        Dim o As ManagementObject
        o = New ManagementObject(s, p, opt)

        ‘ Execute the method and obtain the return values.
        Dim outParams As ManagementBaseObject = _
            o.InvokeMethod(“GetOwner”, Nothing, Nothing)
        Return outParams(“User”).ToString()
    End Function

#Region “Properties”

    Public Property ComputerName() As String
        Get
            Return _ComputerName
        End Get
        Set(ByVal Value As String)
            _ComputerName = Value
        End Set
    End Property

    Public Property UserName() As String
        Get
            Return _UserName
        End Get
        Set(ByVal Value As String)
            _UserName = Value
        End Set
    End Property

    Public Property Password() As String
        Get
            Return _Password
        End Get
        Set(ByVal Value As String)
            _Password = Value
        End Set
    End Property

    Public Property SelectQuery() As String
        Get
            Return _SelectQuery
        End Get
        Set(ByVal Value As String)
            _SelectQuery = Value
        End Set
    End Property


#End Region

#Region “Logging info”

    Sub ErrorHandler(ByVal exp As Exception)
        Dim LogName As String
        Dim Message As String
        Dim Log As New EventLog

        Try
            LogName = “Application”
            Message = “Message: ” & exp.ToString()

            If (Not EventLog.SourceExists(LogName)) Then
                EventLog.CreateEventSource(LogName, LogName)
            End If

            Log.Source = LogName

            Log.WriteEntry(Message)
            Log.Close()
            Log.Dispose()
        Catch ex As Exception
        End Try
    End Sub

    Sub LogInfo(ByVal strValue As String)
        Dim LogName As String
        Dim Message As String
        Dim Log As New EventLog

        Try
            LogName = “Application”
            Message = “Message: ” & strValue

            If (Not EventLog.SourceExists(LogName)) Then
                EventLog.CreateEventSource(LogName, LogName)
            End If

            Log.Source = LogName

            Log.WriteEntry(Message)
            Log.Close()
            Log.Dispose()
        Catch ex As Exception
        End Try
    End Sub

#End Region 

End Class