in reply to Re: Problem with ascertaining last NT logon - Roth script
in thread Problem with ascertaining last NT logon - Roth script

Thanks for the explanation, Roger. I'm afraid that being a complete noob when it comes to Perl, I can find it quite difficult to visualise what is going on within a hash, particularly if elements are being referenced by other variables.

I can see that my %Result is fairly much only storing {$account} and {%attrib}. And I understand the idea that you need another level (for {%machine}?) in the %Result to store what went on before. But to be frank, thinking in more than 2 hash levels is beyond me at present (some things I can visualise by RFTM, others need to be explained - I'm not a programmer).

Would it be possible for you (or someone else) to give me a snippet of code to show what you mean? Apologies for the "obviousness" of the question... :-(

Also, any links to simple discussions of hashes etc would be helpful - my books are good, but coming at it from a different perspective sometimes helps.

  • Comment on Re: Re: Problem with ascertaining last NT logon - Roth script

Replies are listed 'Best First'.
Re: Re: Re: Problem with ascertaining last NT logon - Roth script
by Roger (Parson) on Feb 17, 2004 at 06:38 UTC
    Ok, here comes the code... Give this a try. See if this gives you what you expect:
    foreach my $Machine ( @MachineList ) { ( $Machine = "\\\\$Machine" ) =~ s/^\\+/\\\\/; print "Querying $Machine\n"; foreach my $Account ( sort keys %AccountList ) { my %Attrib; if( Win32::AdminMisc::UserGetMiscAttributes( $Machine, $Account, \%Attrib ) ) { my $Data = $Result{$Machine}{$Account} = {}; $Data->{fullname} = $Attrib{USER_FULL_NAME}; if( $Data->{lastlogon}->{value} < $Attrib{USER_LAST_LOGON} ) { $Data->{lastlogon}->{value} = $Attrib{USER_LAST_LOGON}; $Data->{lastlogon}->{machine} = $Machine; } if( $Data->{lastlogoff}->{value} < $Attrib{USER_LAST_LOGOFF} ) { $Data->{lastlogoff}->{value} = $Attrib{USER_LAST_LOGOFF}; $Data->{lastlogoff}->{machine} = $Machine; } $Data->{badpwcount} += $Attrib{USER_BAD_PW_COUNT}; $Data->{logons} += $Attrib{USER_NUM_LOGONS}; } } } foreach my $Machine ( sort keys %Result ) { my $MachineInfo = $Results{$Machine}; foreach my $Account ( sort keys %{$MachineInfo} ) { print "$Account ($MachineInfo->{$Account}{fullname}):\n"; print Report( "Last logon", $MachineInfo->{$Account}{lastlogon +} ), "\n"; print Report( "Last logoff", $MachineInfo->{$Account}{lastlogo +ff} ), "\n"; print "\tTotal number of bad password attempts: "; print "$MachineInfo->{$Account}{badpwcount}\n"; print "\tTotal number of logons: $MachineInfo->{$Account}{logo +ns}\n"; print "\n"; } } sub Report { my( $Field, $Data ) = @_; my $Date = scalar localtime($Data->{value} ); my $Location = "( $Data->{machine} )"; $Date = "Not available" if( 0 == $Data->{value} ); $Location = "" if( 0 == $Data->{value} ); return( "\t$Field: $Date $Location" ); }
      That's great! -other than what I presume was a typo,
      foreach my $Machine ( sort keys %Result ) { my $MachineInfo = $Results{$Machine}; foreach my $Account ( sort keys %{$MachineInfo} )
      should be my $MachineInfo = $Result{Machine}??

      The output now produces an entry for each machine in the list. All I have to do now is compare the two entries and get it to spit out the last value in each field from all servers, but I can do that with what you've given me.

      Thanks!

        No, it's not a typo. :-)

        $Machine is a variable that gets populated with a different key from the hash (in sorted order) for each iteration of the outer for loop.