I happen to have a script which does exactly this. But it is specific
to my organization. I have trimmed it down and appended it (untested)
below; in theory, it reads hostnames from stdin and dumps each one's
software inventory.
I assume you are looking for the same stuff which shows up in
Add/Remove programs, right? Look in the registry under
HKEY_LOCAL_MACHINE/Software/Microsoft/Windows/CurrentVersion/Uninstall.
You will see a bunch of subkeys there, some with recognizable names,
some without. Ignore their names, and look for values under each
subkey called "DisplayName" and "DisplayVersion". Or see the
get_all_installed() function below.
I also wanted to probe remotely for the vendor and serial number (or
Dell Service tag) of each machine. See get_vendor_serial() below. It
uses WMI, and it only works for systems running Win2k and above.
Although WMI does have a class (Win32_Product) which you can use to
enumerate installed programs, I did not use it because it only knows
about stuff installed by the Windows Installer service (.msi files).
Let me know if you need any help understanding the code.
- Pat
======================================================================
use warnings;
use strict;
use Win32::OLE;
my %reg;
use Win32::TieRegistry (Delimiter => '/', TiedHash => \%reg);
# Warn but do not die if COM engine encounters any trouble.
Win32::OLE->Option ('Warn' => 1);
# Get all of the installed items on a machine. That is, find all of
# the things which show up in "Add/Remove Programs". Return a list of
# informational hashes, including the DisplayName and DisplayVersion
# (if any).
sub get_all_installed ($) {
my ($s_key) = @_;
my $uninstall_key =
$s_key->{'Microsoft/Windows/CurrentVersion/Uninstall/'};
defined $uninstall_key
or die "Unable to open Uninstall key: $^E";
my @results;
foreach my $subkey_name ($uninstall_key->SubKeyNames) {
my $subkey = $uninstall_key->{"$subkey_name/"};
(exists $subkey->{'/DisplayName'}
&& exists $subkey->{'UninstallString'})
or next;
my $pkg = { };
$pkg->{'DisplayName'} = $subkey->{'/DisplayName'};
(exists $subkey->{'/DisplayVersion'})
and $pkg->{'DisplayVersion'} = $subkey->{'/DisplayVersion'};
push @results, $pkg;
}
return @results;
}
# Get the vendor and serial number of a host's BIOS, if possible.
# Return a pair of question marks if not.
sub get_vendor_serial ($) {
my ($wmi) = @_;
my ($vendor, $serial) = ('?', '?');
if (defined $wmi) {
# Get BIOS objects from WMI. See
# <http://msdn.microsoft.com/library/en-us/wmisdk/wmi/win32_bios.asp>
my @bioses = Win32::OLE::Enum->All
($wmi->InstancesOf ('Win32_BIOS'));
my $bios = $bioses[0];
my @enclosures = Win32::OLE::Enum->All
($wmi->InstancesOf ('Win32_SystemEnclosure'));
my $enclosure = $enclosures[0];
my $new_vendor = $bios->{'Manufacturer'};
defined $new_vendor
and $vendor = $new_vendor;
my $new_serial = $bios->{'SerialNumber'};
if (defined $new_serial && $new_serial =~ /\S/) {
$serial = $new_serial;
}
else {
$new_vendor = $enclosure->{'Manufacturer'};
defined $new_vendor
and $vendor = $new_vendor;
foreach my $key ('SerialNumber', 'SMBIOSAssetTag') {
$new_serial = $enclosure->{$key};
defined $new_serial && $new_serial =~ /\S/
and $serial = $new_serial;
}
}
}
return ($vendor, $serial);
}
sub os_version ($$) {
my ($wmi, $s_key) = @_;
my $ret;
if (defined $wmi) {
# We have a working WMI connection, so use it.
my @oses = Win32::OLE::Enum->All
($wmi->InstancesOf ('Win32_OperatingSystem'));
$ret = $oses[0]->{'Caption'};
}
else {
my $base_ver =
$s_key->{'Microsoft/Windows NT/CurrentVersion//CurrentVersion'};
if ($base_ver eq '4.0') {
$ret = 'Windows NT 4.0 (UNKNOWN)';
}
else {
# Other versions of Windows should support WMI.
die "Unrecognized base Windows version $base_ver";
}
}
return $ret;
}
# Sample loop which reads host names and dumps their software
# inventory.
while (my $target = <>) {
chomp $target;
print "($target)\n";
# Get a connection to the WMI service on the remote machine, if
# possible.
my $wmi = Win32::OLE->GetObject ("WinMgmts://$target");
my ($vendor, $serial) = get_vendor_serial ($wmi);
print "--\nVendor: $vendor\nSerial: $serial\n";
# Get handle to HKLM/Software key on remote system
my $software_key = $reg{"//$target/HKEY_LOCAL_MACHINE/Software/"};
print "\n", os_version ($wmi, $software_key), "\n\n";
my @pkgs = get_all_installed ($software_key);
foreach my $pkg (@pkgs) {
my ($name, $version) =
($pkg->{'DisplayName'}, $pkg->{'DisplayVersion'});
print "Name: $name Version: $version\n";
}
print "--\n";
}
_______________________________________________
Perl-Win32-Admin mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs