ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> perl-win32-users
perl-win32-users
RE: WMI wierdness.
by Jim Lancaster other posts by this author
Aug 31 2003 1:42PM messages near this date
view in the new Beta List Site
Re: Win32 perl versions of touch and chmod? | RE: WMI wierdness.
I thought I was checking for the existence of the key in the lines that
needed it:

if ($os-> {'NumberOfLicensedUsers'}) {
	$os_info{'NumberOfLicensedUsers'} =
$os-> {'NumberOfLicensedUsers'};
} else {
	$os_info{'NumberOfLicensedUsers'} = "unknown";
}

However, your solution is more elegant.



-----Original Message-----
From: Carl Jolley [mailto:cjolley@[...].net] 
Sent: Friday, August 29, 2003 3:03 PM
To: Jim Lancaster
Cc: perl-win32-users@[...].com
Subject: RE: WMI wierdness.


On Fri, 29 Aug 2003, Jim Lancaster wrote:

>  Here is the offending sub:
> 
>  sub os_info {
> 
>      # From the WMI documentation. These are the possible values for
>      #  OSProductSuite:
>      my %os_product_suite = (
>              1 => "Small Business",
>              2 => "Enterprise",
>              4 => "BackOffice",
>              8 => "Communication Server",
>              16 => "Terminal Server",
>              32 => "Small Business (Restricted)",
>              64 => "Embedded NT",
>              128 => "Data Center"
>                             );
> 
>      my %os_info;
>      foreach my $os (in($WMI->InstancesOf("Win32_OperatingSystem"))) {
>          $os_info{'Caption'}                = $os->{'Caption'};
>          $os_info{'FreePhysicalMemory'}     =
>  $os->{'FreePhysicalMemory'};
> 
>         # I'm not sure how/where this is calculated, but it doesn't 
>  appear to jibe with
>          #  the data in Win32_PageFileUsage.
>          $os_info{'FreeSpaceInPagingFiles'} = 
>  $os->{'FreeSpaceInPagingFiles'};
> 
>          $os_info{'InstallDate'} = 
>  substr($os->{'InstallDate'},4,2)."/".
> 
>  substr($os->{'InstallDate'},6,2)."/".
>                                      substr($os->{'InstallDate'},0,4);
>          if ($os->{'NumberOfLicensedUsers'}) {
>              $os_info{'NumberOfLicensedUsers'} = 
>  $os->{'NumberOfLicensedUsers'};
>          } else {
>              $os_info{'NumberOfLicensedUsers'} = "unknown";
>          }
>          $os_info{'NumberOfUsers'}          = $os->{'NumberOfUsers'};
>          if ($os->{'Organization'}) {
>              $os_info{'Organization'}       = $os->{'Organization'};
>          } else {
>              $os_info{'RegisteredUser'}     = "unknown";
>          }
>          if ($os->{'RegisteredUser'}) {
>              $os_info{'RegisteredUser'}     = $os->{'RegisteredUser'};
>          } else {
>              $os_info{'Organization'}       = "unknown";
>          }
>          $os_info{'SerialNumber'}           = $os->{'SerialNumber'};
> 
>          # 'ServicePackMajorVersion' is a feature that was introduced
>          #   with W2K.  Use it if applicable; for earler versions use
>  'CSDVersion'.
>          if ($os->{'Version'} le "5.0") {
>              $os_info{'ServicePack'} = $os->{'CSDVersion'};
>          } else {
>              $os_info{'ServicePack'} = "Service Pack ".
> 
>  $os->{'ServicePackMajorVersion'}.".".
> 
>  $os->{'ServicePackMinorVersion'};
>          }
> 
>          $os_info{'Version'}                = $os->{'Version'};
> 
>          # Calculate system uptime
>          my $byear    = substr($os->{'LastBootUpTime'},0,4);
>          my $bmonth   = substr($os->{'LastBootUpTime'},4,2);
>          my $bday     = substr($os->{'LastBootUpTime'},6,2);
>          my $bhour    = substr($os->{'LastBootUpTime'},8,2);
>          my $bmin     = substr($os->{'LastBootUpTime'},10,2);
>          my $bsec     = substr($os->{'LastBootUpTime'},12,2);
>          my $cyear    = substr($os->{'LocalDateTime'},0,4);
>          my $cmonth   = substr($os->{'LocalDateTime'},4,2);
>          my $cday     = substr($os->{'LocalDateTime'},6,2);
>          my $chour    = substr($os->{'LocalDateTime'},8,2);
>          my $cmin     = substr($os->{'LocalDateTime'},10,2);
>          my $csec     = substr($os->{'LocalDateTime'},12,2);
>          my ($dday,$dhour,$dmin,$dsec) = 
>  Delta_DHMS($byear,$bmonth,$bday,$bhour,$bmin,$bsec,
> 
>  $cyear,$cmonth,$cday,$chour,$cmin,$csec);
>          $os_info{'SystemUptime'} = "$dday days, $dhour hrs, $dmin 
>  mins, $dsec secs";
> 
>          # For testing purposes only.
>          #&dref(0,\%os_info);
>          #exit;
>      }
> 
>      return (%os_info);
> 
>  }
> 
> 
>  -----Original Message-----
>  From: Carl Jolley [mailto:cjolley@[...].net]
>  Sent: Thursday, August 28, 2003 4:15 PM
>  To: Jim Lancaster
>  Cc: perl-win32-users@[...].com
>  Subject: Re: WMI wierdness.
> 
> 
>  On Thu, 28 Aug 2003, Jim Lancaster wrote:
> 
>  > Background:
>  > I'm running perl v5.6.1 build 635 and Win32-OLE 0.1403 on a WinXP 
>  > Pro workstation. I've written a number of scripts to query WMI for 
>  > configuration (system, cpu, memory, disk, nic, etc.) information. 
>  > They
>  > *had* been working fine until I went through them and cleaned up my
>  old
>  > code. (I know, if it ain't broke...<g>).  All I did was replace the
>  use
>  > of Win32-PerfLib with a new sub to calculate system uptime using 
>  > WMI, and replace my clunky html subs with CGI.  The bulk of the WMI 
>  > code I left alone.
>  >
>  > Symptoms:
>  > I can run my script from a command prompt against a single server 
>  > and it works fine. If I queue up several servers in an external cfg 
>  > file, some of the servers generate error messages indicating my 
>  > script is trying to process an uninitialized hash value. The errors 
>  > usually refer to the same couple of lines of code where I'm 
>  > concatenating something, or dividing one number by another to get a 
>  > percentage value.
>  >
>  > Wierdness:
>  > If I change the order of servers in the cfg file, the errors happen 
>  > on
> 
>  > different servers.  It never happens on all of the servers.  The 
>  > position in the list doesn't appear to have any effect.  And if 
>  > there is only one server in the list, no matter which, one, I almost

>  > never see the error.
>  >
>  > Even more wierdness:
>  > I inserted some debugging code in my script to print out the suspect

>  > hash values to the screen and they are there, properly initialized, 
>  > but the very next line of code generates an error that it is not.  
>  > If I "fix" it so that the line generating the error looks for the 
>  > existence of a value before processing, the error goes away, only to

>  > reappear in some other section of code.
>  >
>  > What in the heck is going on?  Is WMI timing out on me?  Is there 
>  > some
> 
>  > kind of memory leak?
>  >
> 
>  Have you ever heard of self-instianting hash values?, i.e. it pops 
>  into existance the first time is is referenced. Including creatiun of 
>  possible multiple levels of hash keys. Make sure your debugging codes 
>  uses nested exists not defined, i.e. use exists on the first level of 
>  hash key and if it does exist then you can use exists on the next 
>  level of hash keys. A little code example would allow me to curb my 
>  speculation.
> 

You're assuming that each of the hash keys you reference in the $os
object exist, or you're assuming that if they don't it won't matter. As
you have probably found out, it does matter. if they don't, then they do
after you do the first check or reference to them. If you do
auto-instaniate the hash key then its related value will be undefined. I
suggest you create a function/subroutine to check for $os hash key
existance so your reference will be conditional on the existance of the
key and the defined state of its value. There are several way you could
do this, this is just one
suggestion:

sub hash_value($) {
  my $key=shift;
  if (exists($os-> {$key}) && defined($os->{$key)) {
     return $os-> {$key};
  }
  else {
#   print STDERR \$os-> {$key} is null\n";
    return "";
  }
}

To generalize this code you might want to consider passing a reference
to the hash as the first parameter instead of referencing a global or a
my variable by name and posible allowing one or more hash keys
parameters to allow for nested hashes key/values. In this instance, If
you determine that certain values of the $os hash keys exist for all
OS'es then you can forget the conditional reference for those particular
has keys.  But I degress.

In your os_info subroutine you could then reference the $os hash
reference like:

$os_info{'FreeSpaceInPagingFiles'} =
&hash_value('FreeSpaceInPagingFiles')

In those cases where you are getting a substring of an $os hash key
value or if you are concating an $os has key value you should retrieve
the value of the coressponging &hash_value and check its length prior to
doing those operations, e.g.

if((length($_=&hash_value{'InstallDate')) == 6) {
   $os_info{'InstallDate'} = substr($_,4,2)."/".
                             substr($_,6,2)."/".
                             substr($_,0,4);
}

This will let you avoid tring to concat a null or undefined string. Note
that some of the hash keys may be present for one OS but not for
another. Since $os is a my variable that holds a reference to a hash for
a particular OS the behavior of of your code might differ for each
instance of your foreach loop.

**** cjolley@[...].net <Carl Jolley> 
**** All opinions are my own and not necessarily those of my employer
****

_______________________________________________
Perl-Win32-Users mailing list Perl-Win32-Users@[...].com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

_______________________________________________
Perl-Win32-Users mailing list
Perl-Win32-Users@[...].com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Thread:
Jim Lancaster
Carl Jolley

Privacy Policy | Email Opt-out | Feedback | Syndication
© ActiveState Software Inc. All rights reserved