ADSI - AD access changes/issues in RC2

15 views
Skip to first unread message

Dan Metzler

unread,
Sep 29, 2006, 6:17:18 AM9/29/06
to
So as mentioned in previous threads, I've been playing with the AD
integration in PS.

Here is something that I think is really cool! I'm not sure if it was in
there in the RC1 time frame, and if not, I think this is a very positive
step.

Lets say you need custom attributes in AD or ADAM.

You extend the schema to add an auxilliary class that adds attributes to for
example user objects.
We'll call the new auxiliary class company-newclass.
We define an attribute that uses generalized time syntax. (A date/time field
in LDAP)
We'll call this new attribute company-newtime.
We add the company-newclass auxiliary class to the user class.

We verify that we can now use LDIFDE or some other LDAP tool to modify the
company-newtime attribute on user objects to add a time of the format
20060928120100.0Z. (This is the Generalized Time syntax which means 12:01
on Sept 28, 2006 GMT.)

So then the question is how does this play out in PowerShell?

This is what I think is very cool:
------------------------------------------------------
PS C:\scripts> $ADObject =
[ADSI]LDAP://someserver.company.com/ou=UserOU,dc=someserver,dc=company,dc=com
PS C:\scripts> $ADObject.company-newtime

Wednesday, September 28, 2006 12:01:00 PM

PS C:\scripts> $ADObject.company-newtime = "20060928120200.0Z"
PS C:\scripts> $ADObject.psbase.commitchanges()
PS C:\scripts> $ADObject.company-newtime

Wednesday, September 28, 2006 12:02:00 PM
-------------------------------------------------------

The cool thing here is that even custom LDAP attributes are exposed in this
new layer. Before, this would typically involve some sort of proterties
collection or method.
Using psbase this would be:
$ADObject.psbase.properties.company-newtime
Using a directoryentry in .NET it would be something like
ADObject.properties("company-newtime")


Now here is the thing about these date/time fields in LDAP:

Recall that when I set the time to "20060928120200.0Z". Recall again that
this Generalized Time syntax is Greenwich Mean Time(GMT), (because of the
capital Z on the end).
Even though I'm in the Central Time Zone, the display showed as:
Wednesday, September 28, 2006 12:02:00 PM

With a little more playing in PowerShell...

-------------------------------------------------------------------------
PS C:\scripts> $ADAMObject.company-newtime.gettype()

IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PropertyValueCollection
System.Collections.CollectionBase


PS C:\scripts> $ADAMObject.company-newtime[0].gettype()

IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True DateTime System.ValueType
-----------------------------------------------------------------------
...we see that $ADAMObject.company-newtime is a property collection of
DateTime values.

What this means is that we need to convert the time to the appropriate time
zone if users are to rely on this date and time value for reporting and
other useful things.
If you ever work with the whenCreated and whenChanged attributes in AD,
these are also Generalized Time values.
Just something to keep in mind.

- Dan

Dan Metzler

unread,
Sep 29, 2006, 9:21:08 AM9/29/06
to
And for those who haven't already figured this almost too obvious way to
convert older RC1 PowerShell ADSI scripts to the newer RC2.
Just change the instantiation of the DirectoryEntry object. Thus the
following script:

$ADContainer = New-Object
System.DirectoryServices.DirectoryEntry(LDAP://dc=company,dc=com);
$MyGroups = $ADContainer.get_Children();
...

converts to

$ADContainer = ([ADSI]"LDAP://dc=company,dc=com").psbase;
$MyGroups = $ADContainer.get_Children();
...

"Dan Metzler" <dmet...@southslope.net> wrote in message
news:%23nIryB7...@TK2MSFTNGP03.phx.gbl...

Dan Metzler

unread,
Sep 29, 2006, 9:35:48 AM9/29/06
to
OK... well I spoke too quickly. That doesn't always work.
Directorysearcher doesn't seem to handle that to well.

"Dan Metzler" <dmet...@southslope.net> wrote in message

news:e0Cvho84...@TK2MSFTNGP04.phx.gbl...

/\/\o\/\/ [MVP]

unread,
Sep 29, 2006, 11:36:59 AM9/29/06
to
You do not need it on the searcher as that is ( we are lucky on this one )
not wrapped,

Greetings /\/\o\/\/

"Dan Metzler" <dmet...@southslope.net> wrote in message

news:%23Y0luw8...@TK2MSFTNGP06.phx.gbl...

Jim Holbach

unread,
Sep 30, 2006, 6:15:02 PM9/30/06
to
I agree with MoW in that I think it was a big inconsistent step backwards to
lose the discoverability of the DirectoryEntry methods by get-member.

So my personal "fix" (until this gets fixed in RC3) was that I took the
approach of just extending the type definiton for DirectoryEntry to add the
methods back in as ScriptMethods. (Hey, that seems to be the "PowerShell way"
right? :-) So for example this gives me "get_Children":

<ScriptMethod>
<Name>get_Children</Name>
<Script>
$this.psbase.get_Children()
</Script>
</ScriptMethod>

This seems to have the advantages of (a) not requiring me to change any of
my scripts and (b) at least the ScriptMethods are discoverable with
get-member. As far as I can tell, without the type extension, get-member
doesn't show any methods, with psbase or without.

So I can use your original script unchanged:

PS> $ADContainer = ([ADSI]"LDAP://dc=company,dc=com")
PS> $MyGroups = $ADContainer.get_Children()
PS> $MyGroups

distinguishedName
-----------------
{CN=Builtin,DC=cmcsg,DC=com}
{CN=Computers,DC=cmcsg,DC=com}
{OU=Domain Controllers,DC=cmcsg,DC=com}


etc and I can also do this :


PS> $MyGroups|gm -membertype ScriptMethod

TypeName: System.DirectoryServices.DirectoryEntry

Name MemberType Definition
---- ---------- ----------

GetType ScriptMethod System.Object GetType();
get_Children ScriptMethod System.Object get_Children();
get_Container ScriptMethod System.Object get_Container();
get_Name ScriptMethod System.Object get_Name();
get_NativeGuid ScriptMethod System.Object get_NativeGuid();
get_NativeObject ScriptMethod System.Object get_NativeObject();
Invoke ScriptMethod System.Object Invoke();
InvokeGet ScriptMethod System.Object InvokeGet();
InvokeSet ScriptMethod System.Object InvokeSet();


---
Jim Holbach


"Dan Metzler" wrote:

> And for those who haven't already figured this almost too obvious way to
> convert older RC1 PowerShell ADSI scripts to the newer RC2.
> Just change the instantiation of the DirectoryEntry object. Thus the
> following script:
>
> $ADContainer = New-Object
> System.DirectoryServices.DirectoryEntry(LDAP://dc=company,dc=com);
> $MyGroups = $ADContainer.get_Children();

> ....


>
> converts to
>
> $ADContainer = ([ADSI]"LDAP://dc=company,dc=com").psbase;
> $MyGroups = $ADContainer.get_Children();

> ....

Reply all
Reply to author
Forward
0 new messages