WinBatch Technical Support Forum

Archived Boards => COM Automation and dotNet => Topic started by: galaara98 on July 13, 2015, 03:08:32 pm

Title: Instantiate a .NET Object with a direct call to a method?
Post by: galaara98 on July 13, 2015, 03:08:32 pm
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
Title: Re: Instantiate a .NET Object with a direct call to a method?
Post by: 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
Context = ObjectClrNew("System.DirectoryServices.AccountManagement.PrincipalContext",CType,NAMEOFSOMECOMPUTER)
ThisUser = ObjectClrNew("System.DirectoryServices.AccountManagement.UserPrincipal",  Context ) ; <--------- here
Title: Re: Instantiate a .NET Object with a direct call to a method?
Post by: galaara98 on July 14, 2015, 08:08:17 am
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
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

Title: Re: Instantiate a .NET Object with a direct call to a method?
Post by: galaara98 on July 14, 2015, 09:24:22 am
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
Title: Re: Instantiate a .NET Object with a direct call to a method?
Post by: td on July 14, 2015, 11:55:05 am
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
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)
 
Title: Re: Instantiate a .NET Object with a direct call to a method?
Post by: td on July 14, 2015, 01:06:24 pm
And this will work depending on server directory security setting and the relationship between the client and server.
Code: Winbatch
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)
 
Title: Re: Instantiate a .NET Object with a direct call to a method?
Post by: galaara98 on July 15, 2015, 08:28:43 am
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.
Title: Re: Instantiate a .NET Object with a direct call to a method?
Post by: DAG_P6 on July 15, 2015, 03:55:21 pm
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.
Title: Re: Instantiate a .NET Object with a direct call to a method?
Post by: td on July 16, 2015, 06:46:42 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.
Title: Re: Instantiate a .NET Object with a direct call to a method?
Post by: stanl on August 10, 2015, 04:29:47 am
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.