Search Exchange

Search All Sites

Nagios Live Webinars

Let our experts show you how Nagios can help your organization.

Contact Us

Phone: 1-888-NAGIOS-1


Remember Me

Check WMI Plus

7 votes
Current Version
Last Release Date
Compatible With
  • Nagios 3.x
  • Nagios 4.x
  • Nagios XI
Many, many agentless Windows checks using WMI. No need for any software installs on Windows. Monitor Microsoft Windows systems directly from your Nagios server.
Supports user configurable checks using an ini file - create your own WMI Queries.

Check WMI Plus is an extended version of check_wmi. It uses the Windows Management Interface to check for common services (cpu, disk, sevices, eventlog, and more ) on Windows machines. It requires the open source wmi client for Linux.

See the website for (a lot) more details.

Monitor Windows Server 2000, 2003, 2008, 2012, 2016, Windows XP, Windows 7 & 10, Windows Vista etc

Can also monitor the following applications in great detail: Microsoft SQL Server, Microsoft SQL Express, Microsoft Exchange Server, Microsoft IIS, Server, Windows Terminal Services.

Now includes a generic parameter driven event handler that can be used to execute any commands on the Nagios host under many different conditions. Examples provided to restart Windows services.
Overall there are more than 70 different checks it can perform against your Windows machines.

Here is a list of some of the checks it can do:
Built-in checks:
checkcpu, checkcpuq, checkdrivesize, checkeventlog, checkfileage, checkfilesize, checkfoldersize, checkmem, checknetwork, checkprocess, checkservice, checksmart, checktime, checkuptime, checkvolsize, checkwsusserver

Checks via the ini file configuration:
checkad, checkiis, checkts (terminal services), checkio, checkproc (additional process checks), checkeachcpu, checkdhcp, checkdns, checkprint, checkexchange, checksql, checkfolderfileage, checkusers, info

Besides the above checks you can write your own and/or customise the checks configured by ini file.
Reviews (5)
bytompaah, February 9, 2016
I use this on 100+ Windows servers 2008-2012R2 and mostly it works great. It's great not having to use the NSClient.
It uses a bit more resources on the monitoring server but for most I don't think it would be a problem.
For some reason it tends to time out quite often, even when the timout value is increased to 30 secs. Guess the Windows servers are busy doing something else..
byCameronMR, April 10, 2015

I made a change along the same lines as the comment above to allow for more exclusions to be specified. My change to the code is here:

# process any exclusions, if they have been defined
if ($the_arguments{'_arg2'}) {
# exclusion regex defined, decide if we want this row
my @excl = split(/,/,$the_arguments{'_arg2'});
foreach my $service_exclusion (@excl)
if ($$row{'DisplayName'}=~/$service_exclusion/ || $$row{'Name'}=~/$service_exclusion/) {
# regex matches so exclude this row
$debug && print "---> Excluding \"$$row{'DisplayName'}\" ($$row{'Name'})\n";

Thanks for this plugin, it is great!
bydozla, March 18, 2015
Very powerful plugin, no more messing around with NSClient++, just set it up and Monitor machines from XP to Server2012.

Just one little thing for users from other countries, check for the installation language, nonetheless I would recommend using english language, in case your server is installed in e.g. german, review some sql querys, as some parameters on the server might be in german.

Example: In check_wmi_plus/check_wmi_plus.d/check_sql.ini

#query=SELECT * FROM Win32_PerfFormattedData_MSSQLSERVER_SQLServerWaitStatistics where Name = "Average wait time (ms)"
query=SELECT * FROM Win32_PerfFormattedData_MSSQLSERVER_SQLServerWaitStatistics where Name = "Durchschnittliche Wartezeit (ms)"
We made a change to checkservice in to the perl script so we can exclude services.

sub checkservice {
# ------------------------ checking all services
my $where_bit='';
my $auto_mode='';
my $invert_mode='';

if (lc($the_arguments{'_arg1'}) eq 'auto') {
# for this query we need to look for all automatic services
# check that all auto services are
# we do a query that actually always should return data so that we know that the query works
# we could do a select just listing the bad ones, but it returns nothing if good. hard to tell if it really worked ok.
$where_bit="where StartMode=\"auto\"";
} elsif (lc($the_arguments{'_arg1'}) eq 'invert') {
$where_bit="where StartMode=\"auto\"";

if ($the_arguments{'_arg2'} ne '') {

} else {
# for this query we have been passed a regex and must look for that
# so the WMI query should return all services and then we will apply the regex
# this is the default

# wmic returns something like:
# CLASS: Win32_Service
# DisplayName|Name|Started|StartMode|State|Status
# Telnet|TlntSvr|False|Auto|Stopped|OK
# Security Center|wscsvc|True|Auto|Running|OK

my @collected_data;
my $data_errors=get_multiple_wmi_samples(1,
"select displayname, Started, StartMode, State, Status FROM Win32_Service $where_bit",


# at this point we can assume that we have all the data we need stored in @collected_data
my $result_text='';
# now loop through the results, showing the ones requested
my $num_ok=0;
my $num_bad=0;
# so we want to loop through all the rows in the first query result $collected_data[0]
foreach my $row (@{$collected_data[0]}) {
$debug && print "Service Info: " . Dumper($row);
# in the middle of the WMI output there are lines like:
# CLASS: Win32_Service
# CLASS: Win32_TerminalService
# which means DisplayName and Name might not be set so we need to test for this to stop
# "Use of uninitialized value in pattern match" errors
if ($$row{'DisplayName'} && $$row{'Name'}) {
if ( $auto_mode ||
( !$auto_mode && ($$row{'DisplayName'}=~/$the_arguments{'_arg1'}/i || $$row{'Name'}=~/$the_arguments{'_arg1'}/i) )
) {
if ($$row{'Started'} eq 'True' && $$row{'State'} eq 'Running' && $$row{'Status'} eq 'OK') {
if (!$auto_mode) {
# if we have using the regex mode then list out the services we find
$result_text.="'$$row{'DisplayName'}' ($$row{'Name'}) is $$row{'State'}, ";
} else {
if (!$invert_mode) {
$result_text.="'$$row{'DisplayName'}' ($$row{'Name'}) is $$row{'State'}, ";
} else {
if ($$row{'DisplayName'}!~/$the_arguments{'_arg2'}/i && $$row{'Name'}!~/$the_arguments{'_arg2'}/i) {
$result_text.="'$$row{'DisplayName'}' ($$row{'Name'}) is $$row{'State'}, ";

$result_text=~s/, $/./;

# load some values to check warn/crit against

my $test_result=test_limits($opt_warn,$opt_critical,$collected_data[0][0],\%warn_perf_specs_parsed,\%critical_perf_specs_parsed,\@warn_spec_result_list,\@critical_spec_result_list);

my ($this_display_info,$this_performance_data,$this_combined_data)=create_display_and_performance_data($collected_data[0][0],$display_fields{$opt_mode},$performance_data_fields{$opt_mode},\%warn_perf_specs_
print $this_combined_data;

exit $test_result;


So you'll have to give -a invert -o $ARG2 parameter where $ARG2 can be "service1|service2|service3" etc. The listed services will be excluded from the check.
bymrcoffee, April 5, 2011
Downloaded and tested it and it's a very good plugin. Thank you for your additon to the Open Source community!