Instantiate a .NET Object with a direct call to a method?

Started by galaara98, July 13, 2015, 03:08:32 PM

Previous topic - Next topic

galaara98

I am trying to emulate the following PowerShell Concept

Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$ctype = New-Object System.DirectoryServices.AccountManagement.ContextType "Machine"
$context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ctype, $computer
$user = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($context, $id)

Note if you create the Object [System.DirectoryServices.AccountManagement.UserPrincipal] without using that method, the method does not exist.  It can only be called at the moment of creation


ObjectClrOption ("use","System.DirectoryServices.AccountManagement, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")

MACHINECONSTANT = 0
NAMEOFSOMECOMPUTER = "zzz.abc.loc"
CType = ObjectClrNew("System.DirectoryServices.AccountManagement.ContextType",MACHINECONSTANT)
Context = ObjectClrNew("System.DirectoryServices.AccountManagement.PrincipalContext",CType,NAMEOFSOMECOMPUTER)
ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",      .............. and this is where i get stuck

Aaron

td

Sticking to the ADSI extender or regular COM AD objects will save you a bunch of typing but to use CLR hosting you need to pass the context as a parameter to the constructor.

Code (winbatch) Select
Context = ObjectClrNew("System.DirectoryServices.AccountManagement.PrincipalContext",CType,NAMEOFSOMECOMPUTER)
ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",  Context ) ; <--------- here
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

galaara98

Quote from: td on July 13, 2015, 07:43:51 PM
Sticking to the ADSI extender or regular COM AD objects will save you a bunch of typing but to use CLR hosting you need to pass the context as a parameter to the constructor.

Code (winbatch) Select
Context = ObjectClrNew("System.DirectoryServices.AccountManagement.PrincipalContext",CType,NAMEOFSOMECOMPUTER)
ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",  Context ) ; <--------- here


Hmm doesnt meet the goal.. I NEED to call the Method FindByIdentity the moment I create the Variable ThisUser

you code creates a UserPrincipal Object, but after that object is created you cannot call the method FindByIdentity
again looking at the powerShell:
$user = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($context, $id)

The Effect of this "style" is to create a UserPrincipal Object that already has the Context of the User I am interested in.
I could then for instance change the user givenname, "save" the change from the cached Object to AD, and done.

Aaron


galaara98

Hmm maybe i misread your response.. I'll try to execute the method after I close the ClrNew paranthesis and let you know how it goes.

As far as .net versus com versus winbatch adsi extender.
I didn't delve into COM much (i'm more familiar with Winbatch and Powershell, so .NET was more appealing)

At least as far as the extender is concerned it can't keep up with the performance.
My application searches for about 10000 objects a day
it then interrogates about 30 attributes each.

The Extender was just much slower than the .NET objects that both search and return properties in one call (now one call to me, admittedly on the wire it might be several calls)
Also the .NET objects can return the objects presorted based on any Property...

Aaron

Ok I cant figure it out

Here is a workign Powershell

[System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices")
[System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.AccountManagement")
#there are easier ways to do this in powershell, however i choose this because it calls constructors just like winbatch would.. 1 is the Constant For ContextType.Domain
$context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext(1,"corp.xxxxxxxx.loc")
$thisuser = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($context, "a_valid_samaccountname")


PS C:\Windows\system32> $thisuser


GivenName                         : -----n
MiddleName                        :
Surname                           : ------h
EmailAddress                      : -------h@b-------.com
VoiceTelephoneNumber              : ###-####
EmployeeId                        : ####
AdvancedSearchFilter              : System.DirectoryServices.AccountManagement.AdvancedFilters
Enabled                           : True
AccountLockoutTime                :
LastLogon                         : 7/8/2015 4:59:26 PM
PermittedWorkstations             : {}
PermittedLogonTimes               : {255, 255, 255, 255...}
AccountExpirationDate             :
SmartcardLogonRequired            : False
DelegationPermitted               : True
BadLogonCount                     : 0
HomeDirectory                     : \\XXXXX\Home\Security\XXXXX
HomeDrive                         : X:
ScriptPath                        :
LastPasswordSet                   : 7/9/2015 6:18:29 PM
LastBadPasswordAttempt            : 7/14/2015 5:32:55 PM
PasswordNotRequired               : False
PasswordNeverExpires              : False
UserCannotChangePassword          : False
AllowReversiblePasswordEncryption : False
Certificates                      : {[Subject]
                                      CN=XXXX XXXXX

                                    [Issuer]
                                      CN=XXXXXXXXXXXXXXXXXXX

                                    [Serial Number]
                                      613CB5130002000073F7

                                    [Not Before]
                                      4/17/2015 3:10:58 PM

                                    [Not After]
                                      4/16/2017 3:10:58 PM

                                    [Thumbprint]
                                      D461734FA0019FBF8AD4C2DEAC939730F6DE8352
                                 
                                    }
Context                           : System.DirectoryServices.AccountManagement.PrincipalContext
ContextType                       : Domain
Description                       : XX - XXXXX
DisplayName                       : AXXXX GXXXX
SamAccountName                    : gXXXXX
UserPrincipalName                 : gXXXXXX@XXXXXX.com
Sid                               : S-1-5-21-2795705288-3334924005-23762XXXXX-1XXXX
Guid                              : cb96a1cf-d6bb-43ad-XXXX-1693cf439a5a
DistinguishedName                 : CN=AXXXXXXX,OU=Users,OU=Information Services,OU=Divisions,DC=XXXX,DC=XXXX,DC=XXXXX
StructuralObjectClass             : user



What i tried in WinBatch
   ;ObjectClrOption("version","v4.0.30319")
   ObjectClrOption ("use","System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
   ObjectClrOption ("use","System.DirectoryServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
   ObjectClrOption ("use","System.DirectoryServices.AccountManagement, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
   ObjectClrOption ("use","System.Net, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
   ObjectClrOption ("use","System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
   ObjectClrOption ("use","System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
   ObjectClrOption ("use","System.IO, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")

   ;ObjectClrOption ("use","System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
   ;BigInteger


MACHINECONSTANT = 0
DOMAINCONSTANT = 1

CType = ObjectClrNew("System.DirectoryServices.AccountManagement.ContextType",MACHINECONSTANT)  ; i know this works from other code
DType = ObjectClrNew("System.DirectoryServices.AccountManagement.ContextType",DOMAINCONSTANT) ; i know this works from other code

ThisContext = ObjectClrNew("System.DirectoryServices.AccountManagement.PrincipalContext",DType,"corp.xxxxxxx.loc"); i know this works from other code

;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",ThisContext)(::FindByIdentity(ThisContext,"a_valid_samaccountname"))
;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",ThisContext)::FindByIdentity(ThisContext,"a_valid_samaccountname")
;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",ThisContext)(FindByIdentity(ThisContext,"a_valid_samaccountname"))
;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",ThisContext)FindByIdentity(ThisContext,"a_valid_samaccountname")
;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",ThisContext).FindByIdentity(ThisContext,"a_valid_samaccountname")
;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",ThisContext),FindByIdentity(ThisContext,"a_valid_samaccountname")

;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal")(::FindByIdentity(ThisContext,"a_valid_samaccountname"))
;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal")::FindByIdentity(ThisContext,"a_valid_samaccountname")
;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal")(FindByIdentity(ThisContext,"a_valid_samaccountname"))
;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",ThisContext)FindByIdentity(ThisContext,"a_valid_samaccountname")
;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal").FindByIdentity(ThisContext,"a_valid_samaccountname")
;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal"),FindByIdentity(ThisContext,"a_valid_samaccountname")

;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",'FindByIdentity(ThisContext,"a_valid_samaccountname")')
;ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",'FindByIdentity',ThisContext,"a_valid_samaccountname")
ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",'FindByIdentity(' : ThisContext : ',"a_valid_samaccountname")')

Could not get it to work

td

FindByIdentity is a static method but you still have to have an object to call it in WinBatch CLR hosting.  This work just fine on our test server:

Code (winbatch) Select

enuDsContex = ObjectClrNew("System.DirectoryServices.AccountManagement.ContextType")
dsDomain      = ObjectClrType("System.DirectoryServices.AccountManagement.ContextType", enuDsContex.Domain)
objPrContext = ObjectClrNew("System.DirectoryServices.AccountManagement.PrincipalContext",dsDomain,"testingserver","me","*topsecret*")
objUser         = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal", objPrContext)
objUser2       = objUser.FindByIdentity(objPrContex, 'rrabbit') ; Roger Rabbit user...
Message("User Name", objUser2.DistinguishedName)
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

And this will work depending on server directory security setting and the relationship between the client and server.
Code (winbatch) Select
enuDsContex = ObjectClrNew("System.DirectoryServices.AccountManagement.ContextType")
dsDomain    = ObjectClrType("System.DirectoryServices.AccountManagement.ContextType", enuDsContex.Domain)
objPrContex = ObjectClrNew("System.DirectoryServices.AccountManagement.PrincipalContext",dsDomain,"TestServer")
objUser     = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal", objPrContex)
objUser2 = objUser.FindByIdentity(objPrContex, 'rrabbit') ; Yes we have a test user named Roger Rabbit.
Message("User Name", objUser2.DistinguishedName)
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

galaara98

Thank you..
I have a program written in-house that helps me navigate .NET objects, i guess i believed it too much when it told me that method was not exposed after the object was created, and didnt try.

DAG_P6

Quote from: galaara98 on July 15, 2015, 08:28:43 AM
I have a program written in-house that helps me navigate .NET objects, i guess i believed it too much when it told me that method was not exposed after the object was created, and didnt try.

If your internal program is dependent upon instantiating an object, I suspect that it will miss static methods, because they belong not to an object, but to the class of which it is an instance. For example, there is no Console object as such; hence, Console.WriteLine is a static method, because you don't (can't, really), instantiate a Console object. Likewise, string.IsNullOrEmpty is a static method on the System.string class, whereas strMyStrng.Split is an instance method of strMyStrng, which is an instance of System.string.
David A. Gray
You are more important than any technology.

td

Quote from: DAG_P6 on July 15, 2015, 03:55:21 PM
Quote from: galaara98 on July 15, 2015, 08:28:43 AM
I have a program written in-house that helps me navigate .NET objects, i guess i believed it too much when it told me that method was not exposed after the object was created, and didnt try.

If your internal program is dependent upon instantiating an object, I suspect that it will miss static methods, because they belong not to an object, but to the class of which it is an instance. For example, there is no Console object as such; hence, Console.WriteLine is a static method, because you don't (can't, really), instantiate a Console object. Likewise, string.IsNullOrEmpty is a static method on the System.string class, whereas strMyStrng.Split is an instance method of strMyStrng, which is an instance of System.string.

Again, this is not correct for WinBatch CLR hosted objects.  You will not 'miss static methods' just because you attempt to call a static method using the dotted  instantiated  object syntax on an actual instantiated object.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

Be interesting to see the effects of just calling the PS directly from WB. Return value could be passed to clipboard then return control of script to WB. But then if the intent is to change the value or make other AD changes then Tony's original suggestion to stay with ADSI Extender and COM makes more sense.