This article shows how to retrieve
Physical and Virtual memory usage on a specific process using Windows
Management Instrumentation (WMI). WMI is Microsoft's implementation of WBEM (Web-Based Enterprise Management). Most administrators are familiar with viewing information in task
manager. One thing I look for is memory settings.
Note: The example below shows the Physical memory usage for
the "sqlserver.exe" process at 43,816 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 the "W3WP.exe" process. You could do this for other
processes too. The one additional function 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 a custom user id and password to the remote machine. Not
assuming the user id credentials the process is running under can be very
handy.
Listing 1
Imports System.Management
Imports System.Data.SqlClient
Module Module1
Private _ComputerName As String = "."
Private _UserName As String = "Changeme to Runon a remote machine"
Private _Password As String = "Changeme to Runon a remote machine"
Private _SelectQuery As String = "SELECT * FROMWin32_Process WHERE name='w3wp.exe'"
Private _DateEntered As DateTime =System.DateTime.Now()
Sub Main()
Try
GetProcessInfo()
Catch f As Exception
ErrorHandler(f)
End Try
End Sub
Sub GetProcessInfo()
Try
'**********************************************
'Uncomment this out if you want to run on a remotemachine and
'comment out the other 'scope' variable
'You will get an error about trying passcredentials to the local machine
'
'Dim options As New ConnectionOptions()
'options.Username = _UserName
'options.Password = _Password
'Dim scope As New ManagementScope("\\"& _ComputerName & "\root\cimv2", options)
'**********************************************
'Comment this out if you are going to test on aremote machine
'This will default to authenticating to the localmachine
Dim scope As New ManagementScope("\\"& _ComputerName & "\root\cimv2")
Dim selectQuery As New SelectQuery(_SelectQuery)
Dim searcher As NewManagementObjectSearcher(scope, selectQuery)
Try
scope.Connect()
Catch f As Exception
ErrorHandler(f)
Exit Sub
End Try
For Each queryObj As ManagementObject Insearcher.Get()
Console.WriteLine(queryObj("WorkingSetSize") / 1024)
Console.WriteLine(queryObj("PeakWorkingSetSize") / 1024)
Console.WriteLine(queryObj("PageFileUsage")/ 1024)
Console.WriteLine(queryObj("PeakPageFileSystem") / 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
'**********************************************
'Uncomment this out if you want to run on a remotemachine and
'comment out the other 'scope' variable
'You will get an error about trying passcredentials to the local machine
'
'Dim options As New ConnectionOptions()
'options.Username = _UserName
'options.Password = _Password
'Dim s As New ManagementScope("\\" &_ComputerName & "\root\cimv2", options)
'**********************************************
'Comment this out if you are going to test on aremote machine
'This will default to authenticating to the localmachine
Dim s As New ManagementScope("\\" &_ComputerName & "\root\cimv2", 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
Sub ErrorHandler(ByVal Exp As Exception)
Dim LogName As String
Dim Message As String
Dim Log As New System.Diagnostics.EventLog
Try
LogName = "Application"
Message = "Message: " &Exp.ToString()
If (Not System.Diagnostics.EventLog.SourceExists(LogName))Then
System.Diagnostics.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 Module
Conclusion
In conclusion, this code snippet can help an IIS
administrator manage the web servers and monitor "W3WP.exe" resource
usage. This information can be recorded to a database and used for future
reporting purposes. Happy WMI coding!