question(s) win32::ole and active-directory interaction

Ask a Question related to PERL Modules, Design and Development.

  1. #1

    Default question(s) re: win32::ole and active-directory interaction

    hello,

    i'm curious, could anyone direct me to a half-decent article regarding
    the Win32::OLE module, and using it to interact with active directory?
    i've seen very little on it. the only articles i've come across that
    discuss Win23::OLE where tips/tricks and tutorials on interacting with
    miscellaneous objects in windows (e.g. opening a URL in IE). I've seen
    a very small amount of articles, none of which where of any quality,
    and they mentioned using LDAP as a bridge to AD. is this true? if not,
    is there a better way? - any help would be much appreciated.

    aemaeth9@gmail.com Guest

  2. Similar Questions and Discussions

    1. trying to get Active Directory with SSL
      I am trying to connect to Active Directory that is using SSL to verify a person's user name and password. <cfldap action='QUERY' ...
    2. Active Directory Authorization Store question
      I'm using Authorization and Profile block in my middle tier (.NET Remoting hosted under IIS) for role-based application security. It's all good when...
    3. Active Directory Search fails ("The directory service is unavailab
      Hi all, I'm having one of those nerve wrecking errors, when trying to perform a simple search in an Active Directory. The objective of the code...
    4. Asp.net and Active Directory Log On To
      Hello, I use Active Directory to authenticate users in my Asp.Net web applications. The problem I'm having is that the user's account are set to...
    5. Question about removing a computer from XP Active Directory
      We have a client who inherited two Windows XP Professional machines from their old office (a larger facility running Active Directory, multiple...
  3. #2

    Default Re: question(s) re: win32::ole and active-directory interaction

    [email]aemaeth9@gmail.com[/email] wrote:
    > hello,
    >
    > i'm curious, could anyone direct me to a half-decent article regarding
    > the Win32::OLE module, and using it to interact with active directory?
    > i've seen very little on it. the only articles i've come across that
    > discuss Win23::OLE where tips/tricks and tutorials on interacting with
    > miscellaneous objects in windows (e.g. opening a URL in IE). I've seen
    > a very small amount of articles, none of which where of any quality,
    > and they mentioned using LDAP as a bridge to AD. is this true? if not,
    > is there a better way? - any help would be much appreciated.
    >
    There are at least 2 modules on CPAN dealing with Active Directory or LDAP.

    Win32::AD::User
    Net::LDAP

    I have attached a module I wrote to simplify ADSI queries. You should be
    able to get the basics of ADSI over Win32::OLE by looking at the code.
    But the main information sources are the ADSI-API docs from M$.

    Thomas

    --
    $/=$,,$_=<DATA>,s,(.*),$1,see;__END__
    s,^(.*\043),,mg,@_=map{[split'']}split;{#>J~.>_an~>>e~......>r~
    $_=$_[$%][$"];y,<~>^,-++-,?{$/=--$|?'"':#..u.t.^.o.P.r.>ha~.e..
    '%',s,(.),\$$/$1=1,,$;=$_}:/\w/?{y,_, ,,#..>s^~ht<._..._..c....
    print}:y,.,,||last,,,,,,$_=$;;eval,redo}#.....>.e. r^.>l^..>k^.-

    package Local::ADSI;

    use strict;
    use warnings;

    our $VERSION = "1.01";
    our @ISA = qw(Exporter);

    our @EXPORT = qw(
    ADSIGetGroupMembersRecursive
    ADSIQuery
    ADSISetParam
    $ADSILastErr
    );

    use Win32::OLE qw/in/;
    Win32::OLE->Option(Warn => 1);

    use Data::Dumper;
    $Data::Dumper::Indent = 1;

    our $ADSILastErr = '';

    =head1 NAME

    Local::ADSI - ADSI utility functions

    =head1 VERSION

    This document refers to version 1.01 of Local::ADSI,
    released 04/2006

    =head1 SYNOPSIS

    use Local::ADSI;
    use Data::Dumper;

    my $all_users = ADSIQuery(
    'MY.DOMAIN.NAME',
    {qw/objectClass user/},
    [qw/ADsPath Name displayName/],
    1,
    ) or die $ADSILastErr;

    print Dumper($all_users);


    =head1 DESCRIPTION

    Local::ADSI defines a few utility funtions that should make
    common tasks easier to accomplish.

    All Funtions return undef on error and set $ADSILastErr.

    =head2 ADSIQuery($domain_ou, \%filter, \@outfields, $subtree);

    Run an ADSI query. Simplyfies access to ADODB.Connection and ADODB.Command.
    The filter hash takes properties to search for. Desired output fields can
    be specified in the outfields array. Set subtree to true to search in the
    entire domain or OU.

    $domain_ou can be specified as MY.DOMAIN.NAME/OU/SUB_OU

    Returns a reference to an array of hashes, each hash having the
    selected output fields as keys.

    =cut

    sub ADSIQuery {
    my($Domain, $filter_hash, $outfields, $subtree) = @_;

    my($dom, $ou) = split('/', $Domain, 2);

    my $ADsPath = 'LDAP://';
    $ADsPath .= join(',', map { "OU=" . $_ } split('/', $ou)) . ',' if $ou;
    $ADsPath .= join(',', map { "DC=" . uc } split(/\./, $dom));

    my $filter = '(&';
    $filter .= join(
    '',
    map {
    "($_=" . $filter_hash->{$_} . ')'
    } keys(%$filter_hash)
    );
    $filter .= ')';

    my $fields = join(',', @$outfields);
    my $cmd = join(';', "<$ADsPath>", $filter, $fields, $subtree ? 'subtree' : ());

    my $o_conn = Win32::OLE->new("ADODB.Connection") or do {
    $ADSILastErr = "Cannot create ADODB object!";
    return;
    };
    my $o_cmd = Win32::OLE->new("ADODB.Command") or do {
    $ADSILastErr = "Cannot create ADODB command!";
    return;
    };

    $o_conn->{Provider} = "ADsDSOObject";
    $o_conn->{ConnectionString} = "Active Directory Provider";
    $o_conn->Open();
    $o_cmd->{ActiveConnection} = $o_conn;
    $o_cmd->{CommandText} = $cmd;

    my $o_rec = $o_cmd->Execute() or do {
    $ADSILastErr = "Cannot execute ADODB command!";
    return;
    };

    unless ( $o_rec ) {
    $ADSILastErr = join("\n", values(%{$o_conn->Errors()}));
    return;
    }

    my @records;

    while ( ! $o_rec->EOF ) {
    push( @records, { map { $_ => $o_rec->Fields($_)->value } @$outfields });
    $o_rec->MoveNext;
    }

    $o_rec->Close;
    $o_conn->Close;

    return(\@records);
    }


    =head2 ADSISetParam($path, %param_hash);

    sets and saves a set of parameters for the ADSI object at $path;

    Returns true on success or undef on error.

    =cut

    sub ADSISetParam {
    my $path = shift;

    unless ( 0 == @_ % 2 ) {
    $ADSILastErr = 'ADSISetParam: odd number of params';
    return;
    }

    my %params = @_;

    my $obj = Win32::OLE->GetObject($path) or do {
    $ADSILastErr = Win32::FormatMessage(Win32::LastErr());
    return;
    };

    foreach my $p ( keys(%params) ) {
    $obj->Put($p, $params{$p});
    }

    $obj->SetInfo() && do {
    $ADSILastErr = Win32::FormatMessage(Win32::GetLastError());
    return;
    };

    return(1);
    }


    =head2 ADSIGetGroupMembersRecursive($path);

    Gets all members of a group, including those that get membership
    through another group. Also lists users who have this group as
    primary group (It is a M$ "feature" not to treat those users as
    members of the group).

    Returns a reference to a hash with the member name as the key and the
    displayName as value.

    =cut

    sub ADSIGetGroupMembersRecursive {
    my($group_path) = @_;

    # retrieving the group object
    my $grp_obj = Win32::OLE->GetObject($group_path) or do {
    $ADSILastErr = Win32::FormatMessage(Win32::GetLastError());
    return;
    };

    my @group_stack = ($grp_obj);

    my(%members, %seen);
    while ( @group_stack ) {

    my $obj = shift(@group_stack);
    my $name = $obj->Get('Name');

    # avoid endless recursion
    next if $seen{$name};
    $seen{$name} = 1;

    my $users_with_pg = ADSIGetUsersWithPrimaryGroup($obj) || [];

    $members{$_->{Name}} = $_ for @$users_with_pg;

    foreach my $mem ( in($obj->Members) ) {

    my $name = $mem->Get('Name');
    my $class = $mem->Class;
    my $path = $mem->AdsPath;

    if ( $class eq 'group' ) {

    push @group_stack, $mem;

    }
    else {

    $members{$name} = {
    displayName => $mem->Get('displayName') || '',
    ADsPath => $path,
    };

    }

    }

    }

    return(\%members);
    }


    =head2 ADSIGetUsersWithPrimaryGroup($grp_obj);

    Gets all users who have set the group as primary group.

    $grp_obj is a ADSI group object. It can be created for example by:

    $grp_obj = Win32::OLE->GetObject(<LDAP_PATH>);

    Returns a reference to a hash with the member name as the key and the
    displayName as value.

    =cut

    sub ADSIGetUsersWithPrimaryGroup {
    my($grp_obj) = @_;

    $grp_obj->GetInfoEx(['canonicalName', 'primaryGroupToken'], 0);
    my $cn = $grp_obj->GetEx('canonicalName')->[0];
    my $domain = (split('/', $cn, 2))[0];
    my $pg = $grp_obj->GetEx('primaryGroupToken')->[0];

    my $users_with_pg = ADSIQuery(
    $domain,
    {qw/objectClass user/, primaryGroupID => $pg},
    [qw/ADsPath Name displayName/],
    1,
    ) or do {
    $ADSILastErr = Win32::FormatMessage(Win32::GetLastError());
    return;
    };

    return($users_with_pg);
    }



    =head1 AUTHOR

    Thomas Kratz <ThomasKratz@web.de>

    Copyright (c) 2006 Thomas Kratz. All rights reserved.
    This program is free software; you can redistribute it and/or
    modify it under the same terms as Perl itself.

    =cut


    1;

    Thomas Kratz Guest

  4. #3

    Default Re: question(s) re: win32::ole and active-directory interaction

    Thomas Kratz wrote:
    > [email]aemaeth9@gmail.com[/email] wrote:
    > > hello,
    > >
    > > i'm curious, could anyone direct me to a half-decent article regarding
    > > the Win32::OLE module, and using it to interact with active directory?
    > > i've seen very little on it. the only articles i've come across that
    > > discuss Win23::OLE where tips/tricks and tutorials on interacting with
    > > miscellaneous objects in windows (e.g. opening a URL in IE). I've seen
    > > a very small amount of articles, none of which where of any quality,
    > > and they mentioned using LDAP as a bridge to AD. is this true? if not,
    > > is there a better way? - any help would be much appreciated.
    > >
    >
    > There are at least 2 modules on CPAN dealing with Active Directory or LDAP.
    >
    > Win32::AD::User
    > Net::LDAP
    >
    > I have attached a module I wrote to simplify ADSI queries. You should be
    > able to get the basics of ADSI over Win32::OLE by looking at the code.
    > But the main information sources are the ADSI-API docs from M$.
    >
    > Thomas
    >
    > --
    > $/=$,,$_=<DATA>,s,(.*),$1,see;__END__
    > s,^(.*\043),,mg,@_=map{[split'']}split;{#>J~.>_an~>>e~......>r~
    > $_=$_[$%][$"];y,<~>^,-++-,?{$/=--$|?'"':#..u.t.^.o.P.r.>ha~.e..
    > '%',s,(.),\$$/$1=1,,$;=$_}:/\w/?{y,_, ,,#..>s^~ht<._..._..c....
    > print}:y,.,,||last,,,,,,$_=$;;eval,redo}#.....>.e. r^.>l^..>k^.-
    >
    > --------------040908070706000808060303
    > Content-Type: text/plain
    > Content-Disposition: inline;
    > filename="ADSI.pm"
    > X-Google-AttachSize: 6069
    >
    > package Local::ADSI;
    >
    > use strict;
    > use warnings;
    >
    > our $VERSION = "1.01";
    > our @ISA = qw(Exporter);
    >
    > our @EXPORT = qw(
    > ADSIGetGroupMembersRecursive
    > ADSIQuery
    > ADSISetParam
    > $ADSILastErr
    > );
    >
    > use Win32::OLE qw/in/;
    > Win32::OLE->Option(Warn => 1);
    >
    > use Data::Dumper;
    > $Data::Dumper::Indent = 1;
    >
    > our $ADSILastErr = '';
    >
    > =head1 NAME
    >
    > Local::ADSI - ADSI utility functions
    >
    > =head1 VERSION
    >
    > This document refers to version 1.01 of Local::ADSI,
    > released 04/2006
    >
    > =head1 SYNOPSIS
    >
    > use Local::ADSI;
    > use Data::Dumper;
    >
    > my $all_users = ADSIQuery(
    > 'MY.DOMAIN.NAME',
    > {qw/objectClass user/},
    > [qw/ADsPath Name displayName/],
    > 1,
    > ) or die $ADSILastErr;
    >
    > print Dumper($all_users);
    >
    >
    > =head1 DESCRIPTION
    >
    > Local::ADSI defines a few utility funtions that should make
    > common tasks easier to accomplish.
    >
    > All Funtions return undef on error and set $ADSILastErr.
    >
    > =head2 ADSIQuery($domain_ou, \%filter, \@outfields, $subtree);
    >
    > Run an ADSI query. Simplyfies access to ADODB.Connection and ADODB.Command.
    > The filter hash takes properties to search for. Desired output fields can
    > be specified in the outfields array. Set subtree to true to search in the
    > entire domain or OU.
    >
    > $domain_ou can be specified as MY.DOMAIN.NAME/OU/SUB_OU
    >
    > Returns a reference to an array of hashes, each hash having the
    > selected output fields as keys.
    >
    > =cut
    >
    > sub ADSIQuery {
    > my($Domain, $filter_hash, $outfields, $subtree) = @_;
    >
    > my($dom, $ou) = split('/', $Domain, 2);
    >
    > my $ADsPath = 'LDAP://';
    > $ADsPath .= join(',', map { "OU=" . $_ } split('/', $ou)) . ',' if $ou;
    > $ADsPath .= join(',', map { "DC=" . uc } split(/\./, $dom));
    >
    > my $filter = '(&';
    > $filter .= join(
    > '',
    > map {
    > "($_=" . $filter_hash->{$_} . ')'
    > } keys(%$filter_hash)
    > );
    > $filter .= ')';
    >
    > my $fields = join(',', @$outfields);
    > my $cmd = join(';', "<$ADsPath>", $filter, $fields, $subtree ? 'subtree' : ());
    >
    > my $o_conn = Win32::OLE->new("ADODB.Connection") or do {
    > $ADSILastErr = "Cannot create ADODB object!";
    > return;
    > };
    > my $o_cmd = Win32::OLE->new("ADODB.Command") or do {
    > $ADSILastErr = "Cannot create ADODB command!";
    > return;
    > };
    >
    > $o_conn->{Provider} = "ADsDSOObject";
    > $o_conn->{ConnectionString} = "Active Directory Provider";
    > $o_conn->Open();
    > $o_cmd->{ActiveConnection} = $o_conn;
    > $o_cmd->{CommandText} = $cmd;
    >
    > my $o_rec = $o_cmd->Execute() or do {
    > $ADSILastErr = "Cannot execute ADODB command!";
    > return;
    > };
    >
    > unless ( $o_rec ) {
    > $ADSILastErr = join("\n", values(%{$o_conn->Errors()}));
    > return;
    > }
    >
    > my @records;
    >
    > while ( ! $o_rec->EOF ) {
    > push( @records, { map { $_ => $o_rec->Fields($_)->value } @$outfields });
    > $o_rec->MoveNext;
    > }
    >
    > $o_rec->Close;
    > $o_conn->Close;
    >
    > return(\@records);
    > }
    >
    >
    > =head2 ADSISetParam($path, %param_hash);
    >
    > sets and saves a set of parameters for the ADSI object at $path;
    >
    > Returns true on success or undef on error.
    >
    > =cut
    >
    > sub ADSISetParam {
    > my $path = shift;
    >
    > unless ( 0 == @_ % 2 ) {
    > $ADSILastErr = 'ADSISetParam: odd number of params';
    > return;
    > }
    >
    > my %params = @_;
    >
    > my $obj = Win32::OLE->GetObject($path) or do {
    > $ADSILastErr = Win32::FormatMessage(Win32::LastErr());
    > return;
    > };
    >
    > foreach my $p ( keys(%params) ) {
    > $obj->Put($p, $params{$p});
    > }
    >
    > $obj->SetInfo() && do {
    > $ADSILastErr = Win32::FormatMessage(Win32::GetLastError());
    > return;
    > };
    >
    > return(1);
    > }
    >
    >
    > =head2 ADSIGetGroupMembersRecursive($path);
    >
    > Gets all members of a group, including those that get membership
    > through another group. Also lists users who have this group as
    > primary group (It is a M$ "feature" not to treat those users as
    > members of the group).
    >
    > Returns a reference to a hash with the member name as the key and the
    > displayName as value.
    >
    > =cut
    >
    > sub ADSIGetGroupMembersRecursive {
    > my($group_path) = @_;
    >
    > # retrieving the group object
    > my $grp_obj = Win32::OLE->GetObject($group_path) or do {
    > $ADSILastErr = Win32::FormatMessage(Win32::GetLastError());
    > return;
    > };
    >
    > my @group_stack = ($grp_obj);
    >
    > my(%members, %seen);
    > while ( @group_stack ) {
    >
    > my $obj = shift(@group_stack);
    > my $name = $obj->Get('Name');
    >
    > # avoid endless recursion
    > next if $seen{$name};
    > $seen{$name} = 1;
    >
    > my $users_with_pg = ADSIGetUsersWithPrimaryGroup($obj) || [];
    >
    > $members{$_->{Name}} = $_ for @$users_with_pg;
    >
    > foreach my $mem ( in($obj->Members) ) {
    >
    > my $name = $mem->Get('Name');
    > my $class = $mem->Class;
    > my $path = $mem->AdsPath;
    >
    > if ( $class eq 'group' ) {
    >
    > push @group_stack, $mem;
    >
    > }
    > else {
    >
    > $members{$name} = {
    > displayName => $mem->Get('displayName') || '',
    > ADsPath => $path,
    > };
    >
    > }
    >
    > }
    >
    > }
    >
    > return(\%members);
    > }
    >
    >
    > =head2 ADSIGetUsersWithPrimaryGroup($grp_obj);
    >
    > Gets all users who have set the group as primary group.
    >
    > $grp_obj is a ADSI group object. It can be created for example by:
    >
    > $grp_obj = Win32::OLE->GetObject(<LDAP_PATH>);
    >
    > Returns a reference to a hash with the member name as the key and the
    > displayName as value.
    >
    > =cut
    >
    > sub ADSIGetUsersWithPrimaryGroup {
    > my($grp_obj) = @_;
    >
    > $grp_obj->GetInfoEx(['canonicalName', 'primaryGroupToken'], 0);
    > my $cn = $grp_obj->GetEx('canonicalName')->[0];
    > my $domain = (split('/', $cn, 2))[0];
    > my $pg = $grp_obj->GetEx('primaryGroupToken')->[0];
    >
    > my $users_with_pg = ADSIQuery(
    > $domain,
    > {qw/objectClass user/, primaryGroupID => $pg},
    > [qw/ADsPath Name displayName/],
    > 1,
    > ) or do {
    > $ADSILastErr = Win32::FormatMessage(Win32::GetLastError());
    > return;
    > };
    >
    > return($users_with_pg);
    > }
    >
    >
    >
    > =head1 AUTHOR
    >
    > Thomas Kratz <ThomasKratz@web.de>
    >
    > Copyright (c) 2006 Thomas Kratz. All rights reserved.
    > This program is free software; you can redistribute it and/or
    > modify it under the same terms as Perl itself.
    >
    > =cut
    >
    >
    > 1;
    >
    > --------------040908070706000808060303--
    Thanks Thomas, i appreciate your help :)

    aemaeth9@gmail.com Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139