View Full Version : 'Win32_LogicalDisk'
scrupul0us
05-07-2008, 01:32 AM
I'm trying to dump all the disks on my computer... i have 2 network drives attached but for some reason within my structure it never captures
$colLDSK = $objWMI->InstancesOf('Win32_LogicalDisk');
foreach my $objLDSK (in $colLDSK) {
if ($objLDSK->DriveType == 4)
{
print 'Network Drive',"\n";
}
}
^ simplified
it does dump all my other drives just fine in the full script ive got going
ive done some looking around and seen some vague mentioning of "impersonation" and "sessions" being required to obtain these items but havent found much more than that
anyone have any experience using this WMI control that could give me some pointers please?
KevinADC
05-07-2008, 01:43 AM
get rid of the "if" condition and see what gets outputted.
scrupul0us
05-07-2008, 02:09 AM
well like i said thats a real simplified snippet... in reality i have other checking to see:
-if the size is null
-what the drivetype is
-based on the drive type, what media type (to distinguish between floppy and other removable disk)
removing the if structure doesn't do anymore than it already does...
$colLDSK = $objWMI->InstancesOf('Win32_LogicalDisk');
foreach my $objLDSK (in $colLDSK) {
#if ($objLDSK->DriveType == 4)
#{
#print 'Network Drive',"\n";
#}
print $objLDSK->DriveType == 4;
}
theres no output
KevinADC
05-07-2008, 07:54 AM
like this:
$colLDSK = $objWMI->InstancesOf('Win32_LogicalDisk');
foreach my $objLDSK (in $colLDSK) {
print $objLDSK->DriveType,"\n";
}
scrupul0us
05-07-2008, 02:08 PM
output is:
3 5 5 5 2 5
and on this computer i have 2 network drives assigned to letters that aren't showing up (type 4)
scrupul0us
05-08-2008, 03:18 AM
bump for help
FishMonger
05-08-2008, 05:12 AM
Can you post a complete but shortened version of your script so that I can run a few tests?
scrupul0us
05-08-2008, 01:51 PM
#!/perl.exe -wT
print "Content-type:text/html\n\n";
sub commify {
my $input = shift;
$input = reverse $input;
$input =~ s<(\d\d\d)(?=\d)(?!\d*\.)><$1,>g;
return reverse $input;
}
use Win32::OLE qw(in);
$Win32::OLE::Warn = 3;
# ------ SCRIPT CONFIGURATION ------
$strComputer = '.';
# ------ END CONFIGURATION ---------
$objWMI = Win32::OLE->GetObject('winmgmts:\\\\' . $strComputer . '\\root\\cimv2')
$colLDSK = $objWMI->InstancesOf('Win32_LogicalDisk');
foreach my $objLDSK (in $colLDSK)
{
#DEBUG PRINTS ALL DRIVES
print $objLDSK->DriveType,"\n";
if ($objLDSK->Size != 0)
{
if ($objLDSK->DriveType == 4)
{
print $objLDSK->Name. ' '.commify(sprintf("%.0f",$objLDSK->Size)). ' MB', "\n";
}
}
}
youll just have to edit your shebang... thanks :)
FishMonger
05-08-2008, 06:22 PM
I'll run a few tests when I get into work, which will be in about 4 hours (I don't have any mapped network drives on my home system). For now let me touch on a few side issues.
Instead of using the -w switch, it's better to use the warnings pragma. The pragma is lexically scoped and allows you to selectively turn on/off warnings when needed. The -w switch doesn't allow for the selective enabling/disabling and is global which means that it is applied to code in all modules loaded with use or require. So, if a module doesn't properly handle possible warning issues or has intensionally disabled warnings for a certain section of code, the -w switch overrides that and enables the warnings. This can lead to to unexpected and unnecessary warnings.
You should always use the strict pragma which forces you to declare your vars. The strict pragma will help point out lots of simple mistakes that can be hard to trace.
The -T option, when used on Windows, needs to be used on the command line, in addition to or instead of the shebang line. If you don't, Perl will tell you this:"-T" is on the #! line, it must also be used on the command line at...One solution that some people recommend is to modify the file type association to include the -T option.
Finally, and this is only a personal preference on style, place all of your use statements immediately after the shebang line and move your subroutine definitions to the end of the script and place a comment or some type of divider just before the definitions. This will make it easier for others (and you) to locate the main body of the script.
FishMonger
05-08-2008, 07:10 PM
According to your earlier post, you have 4 local CDROM drives. Is that correct? Or, is it possible that 2 of those are the network drives that you seem to be missing, which happen to be remote CDROM drives?
scrupul0us
05-08-2008, 09:05 PM
i dont recall mentioning CD-ROM drives...
as to not confuse you i will also say my script is portable so right NOW at the time of writing this I'm at work and in "my computer" i see:
a:FLOPPY
c:HDD
d:CD-ROM
e:CD-ROM
f:CD-ROM
g:USB HDD
I:CD-ROM
H:Net Drive
P:Net Drive
S:Net Drive
T:Net Drive
U:Net Drive
V:Net Drive
Z:Net Drive
A: / D: / E: / I: do not show b/c they have no disks in the drive and my script ignores null value drives
The 7 network drives do not show at all regardless of checking against null value
At home, where I was originally seeking help from, has much fewer CD-ROM's and network drives, but still, none of the network drives show up
I'm also fairly new to PERL so if you could provide small examples for you comments RE: warnings and pragma I'd appreciate it
FishMonger
05-08-2008, 11:38 PM
i dont recall mentioning CD-ROM drives...You did implicitly in your prior post where you told us the drives types that your script returned.output is:
3 5 5 5 2 5Type 5 is a CDROM drive.
I ran several tests and I was unable to reproduce your problem. The script returned the proper drive types in each of my tests.
Here's the reworked version of your script that i tested.
#!/perl.exe
use strict;
use warnings;
use Win32::OLE qw(in);
Win32::OLE->Option(Warn => 3);
# ------ SCRIPT CONFIGURATION ------
my $strComputer = '.';
# ------ END CONFIGURATION ---------
my %drive = (
0 => 'DRIVE_UNKNOWN',
1 => 'DRIVE_NO_ROOT_DIR',
2 => 'DRIVE_REMOVABLE',
3 => 'DRIVE_FIXED',
4 => 'DRIVE_REMOTE',
5 => 'DRIVE_CDROM',
6 => 'DRIVE_RAMDISK',
);
my $objWMI = Win32::OLE->GetObject("winmgmts:\\\\$strComputer\\root\\cimv2");
my $colLDSK = $objWMI->InstancesOf('Win32_LogicalDisk');
foreach my $objLDSK (in $colLDSK) {
my $type = $objLDSK->DriveType;
my $total_bytes = commify($objLDSK->Size);
printf("%-18s %4s %18s Total Bytes\n",$drive{$type}, $objLDSK->Name, $total_bytes);
}
sub commify {
my $input = shift;
$input = reverse $input;
$input =~ s<(\d\d\d)(?=\d)(?!\d*\.)><$1,>g;
return reverse $input;
}
Here's the results when I ran it.
D:\>scrupul0us.pl
DRIVE_FIXED C: 55,175,143,424 Total Bytes
DRIVE_FIXED D: 82,260,992,000 Total Bytes
DRIVE_CDROM E: 53,673,984 Total Bytes
DRIVE_REMOTE F: 240,845,553,664 Total Bytes
DRIVE_REMOTE G: 1,159,696,789,504 Total Bytes
DRIVE_REMOTE J: 240,845,553,664 Total Bytes
DRIVE_REMOTE L: 4,999,938,048 Total Bytes
DRIVE_REMOTE M: 240,845,553,664 Total Bytes
DRIVE_REMOTE P: 47,906,947,072 Total Bytes
DRIVE_REMOTE T: 1,159,696,789,504 Total Bytes
DRIVE_REMOTE Z: 240,845,553,664 Total Bytes
If you're interested in testing a slightly different approach (i.e. the Win32::DriveInfo module instead of Win32::OLE), here's another test I ran.
#!/usr/bin/perl
use strict;
use warnings;
use Win32::DriveInfo;
my %drive = (
0 => 'DRIVE_UNKNOWN',
1 => 'DRIVE_NO_ROOT_DIR',
2 => 'DRIVE_REMOVABLE',
3 => 'DRIVE_FIXED',
4 => 'DRIVE_REMOTE',
5 => 'DRIVE_CDROM',
6 => 'DRIVE_RAMDISK',
);
foreach my $drive ( Win32::DriveInfo::DrivesInUse ) {
my $type = Win32::DriveInfo::DriveType($drive);
my $total_bytes = commify((Win32::DriveInfo::DriveSpace($drive))[5]);
printf("%-18s %4s: %18s Total Bytes\n",$drive{$type}, $drive, $total_bytes);
}
sub commify {
my $input = shift;
$input = reverse $input;
$input =~ s<(\d\d\d)(?=\d)(?!\d*\.)><$1,>g;
return reverse $input;
}
Here's it's output
D:\>fishmonger.pl
DRIVE_FIXED C: 55,175,143,424 Total Bytes
DRIVE_FIXED D: 82,260,992,000 Total Bytes
DRIVE_CDROM E: 53,673,984 Total Bytes
DRIVE_REMOTE F: 240,845,553,664 Total Bytes
DRIVE_REMOTE G: 1,159,696,789,504 Total Bytes
DRIVE_REMOTE J: 240,845,553,664 Total Bytes
DRIVE_REMOTE L: 4,999,938,048 Total Bytes
DRIVE_REMOTE M: 240,845,553,664 Total Bytes
DRIVE_REMOTE P: 47,906,947,072 Total Bytes
DRIVE_REMOTE T: 1,159,696,789,504 Total Bytes
DRIVE_REMOTE Z: 240,845,553,664 Total Bytes
scrupul0us
05-09-2008, 03:44 AM
i really appreciate the time and effort you've put forth
the first script still leaves out all my mapped drives
the second doesnt work at all... i get a blank white page
FishMonger
05-09-2008, 04:13 AM
The test scripts I posted are not configured to run as cgi scripts, they are meant to run from the console. If you want the output to go to the browser, then change the top portion to this (modify the shebang line as needed):
#!/usr/bin/perl
use strict;
use warnings;
use CGI qw/:standard/;
use CGI::Carp qw/fatalsToBrowser warningsToBrowser/;
use Win32::OLE qw(in);
use Win32::DriveInfo;
print header();
warningsToBrowser(1); # this line causes warnings to show up as html comments
It's very possible that the Win32::DriveInfo module isn't installed on your server, so you may need to install it and Win32::API (which is its dependency module that calls the 2 C functions in kernal32.dll).
FishMonger
05-09-2008, 04:24 AM
I have a suspicion that your cgi environment is not allowing the access to the info for the network drives. Try running the scripts from the command line and see if they return the drive info.
scrupul0us
05-09-2008, 01:56 PM
i get a full dump from the command line... i wonder why running it at the server makes any difference?
remember as i had mentioned i had heard something about mimicking a user session or something to that extent to be able to see the drives, but I can't find much more than that...
does that ring any bells for you?
Oh and here is the thread:
http://www.mombu.com/microsoft/windows-xp-wmi/t-win32-logicaldisk-not-working-properly-199462.html
FishMonger
05-10-2008, 03:58 AM
i get a full dump from the command line... i wonder why running it at the server makes any difference?
The simple answer is user rights.
To view a network share (which may or may not be mapped to a drive letter), you need to be authenticated. This authentication does not always require manually entering a username/password. In the case of your script, when you run it from the command line, it uses your login credentials, but when run as a cgi script, it uses the credentials of the user account of the web server process. The web server process doesn't have rights to see the network share.
Since mapped network drives are associated with a logged-in user account and not the system, visibility of mapped network drives on remote systems will change depending on user account that is currently logged-in locally on that remote system. I don't know of any method to retrieve drive mappings of a user account that is not logged-in.
scrupul0us
05-10-2008, 07:02 PM
ive done some more googling and found a little more info... it seems that you have to add some security details in the moniker
$objWMI = Win32::OLE->GetObject('WinMgmts:{impersonationLevel=impersonate,authenticationLevel=PktPrivacy}!\\\\' . $strComputer . '\\root\\cimv2');
I've found this in quite a few scripts... im still out of luck tho... i'll keep digging around... i know it can be done!
thanks for all your help FishMonger!!!
vBulletin® v3.8.2, Copyright ©2000-2012, Jelsoft Enterprises Ltd.