MS Perl question -- how to use hacked script to work correctly(was Question on loops and return valu

J

James

First off, thanks to all who replied to my original post, I will go
back and reply to each of you .. thank you for your time.
And to everyone else now here, thank you for your time.
I have altered a couple scripts to work in IndigoPerl and
Win32::Resources to accomplish a simple task - read in a list of
servers from a text file, query them for their drives and space on the
drives, and put all the information on space out to a second text file,
space delimited.

My questions are before the code:
The important question is this: How to get an array of drive letters in
use in a foreach loop, and associating that with a hash variable
returning strings.

Example: GetDrives expects a string or empty list, and with the
empty list a foreach loop spits out all drive letters.
Example: In using GetDriveSpace, it returns only the values for C:\
(or whatever ("x:\\") letter you feed it.

So the question is how to get this function (GetDriveSpace) to be
passed an array, essentially - is this impossible potentially because
of the module design? Resources.pm is the module used with this
script. ShowKeys is what returns total, used and free space -- so this
is a third factor in manipulating this array.
I'm really trying to get the values for used, total and free space -
and I'm not quite sure how to get at it, and this is already taking too
long for me to figure out.

Here is the code:
use lib "$ENV(HOME)/site/lib";
no lib ".";
use Win32::Resources;
use Win32API::Resources;
# use strict;
# use warnings;
my @Drives = Win32API::Resources::GetDrives();
my %DRVSpace = Win32API::Resources::GetDriveSpace("C:\\");
my $pathtofiles = "\\C:\\scripts\\";
my $pathtoserverslist = "\\\\xxxxxnnnnnn\\";
my $Threshold = "80";
my $last_updated = localtime (time);
my $GB = 1073741824;
open(HANDLE1,"machines.txt") || die "open: $!";
open(HANDLE2,">>growth.txt") || die "open: $!";
print "\n\nLast run: $last_updated\n";
print "The following are valid disk drives: @Drives\n";
while ($Driveinfo=<HANDLE1>)
{
chomp($Driveinfo);
# @Drivearray=split (/[\\+]/, $Driveinfo);
# ($Total, $Free) = Win32API::Resources::GetDriveSpace
("\\\\$Driveinfo\\");
my $Total = 15073741824;
my $Free = 12073741824;
if ($Total gt 0) # if ($Total)
{
$Growth = ($Total-$Free) / $GB;
$Utilpercentage = ($Total-$Free) * 100 / $Total;
$Total1 = $Total / $GB;
$Free1 = $Free / $GB;
$Used1 = ($Total-$Free) / $GB;
$Total1 = sprintf("%5.2f\n", "$Total1");
$Free1 = sprintf("%5.2f\n", "$Free1");
$Used1 = sprintf("%5.2f\n", "$Used1");
$Utilpercentage = sprintf("%5.2f\n", "$Utilpercentage");
iscritical();
# Writing out the result set for this server\\share combo.
# print HANDLE2 "@Drivearray[0], @Drivearray[2], $Utilpercentage,
$Free1, $Used1,

$Total1 ";
# If the $Total was empty then "N/A" is put in the fields
}
else
{
$Total1 ="N/A";
$Free1 = "N/A";
$Used1 = "N/A";
$Utilpercentage = "N/A";
print HANDLE2 "$Total $Free1 $Used1 $Utilpercentage $Growth\n";
}
printstats();
skey();
}
close(HANDLE1) || die "close0: $!";
close(HANDLE2) || die "close0: $!";
sub iscritical()
{
if ($Utilpercentage >=$Threshold)
{
print "!!Utilized percentage greater than threshold level!!\n";
}
else # non-critical level
{
print "Utilized percentage less than threshold level!\n";
}
}
sub printstats()
{
$T1 = sprintf("%5.2f","$Total1");
$T2 = sprintf("%5.2f","$Free1");
$T3 = sprintf("%5.2f","$Used1");
$T4 = sprintf("%5.2f","$Utilpercentage");
$T5 = sprintf("%5.2f","$Growth");
print "\n\t\t\tUtilized\tGrowth\n";
print "Total:\tFree:\tUsed:\tPercentage:\tRate:\n";
print "$T1\t$T2\t$T3\t $T4\t $T5\n";
print HANDLE2 "$T1 $T2 $T3 $T4 $T5\n";
}
sub skey()
{
my $num_keys = keys %DRVSpace;
print "\n\nNumber of keys in DRVSpace: $num_keys\n";
foreach $let (@Drives)
{
Win32API::Resources::ShowKeys("Drive Space:", 1, \%DRVSpace);
}
}


Thanks to all for their responses and time .. even if it takes me a
while to respond.
 
H

Henry Law

I have altered a couple scripts to work

Indeed you might have but what you posted isn't one of them, at least
not any more. It's got serious syntax errors.

I use Perl under windows mostly so I did copy your code to see if I
could help. Unfortuately ActiveState's Perl (which I have and which
is a very common Perl implementation for Windows) doesn't have the
Win32 modules you are using, and I wasn't able to find any substitutes
in the time I had available to look. Sorry..

I think your question is to do with the loops and what not, rather
than the details of the Windows API code. Can I suggest that you hack
a version of your code so it doesn't need the API calls - hard-code
some suitable values - and then see if you can make that work? If you
can't it would be easy to post it here so that someone (like me, but
preferably someone more skilled) could then actually test your code
without having to go on a scavenger hunt for the required Win32 API
modules.

large snip ..
# Writing out the result set for this server\\share combo.
# print HANDLE2 "@Drivearray[0], @Drivearray[2], $Utilpercentage,
$Free1, $Used1,

$Total1 ";
That line's got an unmatched quote in it. Did you comment out the
first line of a multi-line statement?
 
J

James

Henry said:
On 8 Dec 2004 11:59:05 -0800, "James" <[email protected]>
wrote:

Hi Henry and thanks for your time,
Indeed you might have but what you posted isn't one of them, at least
not any more. It's got serious syntax errors.

I use Perl under windows mostly so I did copy your code to see if I
could help. Unfortuately ActiveState's Perl (which I have and which
is a very common Perl implementation for Windows) doesn't have the
Win32 modules you are using, and I wasn't able to find any substitutes
in the time I had available to look. Sorry..

I thought it was just me. I had originally tried to get a script
working with the AdminMisc package from roth.net, but I could not get
it to work with Active State Perl or Indigo Perl on Windows 2000,
because of a missing .pll (dll?) file that I searched for and could not
find either. I tried using Win32 and Win32API calls on this script.
For all the time I tried to invest in piecing together other people's
code, I should have spent the time learning it in and out and writing
my own. The reverse of an engineer I guess :)
I think your question is to do with the loops and what not, rather
than the details of the Windows API code. Can I suggest that you hack
a version of your code so it doesn't need the API calls - hard-code
some suitable values - and then see if you can make that work? If you
can't it would be easy to post it here so that someone (like me, but
preferably someone more skilled) could then actually test your code
without having to go on a scavenger hunt for the required Win32 API
modules.

I will try the hard coding, even if I have to do it with code from the
..pm file or not. The below line was one of several lines in an
original script which is also connected to the current main while loop
and a few lines below that while statement as well. I will try and get
a full independent script wiorking to a degree tonight and repost.
(oh joy in some of your minds i'm sure :)
large snip ..
# Writing out the result set for this server\\share combo.
# print HANDLE2 "@Drivearray[0], @Drivearray[2], $Utilpercentage,
$Free1, $Used1,

$Total1 ";
That line's got an unmatched quote in it. Did you comment out the
first line of a multi-line statement?

Thanks again,

James
 
S

Sisyphus

James wrote:
..
Example: GetDrives expects a string or empty list, and with the
empty list a foreach loop spits out all drive letters.
Example: In using GetDriveSpace, it returns only the values for C:\
(or whatever ("x:\\") letter you feed it.

So the question is how to get this function (GetDriveSpace) to be
passed an array, essentially - is this impossible potentially because
of the module design?

Yep ... well actually it's the *function* design that makes it
impossible, as the function takes a scalar variable (not a list or a
reference to a list) as its only argument. At least that's the way it is
with the Win32::AdminMisc version of the function.

You would need to do (untested):

use warnings;
use Win32::AdminMisc;

my @drives = GetDrives();

for(@drives) {
my @space = GetDriveSpace($_);
print "$_: @space\n";
}

__END__

Install Win32::AdminMisc using ppm if you can't build it from source.

Cheers,
Rob
 
A

A. Sinan Unur

So the question is how to get this function (GetDriveSpace) to be
passed an array, essentially - is this impossible potentially because
of the module design? Resources.pm is the module used with this
script. ShowKeys is what returns total, used and free space -- so this
is a third factor in manipulating this array.
I'm really trying to get the values for used, total and free space -
and I'm not quite sure how to get at it, and this is already taking too
long for me to figure out.

It would be useful if you learned a little bit of Perl first.
use lib "$ENV(HOME)/site/lib";

What do you think this does?
no lib ".";

Why do you think this is necessary?
use Win32::Resources;

From:

http://search.cpan.org/~fabpot/Win32-Resources-0.02/lib/Win32/Resources.pm

Win32::Resources allows you to deal with windows
executable (.exe or .dll) resources (load, update
and delete resources).

What does this have to do with getting drive space info?
use Win32API::Resources;

OK. This module is not available through ppm but I found it on CPAN.
Downloaded and installed it and read the docs. Have you tried that?
# use strict;
# use warnings;

Why are these commented out?
my @Drives = Win32API::Resources::GetDrives();
my %DRVSpace = Win32API::Resources::GetDriveSpace("C:\\");
my $pathtofiles = "\\C:\\scripts\\";
my $pathtoserverslist = "\\\\xxxxxnnnnnn\\";
my $Threshold = "80";
my $last_updated = localtime (time);

I give up. This crap is much too hard to read. So, you want to:

1. Find out what are the valid drive assignments on your system
2. Find out how much space is on each one

Why not do that?

use strict;
use warnings;

use Win32API::Resources;

use Data::Dumper;

sub get_drive_space_info {
my @drives = Win32API::Resources::GetDrives();
my %drives;
for (@drives) {
$drives{$_} = { Win32API::Resources::GetDriveSpace($_) };
}
return \%drives;
}

sub print_drive_space_info {
my %ds_info = %{ $_[0] };

for my $d (sort keys %ds_info) {
my %drive = %{ $ds_info{$d} };
print "Drive $d\n";
next if exists $drive{0};
for my $k (keys %drive) {
print "\t$k => $drive{$k}\n";
}
}
}

print_drive_space_info(get_drive_space_info());


__END__

Adapt this script to your needs.


Sinan.
 
J

James

A. Sinan Unur said:

Hi Sinan and thanks for your time,
It would be useful if you learned a little bit of Perl first.

True, this would be the ideal situation and I do have a goal to do so.
What do you think this does?

I thought it explicitly stated where the library was.
Why do you think this is necessary?

To not search in the curretn directory for library files?
http://search.cpan.org/~fabpot/Win32-Resources-0.02/lib/Win32/Resources.pm

Win32::Resources allows you to deal with windows
executable (.exe or .dll) resources (load, update
and delete resources).

What does this have to do with getting drive space info?


OK. This module is not available through ppm but I found it on CPAN.
Downloaded and installed it and read the docs. Have you tried that?


Why are these commented out?

These were commented out because it was complaining about global
symbols (for every stated variable) needing an explicit package
reference, and was not quite sure how to get around it. Other than
commenting it out.
my @Drives = Win32API::Resources::GetDrives();
my %DRVSpace = Win32API::Resources::GetDriveSpace("C:\\");
my $pathtofiles = "\\C:\\scripts\\";
my $pathtoserverslist = "\\\\xxxxxnnnnnn\\";
my $Threshold = "80";
my $last_updated = localtime (time);

I give up. This crap is much too hard to read. So, you want to:

1. Find out what are the valid drive assignments on your system
2. Find out how much space is on each one

Why not do that?

use strict;
use warnings;

use Win32API::Resources;

use Data::Dumper;

sub get_drive_space_info {
my @drives = Win32API::Resources::GetDrives();
my %drives;
for (@drives) {
$drives{$_} = { Win32API::Resources::GetDriveSpace($_) };
}
return \%drives;
}

sub print_drive_space_info {
my %ds_info = %{ $_[0] };

for my $d (sort keys %ds_info) {
my %drive = %{ $ds_info{$d} };
print "Drive $d\n";
next if exists $drive{0};
for my $k (keys %drive) {
print "\t$k => $drive{$k}\n";
}
}
}

print_drive_space_info(get_drive_space_info());


__END__

Adapt this script to your needs.


Sinan.

Excellent. Thank you very much for your time. And I will try to learn
(more ?) Perl quickly.

James
 
J

James

Hi Rob and thanks for your time,

I will try to install AdminMisc using the method you suggested after
trying the code above.

Thanks and cheers,

James
 
A

A. Sinan Unur

I thought it explicitly stated where the library was.

C:\Home> cat t.pl
use strict;
use warnings;

use lib "$ENV(HOME)/site/lib";
print @INC;
__END__


C:\Home> perl t.pl
Use of uninitialized value in concatenation (.) or string at t.pl line 4.
(HOME)/site/libc:/opt/Perl/libc:/opt/Perl/site/lib.
To not search in the curretn directory for library files?

Why do you think it is necessary to specify that?


Sinan
 
M

Michele Dondi

Hi Rob and thanks for your time,

I will try to install AdminMisc using the method you suggested after
trying the code above.

Thanks and cheers,

James

Please provide some context.


PS: please do not take mine as an ad hominem attack, either.
Personally I find this (complete lack of any quoting) just as annoying
as top-posting...


Michele
 
J

Joe Smith

James said:
I thought it explicitly stated where the library was.

It would have, if it weren't for the two typographical
errors in that statement. You need to re-read the
docs and look up the difference between parentheses
and curly braces; $ENV(HOME) is not the same a $ENV{HOME}.
-Joe
 
A

A. Sinan Unur

A. Sinan Unur wrote:

[ Full quotation snipped. Don't do that. Figure out the relevant parts of
the post you are replying to, and quote only those parts. Please go
ahead and re-read the posting quidelines so you can help others help
you. ]
First off, thank you much for your help in the past.

You are welcome.
Second, if you have the time/will to do so, can you suggest how to
optimize code like what follows,

You should first get it to compile:

C:\Home> perl -c d4.pl
Semicolon seems to be missing at d4.pl line 7.
Bareword found where operator expected at d4.pl line 12, near "*
use strict"
(Missing operator before strict?)
String found where operator expected at d4.pl line 12, near "strict 'vars'"
(Do you need to predeclare strict?)
syntax error at d4.pl line 11, near "examples
# from O'Reilly books helped set some structure or ideas.
#
"
BEGIN not safe after errors--compilation aborted at d4.pl line 13.
and any suggestions on strong checking of integer bounds (i.e. pos/neg
values affecting the script or its results)?

I am not sure what this all means.
# perl -w

You don't need the shebang line on Windows but the proper syntax is, say,

#! /usr/bin/perl

Note the exclamation point (the bang in shebang).
use strict 'vars';

Why? You should drop this.
use strict;
use warnings;
use Win32API::Resources;
use Win32::NetAdmin;
use Data::Dumper;
our $lastvalue_updated = localtime (time);
our @Drives;

You should declare your variables within the smallest applicable scope.
my $server=our @Driveinfo;

What on earth do you think this does?

The rest of your code, for example,
for my $k (keys %drive)
{
my $string = ($k => $drive{$k});
print "\t$k => $drive{$k}\n";
if ($k eq "DriveSpaceQuotaFree")
{
my $nada = scalar($drive{$k});
next;
}

can only be described as insanity-inducing. It looks like you have not even
made an attempt to actually read any Perl documentation.

In addition to the posting guidelines, it looks like the following
discussion is also relevant in your case:

http://perl.plover.com/Questions.html

You could at least show a minimal amount of respect to your readers by
properly formatting your source code and does not have glaring syntax
errors.
$used = ($total - $free);
$growth = ($used);
Huh?

$growthrate = (($growth * 100) / $total);

Isn't growth supposed represent the change in the used space from the last
time drives were checked?
$total = sprintf("%5.2f","$total");
$free = sprintf("%5.2f","$free");
$used = sprintf("%5.2f","$used");
$growth = sprintf("%5.2f","$growth");
$growthrate = sprintf("%3.2f","$growthrate");
}
print HANDLE2 "$d $total $free $used $growth $growthrate
$lastvalue_updated\n";

Anyway, what is stopping you from:

my $last_update = localtime time;

printf HANDLE2, "%5.2f %5.2f %5.2f %5.2f %3.2f %s",
$d, $total, $free, $used, $growth, $growthrate, $last_update;

Why you would want to have the last update stamp at the end of the line is
beyond me but whatever floats your boat.

Sinan.
 
J

James

Sinan, thank you for taking the time to look over my question and reply
to it. I believe the errors were from (not required in Windows, but
someone made a point of it (for whatever reason) to be like a unix-perl
scripter and use a #! perl -w in the first line, like on unix would be
as you say .. #! /usr/bin/perl -w) my ignorance of not putting a bang
sign on the first line, #! perl -w
The integer bounds question is as growth drops or rises, if it reaches
a point to change sign, is it just a metter of handling exceptions of
variable types in the script, or is it a matter of using any math
functions in your opinion?
Growth-rate is supposed to mark the points/change in values from
current freespace and lastfreespace, and I thought that was a correct
formula. I'll have to play with it and see if it is.
What on earth do you think this does?
I thought this would assign the array to the next server in the list,
where the drive array would be filled/manipulated later in the loop(s).
In a case such as this:
The rest of your code, for example,
can only be described as insanity-inducing. It looks like you have
not even made an attempt to actually read any Perl documentation.
I thought was all right in terms of tossing quotaspace away, I suppose
I could only let is search for the other two cases and omit this key.
I have tried to undestand the $whatnot names. Some of them I
understand, some of them I keep reading over and over to make sense of
them.
The variable growth could be omitted .. if it was necessary to keep
this for a better formula I guess its laziness keeping it here.
Thank you for your help.
James
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top