[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Delete an AD Attribute via VBScript

Posted on 2011-10-14
46
Medium Priority
?
1,978 Views
Last Modified: 2012-05-12
Since the Google Link is no longer available...
Im trying to perform this in VBscript.

I have 2 attributes I want to not just make null but delete them expongued from the User record.


please help thx

I ref'd. http://www.experts-exchange.com/OS/Microsoft_Operating_Systems/Windows/2000/Q_21192917.html#a36969166 but the link doesnt exist any more hoping to keep example code inline on post for benefit of all users...


also I have something like this to hunt for Group membership but not sure what the objType equivalent is to "group" for retrieving all properties of a person. is it "user" ?


thanks
            
... my local variables declared above ...

strUserToPurge = InputBox("Type in the ID of user", "PURGE USER")
If InStr(strUserToPurge, "\") > 0 Then strUserToPurge = Mid(strUserToPurge, InStr(strUserToPurge, "\") + 1)

strUserPath = Get_LDAP_User_Properties("user", "name", strMyDomain & "\" & strUserToPurge, "adspath", strConnUser, strConnPassword)
' I have something like this to hunt for Group membership but not sure what the objType equivalent is to "group" for retrieving all properties of a person. is it "user" ?

' Delete target Attribute 	strAttribute1 = "myattribute1"
	Set objUser = GetObject(objRecordSet.Fields("strUserPath").Value)
	      objUser.PutEx ADS_PROPERTY_CLEAR, "myattribute1", 0 ' Completely erase 
	objUser.SetInfo


' Delete target Attribute 	strAttribute2 = "myattribute2"
	Set objUser = GetObject(objRecordSet.Fields("strUserPath").Value)
	      objUser.PutEx ADS_PROPERTY_CLEAR, "myattribute2", 0 ' Completely erase 
	objUser.SetInfo


WScript.Quit


' *************************************************
' * Functions
' *************************************************

Function Get_LDAP_User_Properties(strObjectType, strSearchField, strObjectToGet, strCommaDelimProps, strConUser, strConPwd)
      

      If InStr(strObjectToGet, "\") > 0 Then
            arrGroupBits = Split(strObjectToGet, "\")
            strDC = arrGroupBits(0)
            strDNSDomain = strDC & "/" & "DC=" & Replace(Mid(strDC, InStr(strDC, ".") + 1), ".", ",DC=")
            strObjectToGet = arrGroupBits(1)
      Else
      ' Otherwise we just connect to the default domain
            Set objRootDSE = GetObject("LDAP://RootDSE")
            strDNSDomain = objRootDSE.Get("defaultNamingContext")
      End If
 
      Const ADS_SERVER_BIND = &H200
      Const ADS_CHASE_REFERRALS_EXTERNAL = &H40
	
      strBase = "<LDAP://" & strDNSDomain & ">"
      ' Setup ADO objects.
      Set adoCommand = CreateObject("ADODB.Command")
      Set ADOConnection = CreateObject("ADODB.Connection")
      ADOConnection.Provider = "ADsDSOObject"
      If IsNull(strConUser) = False Then ADOConnection.Properties("User ID") = strConUser
      If IsNull(strConPwd) = False Then ADOConnection.Properties("Password") = strConPwd
      If strDC <> "" Then ADOConnection.Properties("ADSI Flag") = ADS_SERVER_BIND
      ADOConnection.Open "Active Directory Provider"
      adoCommand.ActiveConnection = ADOConnection
 
 
      ' Filter on user objects.
      'strFilter = "(&(objectCategory=person)(objectClass=user))"
      strFilter = "(&(objectClass=" & strObjectType & ")(" & strSearchField & "=" & strObjectToGet & "))"
 
      ' Comma delimited list of attribute values to retrieve.
      strAttributes = strCommaDelimProps
      arrProperties = Split(strCommaDelimProps, ",")
 
      ' Construct the LDAP syntax query.
      strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
      adoCommand.CommandText = strQuery
      ' Define the maximum records to return
      adoCommand.Properties("Page Size") = 100
      adoCommand.Properties("Timeout") = 30
      adoCommand.Properties("Cache Results") = False
      If strDC <> "" Then adoCommand.Properties("Chase Referrals") = ADS_CHASE_REFERRALS_EXTERNAL
 
      ' Run the query.
      Set adoRecordset = adoCommand.Execute
      ' Enumerate the resulting recordset.
      strReturnVal = ""
      Do Until adoRecordset.EOF
          ' Retrieve values and display.
          For intCount = LBound(arrProperties) To UBound(arrProperties)
                If strReturnVal = "" Then
                      strReturnVal = adoRecordset.Fields(intCount).Value
                Else
                      strReturnVal = strReturnVal & vbCrLf & adoRecordset.Fields(intCount).Value
                End If
          Next
          ' Move to the next record in the recordset.
          adoRecordset.MoveNext
      Loop
 
      ' Clean up.
      adoRecordset.Close
      ADOConnection.Close
      Get_LDAP_User_Properties = strReturnVal
 
End Function

Open in new window

0
Comment
Question by:JAaron Anderson
  • 32
  • 14
46 Comments
 

Author Comment

by:JAaron Anderson
ID: 36970794
RobSampson  helped me out on this one
http://www.experts-exchange.com/Programming/Languages/Visual_Basic/VB_Script/Q_27100379.html
before...
hopefully he or someone can help me nail down the
strObjectType & strSearchField for properties of a given user (strObjectToGet)
0
 

Author Comment

by:JAaron Anderson
ID: 36970845
hmmmmmmmmm strObjectType, strSearchField

Ive tried combos galore person/cn ; user/cn; user/person; cn/name...

thoughts what it could be? person/username maybe ? hmmmm

for instance
"group", "name", strMainDC & "\" & strSAGroupName, "adspath", strUser, strPassword

WORKS GREAT to get the user's membership of a given  (strSAGroupName)
0
 

Author Comment

by:JAaron Anderson
ID: 36970861
tracking through my successful stable function

I have this statement
"(&(objectClass=" & strObjectType & ")(" & strSearchField & "=" & strObjectToGet & "))"

I just need to identify what is the correct parameter 'value' for a personal attribute


0
Has Powershell sent you back into the Stone Age?

If managing Active Directory using Windows Powershell® is making you feel like you stepped back in time, you are not alone.  For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why.

 

Author Comment

by:JAaron Anderson
ID: 36970891
I think I may had just found out
objectCategory=User
0
 

Author Comment

by:JAaron Anderson
ID: 36971012
Realizing writing to AD will not work the protected attributes I need to
poll are in our Novell LDAP contexts only and ADO is only reflection of
core membership and username info

Can anyone point me in the correct direction regarding binding to an
LDAP-compliant directory that is not Active Directory while using
vbscript? I've scoured the internet alot today and found documentation
seems only able to connect to AD.

thanks
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 36971984
Hi, there's some Novell code here:
http://groups.google.com/group/novell.devsup.ldap_j/browse_thread/thread/ef1fec9c1d86a37e

where it uses username and password to connect to Novell, in the form of:
"CN=admin,o=novell", "novell"

So in my code, if you change this:
ADOConnection.Open "Active Directory Provider"

to something like:
ADOConnection.Open "Active Directory Provider", "CN=admin,o=novell", "novell"

and also change:
strDNSDomain = objRootDSE.Get("defaultNamingContext")

to
strDNSDomain = "localhost/O=novell"

then maybe you will be able to read the attributes.

It also looks like, for Novell, your class (strObjectType) is inetorgperson.

Regards,

Rob.
0
 

Author Comment

by:JAaron Anderson
ID: 36979946
>>objConnection.Open "Active Directory Provider", "CN=admin,o=novell", "novell"

what are these parameters exactly cant find a schema
                              "?? WhatDo i put here ??", "got this" , "I assume this 'novell' is password?"
thx
0
 

Author Comment

by:JAaron Anderson
ID: 36980176
welp I got it to connect. and it queires the whole o=domain because I havent yet made a dynamic hook for the specified user... so Im closer (thx thus far)
I learned "Active Directory Provider" worked sufficiently  ...
I thought it was some vArg I needed to populate with my configs.

...moving on I now need to just figure out how to get the UserPath DN for a given person in the establish ADO bind

Im trying the following code block :
' *************************************************
' Prompt GUI for target User
' *************************************************
strTargetUser = InputBox("Type in targetUser: ", "Specify User", "testuser")
' *************************************************
' Try to perform a lookup for the specified user
' *************************************************
strLookupPath = Get_LDAP_User_Properties("inetorgPerson", "cn", strMainDC & "\" & strTargetUser, "ADsPath", strConnBINDUser, strConnBINDPassword)
' *************************************************
' Echo test lookup path result
' *************************************************
WScript.Echo "path is:" & strLookupPath & ""





' *************************************************
' * Functions
' *************************************************

Function Get_LDAP_User_Properties(strObjectType, strSearchField, strObjectToGet, strCommaDelimProps, strConUser, strConPwd)
      

      If InStr(strObjectToGet, "\") > 0 Then
            arrGroupBits = Split(strObjectToGet, "\")
            strDC = arrGroupBits(0)
            strDNSDomain = strDC & "/" & "DC=" & Replace(Mid(strDC, InStr(strDC, ".") + 1), ".", ",DC=")
            strObjectToGet = arrGroupBits(1)
      Else
      ' Otherwise we just connect to the default domain
            Set objRootDSE = GetObject("LDAP://RootDSE")
            strDNSDomain = objRootDSE.Get("defaultNamingContext")
      End If
 
      Const ADS_SERVER_BIND = &H200
      Const ADS_CHASE_REFERRALS_EXTERNAL = &H40
	
      strBase = "<LDAP://" & strDNSDomain & ">"
      ' Setup ADO objects.
      Set adoCommand = CreateObject("ADODB.Command")
      Set ADOConnection = CreateObject("ADODB.Connection")
      ADOConnection.Provider = "ADsDSOObject"
      If IsNull(strConUser) = False Then ADOConnection.Properties("User ID") = strConUser
      If IsNull(strConPwd) = False Then ADOConnection.Properties("Password") = strConPwd
      If strDC <> "" Then ADOConnection.Properties("ADSI Flag") = ADS_SERVER_BIND
      ADOConnection.Open "Active Directory Provider"
      adoCommand.ActiveConnection = ADOConnection
 
 
      ' Filter on user objects.
      'strFilter = "(&(objectCategory=person)(objectClass=user))"
      strFilter = "(&(objectClass=" & strObjectType & ")(" & strSearchField & "=" & strObjectToGet & "))"
 
      ' Comma delimited list of attribute values to retrieve.
      strAttributes = strCommaDelimProps
      arrProperties = Split(strCommaDelimProps, ",")
 
      ' Construct the LDAP syntax query.
      strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
      adoCommand.CommandText = strQuery
      ' Define the maximum records to return
      adoCommand.Properties("Page Size") = 100
      adoCommand.Properties("Timeout") = 30
      adoCommand.Properties("Cache Results") = False
      If strDC <> "" Then adoCommand.Properties("Chase Referrals") = ADS_CHASE_REFERRALS_EXTERNAL
 
      ' Run the query.
      Set adoRecordset = adoCommand.Execute
      ' Enumerate the resulting recordset.
      strReturnVal = ""
      Do Until adoRecordset.EOF
          ' Retrieve values and display.
          For intCount = LBound(arrProperties) To UBound(arrProperties)
                If strReturnVal = "" Then
                      strReturnVal = adoRecordset.Fields(intCount).Value
                Else
                      strReturnVal = strReturnVal & vbCrLf & adoRecordset.Fields(intCount).Value
                End If
          Next
          ' Move to the next record in the recordset.
          adoRecordset.MoveNext
      Loop
 
      ' Clean up.
      adoRecordset.Close
      ADOConnection.Close
      Get_LDAP_User_Properties = strReturnVal
 
End Function

Open in new window

0
 

Author Comment

by:JAaron Anderson
ID: 36982245


according to the link provided
objCommand.CommandText = _
    "<LDAP://localhost/O=novell>;" & _
        "(&(objectClass=inetorgPerson));" & _
            "ADsPath,telephoneNumber;subtree"

works fine but I need to inject a dynamic cn in the statement

THIS WORKS :::
objCommand.CommandText = "<LDAP://biggie.widener.edu/O=widener>; (cn=janderson1); ADsPath,PSVQ0;subtree"      


THIS DOES NOT WORK?!?!?!? ::: :( :S
objCommand.CommandText = "<LDAP://biggie.widener.edu/O=widener>; (cn="& strUserToPurge &"); ADsPath,PSVQ0;subtree"      

how must I escape out in order to pass the dynamic user input ? thx

0
 

Author Comment

by:JAaron Anderson
ID: 36982250
hard coded works GREAT but that doesnt solve my dynamic needs to cater to user input :(
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 36983761
Hi, if this works:
objCommand.CommandText = "<LDAP://biggie.widener.edu/O=widener>; (cn=janderson1); ADsPath,PSVQ0;subtree"      

Then there's no reason why this wouldn't work:
strUserToPurge = "janderson1"
objCommand.CommandText = "<LDAP://biggie.widener.edu/O=widener>; (cn="& strUserToPurge &"); ADsPath,PSVQ0;subtree"

So, the way you have the function at the moment, if you try calling it like this:
strTargetUser = "janderson1"
strLookupPath = Get_LDAP_User_Properties("inetorgPerson", "cn", strTargetUser, "ADsPath", strConnBINDUser, strConnBINDPassword)

it should work.

Above this though:
      Const ADS_SERVER_BIND = &H200

you might want to try putting
strDNSDomain = "biggie.widener.edu/O=widener"

and see if that helps.  If it does, this section is not required:
      If InStr(strObjectToGet, "\") > 0 Then
            arrGroupBits = Split(strObjectToGet, "\")
            strDC = arrGroupBits(0)
            strDNSDomain = strDC & "/" & "DC=" & Replace(Mid(strDC, InStr(strDC, ".") + 1), ".", ",DC=")
            strObjectToGet = arrGroupBits(1)
      Else
      ' Otherwise we just connect to the default domain
            Set objRootDSE = GetObject("LDAP://RootDSE")
            strDNSDomain = objRootDSE.Get("defaultNamingContext")
      End If

Open in new window


because that's really for AD structured FQDNs.

Rob.
0
 

Author Comment

by:JAaron Anderson
ID: 36985905
I learned my testaccount I was working against was NOT completely created as an object with all parameters as normal accounts my admin told me. we recreated it and now it works thx

we code thinking everything around is a perfect world ready to go lol...
:D



ok next moving onto not just setting the attribute null but deleting the attributes all together in particular in the test code above Im trying to access to delete "PSVQ0" its a integer but probably stored as a string if that matters
0
 

Author Comment

by:JAaron Anderson
ID: 36986642
In short another way to pinpoint my problem is
how to I nest a dynamic path into the GetObject functino

Set executePURGE = GetObject(""&objRecordset.Fields(AdsPath)&"")

not working now :(
0
 

Author Comment

by:JAaron Anderson
ID: 36986684


the error Im getting is " The attribute type specified to the directory is not defined. "

right above the Set instruction I have an Echo statement with the objRecordSet.Field Value being retrieved for visual fine ...:(

I am able to set it to a variable and return and display it.
I just cant seem to nest that variable into the Get object statement :S
0
 

Author Comment

by:JAaron Anderson
ID: 36986794
I also get this error tinkering
"The specified directory service attribute or value does not exist."
0
 

Author Comment

by:JAaron Anderson
ID: 36988427
Also I am confident I can retireve from NDS/ldap not from ADO because :
objRecordset.Fields("whateverattributeString")
is displaying returning values correctly... ADO does not physically have these attributes only NDS
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 36989340
Instead of this:
Set executePURGE = GetObject(""&objRecordset.Fields(AdsPath)&"")

you need this:
Set executePURGE = GetObject(objRecordset.Fields("AdsPath"))

"AdsPath" is the field name, so you need that enclosed in quotes, not the whole thing.

Try that.....
0
 

Author Comment

by:JAaron Anderson
ID: 37006645
##hmmm still saying Object Required... Im not sure whats broke here
##so if I have this statement

objCommand.CommandText = "<LDAP://biggie.widener.edu/o=widener>; (cn=" & strUser & "); ADsPath;subtree"

## and I goto run it
Set objRecordSet = objCommand.Execute

##then assign its result in a collection
userPathFound = objRecordSet.Fields("AdsPath")

how do I get all the other field attributes for this user ?
Set objRecordSet = objCommand.Execute
    If objRecordSet.EOF Then
	strErrorNull2 = MsgBox("No such User is Found",vbCritical,"Verify Error")
     Else
' *************************************************
' When target User account is FOUND
' *************************************************
     While Not objRecordset.EOF
        userPathFound = objRecordSet.Fields("AdsPath")
        userAnswer0 = objRecordSet.Fields("PSVA0") ??????????????????????????????
' *************************************************
' PERFORM PURGE ACTIONS
' *************************************************
	Set executePURGE = GetObject(objRecordset.Fields("PSVA0"))
	    executePURGE.PutEx ADS_PROPERTY_CLEAR, "PSVA0", 0 'Completely erase 
        executePURGE.SetInfo
' *************************************************
' HOUSEKEEPING
' *************************************************
objRecordset.MoveNext
Wend
End If
objConnection.Close

Open in new window

0
 

Author Comment

by:JAaron Anderson
ID: 37006919
in this example
Set x = GetObject("LDAP://CN=JeffSmith,CN=Users,DC=Fabrikam,DC=com")
on URL http://msdn.microsoft.com/en-us/library/windows/desktop/aa746353%28v=vs.85%29.aspx

see the Get object is (" ")

Set x = GetObject(objRecordSet.Fields("AdsPath"))
wont that just do:
Set x = GetObject(LDAP://CN=JeffSmith,CN=Users,DC=Fabrikam,DC=com)
or do the double quotes really not matter there ?
0
 

Author Comment

by:JAaron Anderson
ID: 37007172
also must I use ADS_PROPERTY_CLEAR, or ADS_PROPERTY_DELETE because I know the attributes do not exit in ADO but they DO in eDirectory...

could it somehow be trying to reach and delete from ADO using these ADO constants...

is there anything like NOVELL_PROPERTY_CLEAR ?...
does that make sense or am I reaching
0
 

Author Comment

by:JAaron Anderson
ID: 37007309
backing out of my script I find


Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider", "****cn path ******", "********password *******"
            
## then another one ??????????                                    
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection

                        
objCommand.CommandText = "<LDAP://biggie.widener.edu/O=widener>; (cn="&strSpecifiedCN&"); ADsPath;subtree"



how exactly should the blocl look like to connect ONLY to eDirectory including constants?
                        
                        
0
 

Author Comment

by:JAaron Anderson
ID: 37007328
     objCommand.ActiveConnection = objConnection is seriously confusing is all this neccessary ?
0
 

Author Comment

by:JAaron Anderson
ID: 37007376
objConnection.Provider = "ADsDSOObject" seems to blow out my BIND if I remove it but I think this is connecting to my ADO not eDirectory...
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37015934
Hi, you've asked a lot of questions now, but I'll to answer them.

You asked "how do I get all the other field attributes for this user?"

In AD, there are two ways.  For information retrieval, you can use:
objCommand.CommandText = "<LDAP://biggie.widener.edu/o=widener>; (cn=" & strUser & "); ADsPath,PSVA0;subtree"

where each attribute you want to return is listed before the ;subtree part.  Then you retrieve *only* the ones you listed, by using
        userPathFound = objRecordSet.Fields("AdsPath")
        userAnswer0 = objRecordSet.Fields("PSVA0")

But the Fields("attributename") must be specified in the query when using that method.

Method 2 is to bind to object, which we've tried to do (I think, although I can't see it in your code) with
Set objUser = GetObject(userPathFound)

If we haven't tried that, put that line under
        userPathFound = objRecordSet.Fields("AdsPath")

Then, if it binds successfully, you can do something like:
        userAnswer0 = objUser.PSVA0
or
        userAnswer0 = objUser.Get("PSVA0")


In the example you mentioned where you asked "or do the double quotes really not matter there?"
This depends on whether you are binding to a string that you are entering, or to a variable that holds a string value.

For example, if you were to use:
Set objUser = GetObject("LDAP://CN=JeffSmith,CN=Users,DC=Fabrikam,DC=com")

then you *do* need the quotes, since it's a string, however, if you use:
strUserADsPath = "LDAP://CN=JeffSmith,CN=Users,DC=Fabrikam,DC=com"
Set objUser = GetObject(strUserADsPath)

then you don't need the quotes in the GetObject call because the string is in a variable.


>> must I use ADS_PROPERTY_CLEAR, or ADS_PROPERTY_DELETE

Probably not.  These constants translate to 1 and 4 respectively, and are likely different in the NDS world.  I found another thread:
http://groups.google.com/group/novell.devsup.ldap_j/browse_thread/thread/79e690259930ace6

that suggests you might just be able to do this:
objUser.Delete "PSVA0"

after binding to the user object.


And finally, onto this:
objConnection.Open "Active Directory Provider", "****cn path ******", "********password *******"

and
objCommand.ActiveConnection = objConnection
objCommand.CommandText = "<LDAP://biggie.widener.edu/O=widener>; (cn="&strSpecifiedCN&"); ADsPath;subtree"

The first objConnection.Open creates the initial connection, using the credentials of cn path and password, whereas the *command* first *uses* the connection as its object to run the command, then runs the CommandText string, as a directory search.

I think though, whether you use
objConnection.Provider = "Active Directory Provider"
or
objConnection.Provider = "ADsDSOObject"

it shouldn't make much difference.  It should be the LDAP service you're connecting to that defines what you can do with it.

Hope that helps.

Rob.
0
 

Author Comment

by:JAaron Anderson
ID: 37024781
thanks Rob everything is connecting and returning fine!
now for deletion...
getting a type mismatch error on the following code block


' *************************************************
' CONNECTION Block
' *************************************************
''Creating the Connection Object
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
'' Setting the Data Source
objConnection.Open "Active Directory Provider", "ldap,user,name", "clear_text_password"
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection
objCommand.CommandText = "<LDAP://myldapserver/ou=forrest/o=domain>; (cn=" & strUserToPurge & "); ADsPath,testAttribute;subtree"	
				
Set objRecordSet = objCommand.Execute
' *************************************************
' Error null handling
' *************************************************		
If objRecordSet.EOF Then
strErrorNull = MsgBox("No User is Found", vbOKCancel,  "Error")
Else
' *************************************************
' When target User is FOUND
' *************************************************
While Not objRecordset.EOF
         userStringFound = objRecordSet.Fields("testAttribute")
' *************************************************
' Perform deletion NOT yet working... :(  
         objRecordSet.Delete userStringFound 
' *************************************************
         objRecordset.MoveNext
Wend
End If
' *************************************************
' housekeeping
' *************************************************
objConnection.Close

Open in new window

0
 

Author Comment

by:JAaron Anderson
ID: 37025057



in the deletion block if I try :

objRecordset.PutEx ADS_PROPERTY_DELETE, "testAttribute", Array(userStringFound)
objRecordset.SetInfo


I get an error Object doesn't support this property or method.
SO I know this technique is not the right path to take...
Im continuing to hunt for functional sample code to perform the ldap edirectory attributes deletion I require

thanks please advise next suggestion to try....
0
 

Author Comment

by:JAaron Anderson
ID: 37027538
none of these iterations work type mismatch all...

objRecordSet.Remove(objRecordSet.Fields("PSVA0").Value)
...
objRecordSet.Remove(objRecordSet.Fields("PSVA0"))
...
objRecordSet.Remove objRecordSet.Fields("PSVA0")  
...
string = objRecordSet.Fields("PSVA0")
objRecordSet.Remove string
...
objRecordSet.Delete("PSVA0") ' learned cannot use parenthesis when calling a SubFunction
...
objRecordSet.Delete((objRecordSet.Fields("PSVA0"))

Im at my wits end ; even hoped novell would respond in simplest forms no avail :S
https://twitter.com/#!/JAaronAnderson/status/128916130365579264
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37027892
The recordset does not actually contain any bindings to the objects in the directory.  The recordset is just a data set, like that returned from a query in Access.  You need to bind to the user object you want to delete a value from.  Please try changing this:
While Not objRecordset.EOF
         userStringFound = objRecordSet.Fields("testAttribute")
' *************************************************
' Perform deletion NOT yet working... :(  
         objRecordSet.Delete userStringFound 
' *************************************************
         objRecordset.MoveNext
Wend

Open in new window


to something like:
While Not objRecordset.EOF
	' Retreive the values from the recordset
	strADsPath = objRecordSet.Fields("adsPath")
    userStringFound = objRecordSet.Fields("testAttribute")
    
    ' Bind to the object
    WScript.Echo "Binding to " & strADsPath
    Set objUser = GetObject(strADsPath)
    WScript.Echo "Retrieving PSVA0 attribute..."
    strPSVA0 = objUser.Get("PSVA0")
    WScript.Echo "PSVA0 value is " & strPSVA0
    WScript.Echo "Deleting PSVA0 attribute..."
    objUser.Delete "PSVA0"
    WScript.Echo "Setting info...not sure if this is required in eDirectory..."
    objUser.SetInfo
    
	objRecordset.MoveNext
Wend

Open in new window


Note that once you have bound to the object, you should have available to you each of the attributes that you have permission to view, and not just those specified in the LDAP query.

So, running that code you will see the LDAP path that it is attempting to bind to.  Firstly, once you see the text echoed to screen, make sure this follows the same syntax as that you have in the LDAP query.  The structure and path should be the same.

Secondly, I try to retrieve an attribute value that you have not specified on the LDAP query, just to illustrate that point.

Third, we try to delete that PSVA0 value.

Finally, in the Active Directory world, you need to use SetInfo when you make changes to a user object, so I've included it, but not sure if it's required for eDirectory.

Regards,

Rob.
0
 

Author Comment

by:JAaron Anderson
ID: 37032110
strPSVA0 = objUser.Get("PSVA0") isnt seeming to return its blank "null"

is there a mapping issue in your sample ?
how is userStringFound used ?


I got
objCommand.CommandText = "<LDAP://myserver/o=mydomainforrest>; (cn=" & strTargetUserToDeleteFrom & ");ADsPath,PSVA0;subtree"
just above this block but for some reason doesnt seem to connect now :(

please help ...
Ill begin exploring the objUser and whay its not binding...
thx
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37034553
In my example, userStringFound isn't really *used*, it's just obtained from the recordset, since you had
objCommand.CommandText = "<LDAP://myldapserver/ou=forrest/o=domain>; (cn=" & strUserToPurge & "); ADsPath,testAttribute;subtree"      

so that means the recordset would hold two values, being ADsPath and testAttribute

userStringFound just obtains the value of the attribute called testAttribute for the user.

I was just trying to illustrate that's one way of retrieving attributes.  The part that would be best to get working is the bind to the user, and the objUser.Get calls to retrieve any values you needed.  When you see
Binding to <LDAPPATH>

does that look correct?

I'm amazed at how little examples I can find on scripting Novell or eDirectory....

A side question, have you used something like Softerra LDAP Browser to connect to and read your Novell directory?  Can you see the PSVA0 attribute?

Rob.
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37034567
Can you use this to echo the display name?
    ' Bind to the object
    WScript.Echo "Binding to " & strADsPath
    Set objUser = GetObject(strADsPath)
    WScript.Echo "Retrieving displayName attribute..."
    strDisplayName = objUser.Get("displayName")
    WScript.Echo "displayName value is " & strDisplayName

Open in new window


Rob.
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37035063
I found some hopefully useful code that will help us identify the properties of the user that are available (as long as we can bind to it).

Regards,

Rob.
While Not objRecordset.EOF
	' Retreive the values from the recordset
	strADsPath = objRecordSet.Fields("adsPath")
    userStringFound = objRecordSet.Fields("testAttribute")
    
    ' Bind to the object
    WScript.Echo "Binding to " & strADsPath
	Set objUser = GetObject(strADsPath)
	Set objClass = GetObject(objUser.Schema)
	strMProps = "Mandatory Properties:"
	For Each strPropName In objClass.MandatoryProperties
		strMProps = strMProps & VbCrLf & strPropName
	Next
	strOProps = "Optional Properties:"
	For Each strPropName In objClass.OptionalProperties
		strOProps = strOProps & VbCRLf & strPropName
	Next
	WScript.Echo strMProps & VbCrLf & VbCrLf & strOProps    

	objRecordset.MoveNext
Wend

Open in new window

0
 

Author Comment

by:JAaron Anderson
ID: 37040906

strUserToPurge = InputBox("Type target ID: ", "msg popup title", "")

Set objUser = GetObject("<LDAP://myserver/o=domain>; (cn=" & strUserToPurge & ");ADsPath;subtree")
objUser.GetInfo

strADsPath = objUser.Fields("ADsPath")
' Bind to the object
    WScript.Echo "Binding to " & strADsPath
    Set objUser = GetObject(strADsPath)
    WScript.Echo "Retrieving displayName attribute..."
    strDisplayName = objUser.Get("displayName")
    WScript.Echo "displayName value is " & strDisplayName




All returns null...
0
 

Author Comment

by:JAaron Anderson
ID: 37041140
I have givenName

that worked... for post ID:37034567




0
 

Author Comment

by:JAaron Anderson
ID: 37041219
see the attached image for the error on line

For Each strPropName In objClass.MandatoryProperties


notworking.jpg
0
 

Author Comment

by:JAaron Anderson
ID: 37041302
Guessing the "not a collection" error is because we are trying to pull objClass.MandatoryProperties keys that either we cant BIND to or dont have values, so our script tries to enumerate an non-existing array (collection) ????

.. jeesh all I wanna do is delete and eDirectory attribute. :D
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37042860
Hmmm, things are different in the Novell world :-(

Anyway, if this worked
    strGivenName = objUser.Get("givenName")
    WScript.Echo "givenName value is " & strGivenName

then good!  That at least means we have bound to the user object correctly.  Now, did you mention whether you had tried Softerra LDAP Browser to see the properties available to a user?  Have a look through that to see what properties you can retrieve with the above method.

Anyway, so now we know we have an existing attribute, let's try and delete the givenName.

Add this:
objUser.Delete "givenName"

Or this:
objUser.Put("givenName", "")
objUser.SetInfo

Or this:
objUser.PutEx 1, "givenName", 0
objUser.SetInfo

Rob.
0
 

Author Comment

by:JAaron Anderson
ID: 37044657

objUser.Delete "givenName"    ' returns error Wrong number of arguments or invalid property assignment:

objUser.Put("givenName", "") ' Cannout use parenthesis when calling a Sub
so I tried

objUser.Put "givenName", ""  ' The specified directory service attribute or value does not exist
' I just went and verified it IS in there as a single valued String type argument of the 'User' Class


objUser.PutEx 1, "givenName", 0  
objUser.SetInfo '  ' returns The specified directory service attribute or value does not exist


I made sure my user does have delete permissions checked in edirectory... not sure whats next Ill begin studying this error:
specified directory service attribute or value does not exist

0
 

Author Comment

by:JAaron Anderson
ID: 37044818
following this doc http://support.novell.com/techcenter/articles/ann20021101.html
I verified in consoleone my BIND user account is associated as a
" Supervisor  " which grants all access privileges. so thats good we just verified that now we need to go see if delete is enabled
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37061956
Well, I really can't find anything relating to scripting Novell, so the next best thing I can find is this:
http://support.novell.com/techcenter/articles/ana20001002.html

which seems to have command line programs for modifying things.

It looks like you may need to pass the DN of an object to the command line to work on specific users, so you could use the script you have so far, to search for the DN (which it does), then just add that to a command to run with the Run method of the WScript.Shell object.

See if you can make sense of those commands and get one to work on the command line the way you want, and I could help you script the command.

Regards,

Rob.
0
 

Author Comment

by:JAaron Anderson
ID: 37140439
Ill try passing the DN in the statement of the delete instruction see if that makes a difference... thx

I cant pursue the Import Convert option since Im not eDirectory 8.5 :(
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37168864
Hi, well, something tells me I'm going to run out of ideas now.  I did, however, just find this:
http://hiredavidbank.com/eDirPerl.html

which uses Perl to script against eDirectory.  I don't know Perl, so I can't help you there.

Looking at it though, since I can't translate Perl very well either, there's a very small change that something like this might work.....

    Set objUser = GetObject(strADsPath)
    WScript.Echo "Retrieving displayName attribute..."
    'strPSVA0 = objUser.GetFieldValue("Title")
    strPSVA0 = objUser.Get("PSVA0")
    If IsNull(strPSVA0) Or IsEmpty(strPSVA0) Then
       objUser.SetFieldValue("PSVA0", Null)
    Else
       objUser.SetFieldValue("Title", Null, strPSVA0)
    End If

Open in new window


There's a chance you may need to swap the commenting on these two line:
    'strPSVA0 = objUser.GetFieldValue("Title")
    strPSVA0 = objUser.Get("PSVA0")


I really don't know if that will work. If it doesn't, I recommend that you post a new question in the Novell / Netware and Perl zones.

Regards,

Rob.
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37168870
Oops, change:
       objUser.SetFieldValue("Title", Null, strPSVA0)

to
       objUser.SetFieldValue("PSVA0", Null, strPSVA0)

Rob.
0
 
LVL 65

Assisted Solution

by:RobSampson
RobSampson earned 2000 total points
ID: 37168887
I think I just found a reference here:
http://webdev.boras.se/webdev/Docs/nsc3_enu/nsc3_enu.pdf

So try this:
    Set objUser = GetObject(strADsPath)
    WScript.Echo "Retrieving displayName attribute..."
    'strPSVA0 = objUser.GetFieldValue("Title")
    strPSVA0 = objUser.Get("PSVA0")
    If IsNull(strPSVA0) Or IsEmpty(strPSVA0) Then
       objUser.SetFieldValue("PSVA0", Null)
    Else
       objUser.SetFieldValue("PSVA0", Null, strPSVA0)
    End If
    objUser.Update

Open in new window


There seems to be some ActiveX object called UCX:NWDIR

As a test, if you run this code in it's own VBScript:
Set objNWDir = CreateObject("UCX:NWDIR")

and don't get any errors, I think we'll be better off using that control.  If you do have an error, then somehow you will need to get that control, but I can't find out how to get it.

Regards,

Rob.
0
 

Author Comment

by:JAaron Anderson
ID: 37177655
>>Set objNWDir = CreateObject("UCX:NWDIR")
I get error ActiveX component can't create object UCX:NWDIR
0
 
LVL 65

Accepted Solution

by:
RobSampson earned 2000 total points
ID: 37179777
Hmm, what about the GetFieldValue and SetFieldValue methods?

As far as I can tell, you might need to install the Novell NDK to have the UCX components available.

Rob.
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

We live in a world of interfaces like the one in the title picture. VBA also allows to use interfaces which offers a lot of possibilities. This article describes how to use interfaces in VBA and how to work around their bugs.
Active Directory can easily get cluttered with unused service, user and computer accounts. In this article, I will show you the way I like to implement ADCleanup..
Are you ready to implement Active Directory best practices without reading 300+ pages? You're in luck. In this webinar hosted by Skyport Systems, you gain insight into Microsoft's latest comprehensive guide, with tips on the best and easiest way…
Screencast - Getting to Know the Pipeline

873 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question