Archive for June 12th, 2009

Corrupt or Missing Performance Counters

One of the functions in the code I posted in “Check Exchange 2003 vitals with PowerShell” is to check performance counters. When running the script, you may encounter an error:

Get-WmiObject : Invalid Class

 

This could happen for 2 reasons:

1: You have a typo in Perf Counter object.

2: The performance counter is missing on the host you are checking.

 

When this happened to me, I checked and verified this by loading performance monitor on affected server and trying to load Memory counters which the code was checking for. To no surprise, I found that the server did not have Memory object.

There are many reasons why the performance object could go missing from the OS. The KB article “How to manually rebuild Performance Counter Library values” explains how you can resolve this problem and bring the missing performance counter objects back.

  • Share/Bookmark
Print

Tags: , ,

Check Exchange 2003 vitals with PowerShell – Part II

In continuation to my previous post “Check Exchange 2003 vitals with PowerShell”, I also have a code block that you can replace if you want to query all exchange servers in your environment dynamically with script instead of using text file as in the code I posted earlier.

In the code I posted earlier, the following lines read the file servers.txt.

1
2
3
# Read file and store server names in variable
 
$Servers = (Get-Content .\servers.txt)

Replace it with the following, which queries Active Directory for objectclass msExchExchangeServer and returns all servers found.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Get Exchange Servers from Active Directory
 
function GetExchangeServers()
{
	# Set variables to connect to Active Directory, searching Configuration Naming Context
	$root= New-Object System.DirectoryServices.DirectoryEntry("LDAP://RootDSE")
	$configpartition = [adsi]("LDAP://CN=Microsoft Exchange,CN=Services," + $root.configurationNamingContext)
 
	# Set variables for search criteria
	$search = New-Object System.DirectoryServices.DirectorySearcher($configpartition)
	$search.filter = '(objectclass=msExchExchangeServer)'
 
	# Perform Serach, this will return all Exchange Server objects
	$ExchServer = $search.FindAll()
 
	# Output Name property of each server object stored in ExchServer array
	$ExchServer | foreach {$_.properties.name}
 
	# Comment the line above and uncomment the line below if you want to search specific Exchange servers by name
	# The example filter below will only output servers that have MBX in their name (i.e. MBX01, SRVMBX45 etc.)
	#$ExchServer | foreach {$_.properties.legacyexchangedn -match "MBX"}
}

You will also have to replace the lines:

1
2
# Get vitals for each server stored in $Servers array
$Servers | %{getVitals}

with the following:

1
2
# Get vitals for each server stored in $Servers array
GetExchangeServers | %{getVitals}


Comments welcome.

  • Share/Bookmark
Print

Tags: ,

Check Exchange 2003 vitals with PowerShell

I have written recently about Free System PTEs and /PAE usage in Exchange 2003 mailbox servers.

I set out to write a PowerShell script that will run against given list of servers and report back certain vitals including boot.ini settings, SystemPages registry setting and current performance data for Free Sytem PTEs and Pool Non-Paged Bytes.

 

The output csv can be used as a checkpoint for server health and can be used for reporting matrix. The script can easily be modified to add more performance counters and registry checks as necessary.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# Read file and store server names in variable
 
$Servers = (Get-Content .\servers.txt)
 
# Write header in output file
 
# Store header in variable
$headerLine =
@"
 
Server Name,Boot String,3GB,PAE,UserVA,Basevideo,SystemPages,Free System PTEs, Pool Non-Paged Bytes
"@
 
# Write header to file
$headerLine | Out-File .\results.csv -Encoding ASCII -Append
 
function getVitals()
 
{
	# Set server to connect to
	$Server = "$_"
 
# Read SystemPages from servers
 
	# Set Registry Key variables
	$REG_KEY = "System\\CurrentControlSet\\Control\\Session Manager\\Memory Management"
	$VALUE = "SystemPages"
 
	# Open remote registry
	$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Server)
 
	# Open the targeted remote registry key/subkey
	$regKey= $reg.OpenSubKey($REG_KEY)
 
	# Read and Store SystemPages value in variable
	$SystemPages = $regkey.getvalue($VALUE)
 
	# Close the Reg Key
	$regKey.Close()
 
# Read Boot.ini from Servers
 
	# Store Boot.ini contents in variable
	$iniContent = Get-Content "\\$Server\c$\boot.ini"
 
	# Store Boot string and values in variables
	$bootString = $iniContent[4] -replace ","," "
	$userva = ($bootString -split " " | foreach {if ($_ -match "userva") {$_}} | foreach {$_ -replace "/userva=",""})
 
	if ($iniContent[4] -match "3gb") {$3gb="Present"} else {$3gb="Missing"}
	if ($iniContent[4] -match "PAE") {$pae="Present"} else {$pae="Missing"}
	if ($iniContent[4] -match "basevideo") {$basevideo="Present"} else {$userva="Missing"}
 
# Read System Pages and NPP values from Performance Counters
 
	# Read performance counters
	$freeSPTEs = (Get-WmiObject Win32_PerfFormattedData_PerfOS_Memory -ComputerName $Server).FreeSystemPageTableEntries
	$poolNPBytes = (Get-WmiObject Win32_PerfFormattedData_PerfOS_Memory -ComputerName $Server).PoolNonPagedBytes
 
# Write data to file
 
	# Store result string in a variable
	$result = "$Server,$bootString,$3gb,$pae,$userva,$basevideo,$SystemPages,$freeSPTEs,$poolNPBytes"
 
	# Write results to file
	$result | Out-File .\results.csv -Encoding ASCII -Append
 
}
 
 
# Get vitals for each server stored in $Servers array
$Servers | %{getVitals}
  • Share/Bookmark
Print

Tags: ,