http://qs321.pair.com?node_id=196981
Category: Win32 Stuff
Author/Contact Info OzzyOsbourne aka Jonathan E. Dyer
Description:

Compares directories on the servers against who is using them in user manager. If no one claims the directory as a home directory in user manager, it is dubbed an orphan and printed to orphans.txt. An e-mail is sent to when the script is complete. This will Get NT4 accounts, or Active Directory (AD) Accounts.

# Compares directories on the servers against who is using them in use
+r manager 
# If no one claims the directory as a home directory in user manager, 
+it is 
# dubbed an orphan and printed to orphans.txt. An e-mail is sent to wh
+en the script 
# is complete.  This will Get NT4 accounts, or Active Directory (AD) A
+ccounts.
#
# Required: File conatining a list of all servers with user shares (1 
+server / line)
#             Modify Variables: $domain, $serverin, $in, $out, $logfil
+e, $smtp, $ADSPath  
#
# Optional:    An SMTP server with open relay (only to use mail capabi
+lity)
#
# Authored by Jonathan E. Dyer

use strict;
use Win32::OLE 'in';
use Win32::NetAdmin qw(GetUsers UserGetAttributes GetDomainController)
+;
  
my $out="//mfappjp1/c\$/scripts/Orphan/accounts.tmp";
open OUT,">$out" or die "Can't open $out for write";
&get_NT4_accts();
&get_AD_accts();
close OUT;
&compare();
&SendEmail();


sub get_NT4_accts{
  my $filter='FILTER_NORMAL_ACCOUNT';
  my $domain='XXXXXXXX';
  my ($x,$homeDir,$account,$PDC,@accounts);

  # Find an NT4 Domain Controller  
  GetDomainController("", $domain, $PDC);

  # Get the Accounts from the Domain
  GetUsers($PDC,$filter, \@accounts) or die "Can't get users $!";
  @accounts = grep (!/\$$/,@accounts); #filter doesn't seem to work, s
+o need to weed out machines.
  print "got $domain accounts\n";

  # Go back and get the HomeDirectory for each account
  foreach $account(@accounts){
    UserGetAttributes("$PDC",$account,$x,$x,$x,$homeDir,$x,$x,$x) or w
+arn "UserGetAttributes() failed: $^E";
    $homeDir=lc ($homeDir);
        $account=lc ($account);
        print OUT "$account\t$homeDir\n";
    }
  print "wrote $domain accounts\n"; 
  sleep 15;   
}

sub get_AD_accts{

    # get ADO object, set the provider, open the connection
    my $ADO = Win32::OLE->new("ADODB.Connection");
    $ADO->{Provider} = "ADsDSOObject";
    $ADO->Open("ADSI Provider");
    
    # Create the ADO Command
    my $ADSPath = "LDAP://OU=group,DC=subdomain,DC=domain,DC=com";
    my $ADOCmd=Win32::OLE->new("ADODB.Command");
    $ADOCmd->{ActiveConnection}=$ADO;
    $ADOCmd->{CommandText}="<$ADSPath>;(objectClass=User);samAccountNa
+me,HomeDirectory;SubTree";#new
    # Next line VERY IMPORTANT if the domain has more than 1000 accoun
+ts.
    $ADOCmd->Properties->{"Page Size"}=10000;
    
    #Execute the Command
    my $users=$ADOCmd->Execute;
    
    #Extract the Info (AccountName, HomeDirectory) from the returned o
+bject
    until ($users->EOF){
        my $homeDir=lc($users->Fields(1)->{Value});
        my $account=lc($users->Fields(0)->{Value});
        print OUT "$account\t$homeDir\n";
        $users->MoveNext;
    }
    $users->Close;
    $ADO->Close;
    print "Wrote CORP Accounts\n";
}

sub ole_error_check{
    if (Win32::OLE->LastError(  )){
        die Win32::OLE->LastError();
    }
}

sub compare{
  my (%is_acct,$x,$key,$homeDir,$account,$userDir,$server);
  my $in="//XXXXXX/XXXXX/XXXXX/accounts.tmp";
  my $out="//XXXXXX/XXXXX/XXXXX/orphans.tmp";
  my $serverin="//XXXXXX/XXXXX/XXXXX/fileprint.txt";
  print "Starting Comparison\n";
  %is_acct=();
  open (IN,"<$in") or die "Can't open $in for read";
  open (SERVERS,"<$serverin") or die "Can't open Server file for read"
+;
  open (OUT,">$out") or die "Can't open $in for write";
  # Create a hash with user accounts and home directory paths
  while (<IN>){
    chomp;
    s/\\/\//g;
    ($account, $homeDir) = split /\t/; 
    $homeDir = lc ($homeDir);
    $is_acct{$homeDir}=$account; #may be a problem
  }
  print "Hash complete\n";

  # Check for user shares on D$ and E$ and exit if not there...
  foreach $server (<SERVERS>){
      chomp $server;
    my $dir1="//$server/d\$/users";
    if (!(-e "$dir1")){#if directory doesn't exist try d$
        $dir1="//$server/e\$/users";
    if (!(-e "$dir1")){#if directory doesn't exist try d$
            $dir1="//$server/users";
        if (!(-e "$dir1")){
            next;
        }
        }
    }
  # Read in the user shares from the servers 
    opendir(DIR, $dir1) or die "can't opendir $dir1: $!";
    my @dirs = grep { !/^\./ && -d "$dir1/$_" } readdir(DIR) or warn "
+can't grep"; #weed out dots and get only dirs
    closedir DIR;
    @dirs = map (lc "//$server/$_", @dirs);
    print "read directories from $server\n";

    foreach $userDir (@dirs){
       print OUT "$userDir";
        if(!exists $is_acct{$userDir}){
            print OUT ": Orphan";
        }
    print OUT "\n";
    }

  }
  close OUT;
}

sub SendEmail {
    my $logfile="//XXXXXX/XXXXX/XXXXX/orphans.txt";
    if (-e $logfile){
        use Net::SMTP;
        my $from="$ENV{USERNAME}";
        my $smtp = Net::SMTP->new('SMTPRelay');
        $smtp->mail($from);
        $smtp->to('you@here.com','me@here.com');
        $smtp->data();
        $smtp->datasend("Subject: Orphan Script Complete\n");
        $smtp->datasend("\n");
        $smtp->datasend("This message was generated and sent by Perl s
+cript without major human intervention.  The Orphans listed are a gui
+deline, and apply only to the XXXXX and XXXXX domains. \n\nfile://XXX
+XXXX/XXXXX/XXXXXX/XXXXXX/orphans.txt\n");
        $smtp->dataend();
    }else{
        die "something went wrong! in mail send";
    }

}