package sysinfo; use strict; require Exporter; @sysinfo::ISA = qw(Exporter); @sysinfo::EXPORT = qw( read_cpus get_os_data get_system_info get_memory_status get_wbem_info get_install_info get_sysinfo print_sysinfo ); use POSIX qw(strftime); use Win32; use Win32::OLE qw(in); use Win32::API; use Win32::TieRegistry; $Registry->Delimiter('/'); $Registry->ArrayValues(1); use constant wbemFlagReturnImmediately => 0x10; use constant wbemFlagForwardOnly => 0x20; my $PROCESSOR_ARCHITECTURE = { 0 => 'x86', 1 => 'MIPS', 2 => 'Alpha', 3 => 'PPC', 5 => 'ARM', 6 => 'IA64', 9 => 'x64' }; sub get_value ($) { my ($node) = @_; my $value = $$node[0]; return undef unless defined $value; my $type = $$node[1]; if ($type == 4 && $value =~ /^0x[0-9a-f]+$/oi) { # REG_DWORD return hex($value); } return $value; } sub defines () { Win32::API::Struct->typedef( SYSTEM_INFO => qw { WORD wProcessorArchitecture; WORD wReserved; DWORD dwPageSize; UINT_PTR lpMinimumApplicationAddress; UINT_PTR lpMaximumApplicationAddress; LPDWORD dwActiveProcessorMask; DWORD dwNumberOfProcessors; DWORD dwProcessorType; DWORD dwAllocationGranularity; WORD wProcessorLevel; WORD wProcessorRevision; } ); Win32::API::Struct->typedef( MEMORYSTATUSEX => qw { DWORD dwLength; DWORD MemLoad; DWORD TotalPhysLo; DWORD TotalPhysHi; DWORD AvailPhysLo; DWORD AvailPhysHi; DWORD TotalPageFileLo; DWORD TotalPageFileHi; DWORD AvailPageFileLo; DWORD AvailPageFileHi; DWORD TotalVirtualLo; DWORD TotalVirtualHi; DWORD AvailVirtualLo; DWORD AvailVirtualHi; DWORD AvailExtendedVirtualLo; DWORD AvailExtendedVirtualHi; } ); Win32::API->Import('kernel32', 'VOID GetSystemInfo(LPSYSTEM_INFO lpSystemInfo)') || die "Could not locate kernel32.dll - cannot call GetSystemInfo()\n"; Win32::API->Import('kernel32', 'BOOL GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpMemoryStatus)') || die "Could not locate kernel32.dll - cannot call GlobalMemoryStatusEx()\n"; } sub get_system_info () { my $si = Win32::API::Struct->new('SYSTEM_INFO'); $si->align('0'); $si->{'wProcessorArchitecture'} = 0; $si->{'wReserved'} = 0; $si->{'dwPageSize'} = 0; $si->{'lpMinimumApplicationAddress'} = 0; $si->{'lpMaximumApplicationAddress'} = 0; $si->{'dwActiveProcessorMask'} = 0; $si->{'dwNumberOfProcessors'} = 0; $si->{'dwProcessorType'} = 0; $si->{'dwAllocationGranularity'} = 0; $si->{'wProcessorLevel'} = 0; $si->{'wProcessorRevision'} = 0; GetSystemInfo($si); my $arch = $si->{'wProcessorArchitecture'}; if (! defined $arch) { $arch = 'Unknown'; } elsif (! defined $$PROCESSOR_ARCHITECTURE{$arch}) { $arch = 'Unknown'; } else { $arch = $$PROCESSOR_ARCHITECTURE{$arch}; } return { ProcArch => $arch }; } sub get_memory_status () { my $ms = Win32::API::Struct->new('MEMORYSTATUSEX'); $ms->align('auto'); $ms->{'dwLength'} = $ms->sizeof(); $ms->{'MemLoad'} = 0; $ms->{'TotalPhysLo'} = 0; $ms->{'TotalPhysHi'} = 0; $ms->{'AvailPhysLo'} = 0; $ms->{'AvailPhysHi'} = 0; $ms->{'TotalPageFileLo'} = 0; $ms->{'TotalPageFileHi'} = 0; $ms->{'AvailPageFileLo'} = 0; $ms->{'AvailPageFileHi'} = 0; $ms->{'TotalVirtualLo'} = 0; $ms->{'TotalVirtualHi'} = 0; $ms->{'AvailVirtualLo'} = 0; $ms->{'AvailVirtualHi'} = 0; $ms->{'AvailExtendedVirtualLo'} = 0; $ms->{'AvailExtendedVirtualHi'} = 0; GlobalMemoryStatusEx($ms); return undef if $ms->{dwLength} == 0; my $memory = {}; if (defined $ms->{'TotalPhysLo'} && defined $ms->{'TotalPhysHi'}) { $$memory{TotalPhysMB} = $ms->{'TotalPhysHi'} * 4096 + int(($ms->{'TotalPhysLo'} + 1048575) / 1048576); } if (defined $ms->{'TotalPageFileLo'} && defined $ms->{'TotalPageFileHi'}) { $$memory{TotalPageFileMB} = $ms->{'TotalPageFileHi'} * 4096 + int(($ms->{'TotalPageFileLo'} + 1048575) / 1048576); } return $memory; } sub get_nodename () { return Win32::NodeName(); } sub get_os_data () { my $guid = $Registry->{'HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Cryptography/MachineGuid'}; die 'Cannot find HKLM\\SOFTWARE\\Microsoft\\Cryptography\\MachineGuid' unless defined $guid; my $nodename = get_nodename(); my $domainname = Win32::DomainName(); my $osdispname = Win32::GetOSDisplayName(); my $osname = Win32::GetOSName(); my ($osver, $osmajor, $osminor, $osbuild) = Win32::GetOSVersion(); my $loginname = Win32::LoginName(); return { MachineGuid => get_value($guid), NodeName => $nodename, DomainName => $domainname, LoginName => $loginname, OSDisplayName => $osdispname, OSName => $osname, OSVersion => $osver, OSMajor => $osmajor, OSMinor => $osminor, OSBuild => $osbuild }; } sub read_cpus () { my $cpus = []; my $cpu = $Registry->{'HKEY_LOCAL_MACHINE/HARDWARE/Description/System/CentralProcessor'}; die 'Cannot find HKLM\\HARDWARE\\Description\\System\\CentralProcessor' unless defined $cpu; foreach my $name ($cpu->SubKeyNames) { my $sub = $cpu->{$name}; next unless defined $sub; my $mhz = get_value($sub->{'~MHz'}); my $vendor = get_value($sub->{'VendorIdentifier'}); my $ident = get_value($sub->{'Identifier'}); my $procname = get_value($sub->{'ProcessorNameString'}); $procname =~ s/^ +//o; $procname =~ s/ +$//o; my $code; if ($ident =~ /Family (\d+) Model (\d+) Stepping (\d+)/o) { $code = $1.'.'.$2.'.'.$3; } push @$cpus, { Id => $name, MHz => $mhz, Vendor => $vendor, Identifier => $ident, Code => $code, Name => $procname }; } return $cpus; } sub get_wbem_info () { my $nodename = get_nodename(); my $wmiservice = Win32::OLE->GetObject('winmgmts:\\\\'.$nodename.'\\root\\CIMV2'); die 'Cannot open WBEM interface' unless defined $wmiservice; my $list = $wmiservice->ExecQuery('SELECT * FROM Win32_ComputerSystem', 'WQL', wbemFlagReturnImmediately | wbemFlagForwardOnly); my $wbem = {}; foreach my $objitem (in $list) { $$wbem{PartOfDomain} = $objitem->{'PartOfDomain'}; $$wbem{Domain} = $objitem->{'Domain'}; $$wbem{Workgroup} = $objitem->{'Workgroup'}; $$wbem{Manufacturer} = $objitem->{'Manufacturer'}; $$wbem{Model} = $objitem->{'Model'}; } return $wbem; } sub get_install_info () { my $sw = $Registry->{'HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion'}; die 'Cannot find HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion' unless defined $sw; my $info = {}; my $installdate = get_value($sw->{'InstallDate'}); $$info{InstallDateNum} = $installdate; $$info{InstallTime} = strftime('%Y-%m-%d %H:%M:%S', localtime($installdate)) if defined $installdate; $$info{ProductId} = get_value($sw->{'ProductId'}); $$info{ProductName} = get_value($sw->{'ProductName'}); $$info{InstallationType} = get_value($sw->{'InstallationType'}); $$info{EditionID} = get_value($sw->{'EditionID'}); $$info{ReleaseId} = get_value($sw->{'ReleaseId'}); $$info{CSDVersion} = get_value($sw->{'CSDVersion'}); $$info{CurrentVersion} = get_value($sw->{'CurrentVersion'}); return $info; } sub get_sysinfo () { return { CPU => read_cpus(), OS => get_os_data(), System => get_system_info(), Memory => get_memory_status(), Install => get_install_info(), WBEM => get_wbem_info() }; } sub print_sysinfo () { my $sysinfo = get_sysinfo(); my $cpus = $$sysinfo{CPU}; my $osdata = $$sysinfo{OS}; my $systeminfo = $$sysinfo{System}; my $memorystatus = $$sysinfo{Memory}; my $install = $$sysinfo{Install}; my $wbem = $$sysinfo{WBEM}; print 'NodeName='.$$osdata{NodeName}.', DomainName='.$$osdata{DomainName}.', LoginName='.$$osdata{LoginName}."\n"; if (defined $$wbem{PartOfDomain}) { print 'NodeStatus='.($$wbem{PartOfDomain} ? 'Domain' : 'Workgroup'). ($$wbem{PartOfDomain} ? (defined $$wbem{Domain} ? ', Domain='.$$wbem{Domain} : '') : (defined $$wbem{Workgroup} ? ', Workgroup='.$$wbem{Workgroup} : '')). "\n"; } print 'MachineGuid='.$$osdata{MachineGuid}."\n"; if (defined $$wbem{Manufacturer}) { print 'Manufacturer='.$$wbem{Manufacturer}; print ', Model='.$$wbem{Model} if defined $$wbem{Model}; print "\n"; } print 'NumProc='.scalar(@$cpus); print ' TotalPhys='.$$memorystatus{TotalPhysMB}.' MB' if defined $$memorystatus{TotalPhysMB}; print ' TotalPageFile='.$$memorystatus{TotalPageFileMB}.' MB' if defined $$memorystatus{TotalPageFileMB}; print ' CPUArch='.$$systeminfo{ProcArch}."\n"; print 'OSDisplayName='.$$osdata{OSDisplayName}.', OSName='.$$osdata{OSName}."\n"; if (defined $$install{ProductName}) { print 'OSProduct='.$$install{ProductName}; print ' OSType='.$$install{InstallationType} if defined $$install{InstallationType}; print ' OSEdition='.$$install{EditionID} if defined $$install{EditionID}; print ' OSRelease='.$$install{ReleaseId} if defined $$install{ReleaseId}; print "\n"; } print 'OSVersion='.$$install{CurrentVersion}.' ' if defined $$install{CurrentVersion}; print 'OSMajor='.$$osdata{OSMajor}.' OSMinor='.$$osdata{OSMinor}.' OSBuild='.$$osdata{OSBuild}; print ' SPVersion='.$$install{CSDVersion} if defined $$install{CSDVersion}; print "\n"; print 'ProductId='.$$install{ProductId}; print ' Installed='.$$install{InstallTime} if defined $$install{InstallTime}; print "\n"; foreach my $cpu (@$cpus) { print $$cpu{Id}.': '.$$cpu{MHz}.' MHz '.$$cpu{Name}.' CPUCode='.$$cpu{Code}."\n"; } } defines(); 1;