WMI error 80041010 on performance counters

I recently was having problems with my WMI queries. Following some (bad) advice I rebuilt the repository. It didn’t solve my problem, and afterwards all the performance counter classes had disappeared. Win32_PerfRawData_* and Win32_PerfFormattedData_* were gone, reporting error 0x80041010 [“Invalid class”] (Instead of an error 0x80041010, MS says you might get error 0x80041002 [“Object could not be found”] or error 0x80041006 [“Insufficient memory”] when trying to connect to a nonexistent class.) All the rebuilding and troubleshooting and searching MOF files gave me nothing.

The answer? winmgmt /resyncperf rebuilds the performance counter classes in the repository. To be extra safe, winmgmt /clearadap clears the old data first.

Continue reading “WMI error 80041010 on performance counters”

Using PHP to interface with WMI

Windows Management Instrumentation (WMI) is a Windows derivative of the WBEM standard allowing centralized management of a wide number of Windows functions. There is almost no mention of how to use it from PHP, although combined together they provide a powerful method of web-based management. This example shows how to connect to a remote server, update a single DNS record, then flush the DNS cache.

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
< ?php
$host = 'www';
$ip = '192.168.1.1';
$domain = 'example.com';
$query = "SELECT * FROM MicrosoftDNS_AType WHERE DomainName='$domain' AND OwnerName='$host.$domain'"; 
try {
//create the object
	$rpc = new COM('WbemScripting.SWbemLocator');
//update DNS
	$wmi = $rpc->ConnectServer($rpchost, 'Root/MicrosoftDNS', $user, $pass);
	$hosts = $wmi->ExecQuery($query);
	foreach($hosts as $host) {
		echo "Updating $host->OwnerName from $host->IPAddress to $ip.";
		flush(); ob_flush();
		$result = new Variant(null);
		$host->Modify(null, $ip, $result);
	}
//flush the DNS cache by restarting the dnscache service
	$query = "SELECT * FROM Win32_Service WHERE Name='Dnscache'";
	$wmi = $rpc->ConnectServer($rpchost, 'Root/cimv2', $user, $pass);
	$services = $wmi->ExecQuery($query);
	foreach ($services as $service) {
		$service->StopService();
		sleep(2);
		$service->StartService();
	}
}
catch(Exception $e) {
	echo $e;
	exit;
}?>

< ?php $host = 'www'; $ip = '192.168.1.1'; $domain = 'example.com'; $query = "SELECT * FROM MicrosoftDNS_AType WHERE DomainName='$domain' AND OwnerName='$host.$domain'"; try { //create the object $rpc = new COM('WbemScripting.SWbemLocator'); //update DNS $wmi = $rpc->ConnectServer($rpchost, 'Root/MicrosoftDNS', $user, $pass); $hosts = $wmi->ExecQuery($query); foreach($hosts as $host) { echo "Updating $host->OwnerName from $host->IPAddress to $ip."; flush(); ob_flush(); $result = new Variant(null); $host->Modify(null, $ip, $result); } //flush the DNS cache by restarting the dnscache service $query = "SELECT * FROM Win32_Service WHERE Name='Dnscache'"; $wmi = $rpc->ConnectServer($rpchost, 'Root/cimv2', $user, $pass); $services = $wmi->ExecQuery($query); foreach ($services as $service) { $service->StopService(); sleep(2); $service->StartService(); } } catch(Exception $e) { echo $e; exit; }?>

A couple of points to note:

  1. this is PHP 5 code, it will not work in version 4.
  2. This code uses the COM functions, only available in Windows-based PHP installs.
  3. notice that even though I only pulled one record from the WMI server, I still have to use foreach to iterate through the result set. Like the query itself, the result set is treated the same as one from a database.
  4. I needed to reconnect after the DNS update to use a new namespace; where the DNS server management classes are in the Root/MicrosoftDNS namespace, the service management classes are in the default Root/cimv2 namespace.
  5. Microsoft’s WMI documentation is here. All the code samples are VBScript, but using the example above you should be able to figure things out.