blackadder has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks

Apologies if this question has been covered here before.

I have an Active Directory domain called SSS. In this active directory SSS I have a number of OUs. Each OU has a number of users and attributes.

My question is how can I Enumerate all OU in this AD and print its contents? What would be the best Module to use? And perhaps an example that will enlighten me further please.

Thanks

Btw : How can I install ISG::Win32::ActiveDirectory please? And does this module do what I need?

Thanks
Blackadder
  • Comment on How to Enum windows ActiveDirectory OU objects

Replies are listed 'Best First'.
Re: How to Enum windows ActiveDirectory OU objects
by holli (Abbot) on Mar 07, 2005 at 17:20 UTC
Re: How to Enum windows ActiveDirectory OU objects
by g0n (Priest) on Mar 07, 2005 at 17:30 UTC
    You could also use Net::LDAP, which is extremely widely used and well supported.

    VGhpcyBtZXNzYWdlIGludGVudGlvbmFsbHkgcG9pbnRsZXNz
Re: How to Enum windows ActiveDirectory OU objects
by FitTrend (Pilgrim) on Mar 07, 2005 at 17:59 UTC

    I've used Win32::OLE and Win32::OLE::Enum to grab WMI information. As for enumerating your output, what are you trying to accomplish? I'd tackle this differently based on if you were printing a tree menu of the data, or simply reporting on it.

    Either way I've included a basic example of grabbing a CPU value from WMI. This script contains more source the necessary, to assist with learning.

    #!perl #Change These Variables (Leave all variables BLANK if connecting to lo +cahost)# $server=""; $remote_user=""; $remote_pass=""; use Win32::OLE qw(in with); use Win32::OLE::Enum; Win32::OLE->Option(Warn => 0); ##WMI Connect## $WMI = Win32::OLE->new('WbemScripting.SWbemLocator'); if(!$WMI){ print Win32::OLE->LastError(); exit; } $Services = $WMI->ConnectServer($server, "root/cimv2", $remote_user, $ +remote_pass); if(!$Services){ $err_tmp_raw=Win32::OLE->LastError(); $err_tmp=Win32::OLE->LastError(); $err_tmp=~s/\'/\\'/g; $err_tmp=~s/\"/\\"/g; $err_tmp='Access Denied' if($err_tmp=~m/denied/i); $err_tmp='WMI Not Installed' if($err_tmp=~m/class not registered/i +); $err_tmp='RPC Server Unavailable' if($err_tmp=~m/rpc server is una +vailable/i); print "$err_tmp\n"; print Win32::OLE->LastError(); exit; } my $Processor_set = $Services->InstancesOf("Win32_Processor"); foreach my $object (Win32::OLE::Enum->All($Processor_set)){ print "CPU: $object->{'caption'}\n"; print "CPU Utilization: $object->{'LoadPercentage'}\n"; }

    Hope this helps.

Re: How to Enum windows ActiveDirectory OU objects
by mvaline (Friar) on Mar 07, 2005 at 20:30 UTC
    There may be better ways to do this, but I simply use Win32::OLE to traverse the LDAP hierarchy. This is quick code, but it should point you in the right direction. This will print everything, including a lot of things you probably don't care to see. You could decide whether to look at an object based on its class, and also if it was a class like "user", print out some additional attributes.
    use Win32::OLE qw(in); showObjects("LDAP://[INSERT DOMAIN NAME HERE]",""); sub showObjects { my ($path, $space) = @_; my $object = Win32::OLE->GetObject($path); print "$space $object->{Name} ($object->{Class})\n"; foreach my $childObject (in $object) { showObjects($childObject->ADsPath, $space . " "); } }
    I can't take credit for this approach—I basically translated a solution in O'Reilly's Active Directory Cookbook from VBScript to Perl. If you have to do a lot of AD scripting, this book would probably be a good investment. It's pretty simple to translate its VBScript code into Perl.
Re: How to Enum windows ActiveDirectory OU objects
by Golo (Friar) on Mar 08, 2005 at 09:33 UTC
    You can also use DBI and DBD::ADO to query your Active Directory, to get all objects you could use "(objectCategory=*)" as filter.
    #!perl use strict; use warnings; use Win32::OLE; use DBI; # find the default naming context for the domain we are logged in my $rootDSE = Win32::OLE->GetObject("LDAP://rootDSE")->Get("defaultNam +ingContext") or die "could not get rootDSE"; print "rootDSE is $rootDSE\n"; # Open ADO connection to AD under current logged in user my $dbh = DBI->connect("DBI:ADO:Provider=ADSDSOObject") or die $DBI::e +rrstr; # We're looking for all user objects below the "test" OU my $query = "<LDAP://OU=test,${rootDSE}>;" # the search filter . "(objectCategory=user);" # You can use more criteria to filter on, e.g. # the following would only get user with a name st +arting with A #. "(&(objectCategory=user)(Name=A*));" # what properties we want . "Name,SAMAccountName;" # how deep we want to query, Subtree means we're i +nterested about # the content of all OU's below our start . "Subtree"; # prepare and exec our query my $sth = $dbh->prepare($query) or die $dbh->errstr; $sth->execute(); my @res; while ( my $rec = $sth->fetchrow_hashref() ) { print "$rec->{Name}: $rec->{SAMAccountName}\n"; } $sth->finish(); $dbh->disconnect();
      Thanks to all.
      Blackadder