locked
VB.NET - Update AD attributes -Need Help RRS feed

  • Question

  • I am getting "Server is Unwilling to process the request."
    I need to update the Email ID field for users in AD using VB.net, I am able to search the users in AD all okay, not able to update any field, however.

    Even tried to update other fields "homePhone", that too fails with same error, please help.

    '' Hers my code..

    Dim ADEntry As New DirectoryServices.DirectoryEntry("<Domain Name>")

    Dim ADSearch As New System.DirectoryServices.DirectorySearcher(ADEntry) Dim Result As String ADSearch.Filter = ("(samAccountName=" & UserName & ")") ADSearch.SearchScope = SearchScope.Subtree Dim MachineFoundAD As SearchResult = ADSearch.FindOne() If Not IsNothing(MachineFoundAD) Then Dim mailID As String Dim attrUpdate As New System.DirectoryServices.DirectoryEntry(MachineFoundAD.Path) Result = MachineFoundAD.GetDirectoryEntry().Properties.Item("cn").Value MsgBox("FOUND USER " & Result) ' Getting Search Results fine attrUpdate.Properties("mail").Value = "somethng@test.com" attrUpdate.CommitChanges() End If End Sub


    I am getting "Server is Unwilling to process the request."
    I need to update the Email ID field for users in AD using VB.net, I am able to search the users in AD all okay, not able to update any field, however.

    Even tried to update other fields "homePhone", that too fails with same error, please help.



    • Edited by kush86g Saturday, July 9, 2016 1:33 PM
    Saturday, July 9, 2016 1:30 PM

Answers

  • This is not a VB.Net forum so you will want to post in either the VB.Net developers forum or the Directory developers forum for help with using AD with VB.Net

    Here is a more usual approach to your code as it eliminates redundant code and uses the defaults for the AD types t make the code cleaner ad less prone to failure.

    	Try
    		Dim Filter As String = "(samAccountName=" & UserName & ")"
    		Dim searcher As New DirectorySearcher(filter)
    		Dim result As SearchResult = searcher.FindOne()
    	    If Not result Is Nothing Then
    	        MsgBox("FOUND USER  " & reult.Properties.Item("cn") )
    	        Dim dirEntry As  DirectoryEntry = result.GetDirectoryEntry()
    	        Dim name as String = dirEntry.Properties.Item("cn").Value
    	        dirEntry.Properties("mail").Value = "somethng@test.com"
    	        dirEntry.CommitChanges()
    	    End If
        Catch
        	' handle exceptions
        End Try
        
    End Sub


    The default for a search is the current domain.  We do not need to express that.

    If we want to search a specific root then we can do this:

    Dim Filter As String = "(&(objectclass=user)(objectcategory=person))"
    Dim properties As String() = {}
    Dim searcher As New DirectorySearcher(filter,properties)
    searcher.SearchRoot = New DirectoryEntry(LDAP://OU=Some Ou,CN=MyDom,CN=com)

    Of course to retrieve a single user by samname we don't need to do this.  We would also only null the properties if we were going to use GetDirectoryEntry().  For pure reporting we would ask for all properties we need and use the search object for the reporting.


    \_(ツ)_/







    • Marked as answer by kush86g Wednesday, July 13, 2016 8:00 AM
    • Edited by jrv Wednesday, July 13, 2016 10:25 AM Fixed root builder
    Saturday, July 9, 2016 3:42 PM
  • Thanks jrv for help.

    I found the issue was with my connection strings   Dim ADEntry As New DirectoryServices.DirectoryEntry("<Domain Name>")

    my "Domain Name" must contain the LDAP , however, I was using this

    Dim ADEntry As New DirectoryServices.DirectoryEntry("GC://DC=<DC Name>,DC=com")

    Changing it to Dim ADEntry As New DirectoryServices.DirectoryEntry("LDAP://DC=<DC Name>,DC=com")

    Worked for me.

    Reason I couldn't identify this earlier, as my search results were fine no error there.

    putting LDAP Solved the problem.

    • Marked as answer by kush86g Wednesday, July 13, 2016 7:59 AM
    Wednesday, July 13, 2016 7:59 AM

All replies

  • Replace MachineFoundAD.Path with MachineFoundAD.AdsPath.

    Richard Mueller - MVP Enterprise Mobility (Identity and Access)

    Saturday, July 9, 2016 2:51 PM
  • This is not a VB.Net forum so you will want to post in either the VB.Net developers forum or the Directory developers forum for help with using AD with VB.Net

    Here is a more usual approach to your code as it eliminates redundant code and uses the defaults for the AD types t make the code cleaner ad less prone to failure.

    	Try
    		Dim Filter As String = "(samAccountName=" & UserName & ")"
    		Dim searcher As New DirectorySearcher(filter)
    		Dim result As SearchResult = searcher.FindOne()
    	    If Not result Is Nothing Then
    	        MsgBox("FOUND USER  " & reult.Properties.Item("cn") )
    	        Dim dirEntry As  DirectoryEntry = result.GetDirectoryEntry()
    	        Dim name as String = dirEntry.Properties.Item("cn").Value
    	        dirEntry.Properties("mail").Value = "somethng@test.com"
    	        dirEntry.CommitChanges()
    	    End If
        Catch
        	' handle exceptions
        End Try
        
    End Sub


    The default for a search is the current domain.  We do not need to express that.

    If we want to search a specific root then we can do this:

    Dim Filter As String = "(&(objectclass=user)(objectcategory=person))"
    Dim properties As String() = {}
    Dim searcher As New DirectorySearcher(filter,properties)
    searcher.SearchRoot = New DirectoryEntry(LDAP://OU=Some Ou,CN=MyDom,CN=com)

    Of course to retrieve a single user by samname we don't need to do this.  We would also only null the properties if we were going to use GetDirectoryEntry().  For pure reporting we would ask for all properties we need and use the search object for the reporting.


    \_(ツ)_/







    • Marked as answer by kush86g Wednesday, July 13, 2016 8:00 AM
    • Edited by jrv Wednesday, July 13, 2016 10:25 AM Fixed root builder
    Saturday, July 9, 2016 3:42 PM
  • I finally remembered my VB.Net. The correct test for Nothing is "var Is Nothing" and "Not var Is Nothing".


    \_(ツ)_/

    Saturday, July 9, 2016 3:57 PM
  • As an exercise and to refresh my stale VB.Net  - I use C# exclusively except when I have to fix code - I decided to build a working example. This can be run directly at a PowerShell prompt or the VB code can be extracted and compiled in VS.

    $code = @'
    Imports System
    Imports System.DirectoryServices
    
    Public Class ADTest
    	Sub Main(userName As String)
    		Try
    			Dim Filter As String = "(samAccountName=" + UserName + ")"
    			Dim searcher As New DirectorySearcher(filter)
    			Dim result As SearchResult = searcher.FindOne()
       			If result Is Nothing Then
         Console.WriteLine("User Not " + userName)
    Else
    Console.WriteLine("FOUND USER " + result.Properties.Item("cn")(0)) Dim dirEntry As DirectoryEntry = result.GetDirectoryEntry() Dim name as String = dirEntry.Properties.Item("cn").Value Console.WriteLine(" CN:" + result.Properties.Item("cn")(0)) 'dirEntry.Properties("mail").Value = "somethng@test.com" dirEntry.CommitChanges() End If Catch e As Exception ' handle exceptiions Throw e End Try End Sub End Class '@ Add-Type $code -Language VisualBasic -ReferencedAssemblies System.DirectoryServices $adtest = New-Object ADTest $adtest.Main('jsmith')
    Use a samname that exists and it will find the account.


    \_(ツ)_/




    • Edited by jrv Saturday, July 9, 2016 4:25 PM
    Saturday, July 9, 2016 4:21 PM
  • Replace MachineFoundAD.Path with MachineFoundAD.AdsPath.

    Richard Mueller - MVP Enterprise Mobility (Identity and Access)

    Richard. MachineFoundAD is a "SearchResult" which uses "Path".  "Path" and "Properties" are the only properties of the object.

    https://msdn.microsoft.com/en-us/library/system.directoryservices.searchresult%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

    In VBScript we used to use "aDSPath" which is the formal name of the attribute with LDAP COM interface.


    \_(ツ)_/

    Saturday, July 9, 2016 4:48 PM
  • I am getting "Server is Unwilling to process the request."
    I need to update the Email ID field for users in AD using VB.net, I am able to search the users in AD all okay, not able to update any field, however.

    Even tried to update other fields "homePhone", that too fails with same error, please help.

    '' Hers my code..

    Dim ADEntry As New DirectoryServices.DirectoryEntry("<Domain Name>")

    Dim ADSearch As New System.DirectoryServices.DirectorySearcher(ADEntry) Dim Result As String ADSearch.Filter = ("(samAccountName=" & UserName & ")") ADSearch.SearchScope = SearchScope.Subtree Dim MachineFoundAD As SearchResult = ADSearch.FindOne() If Not IsNothing(MachineFoundAD) Then Dim mailID As String Dim attrUpdate As New System.DirectoryServices.DirectoryEntry(MachineFoundAD.Path) Result = MachineFoundAD.GetDirectoryEntry().Properties.Item("cn").Value MsgBox("FOUND USER " & Result) ' Getting Search Results fine attrUpdate.Properties("mail").Value = "somethng@test.com" attrUpdate.CommitChanges() End If End Sub


    I am getting "Server is Unwilling to process the request."
    I need to update the Email ID field for users in AD using VB.net, I am able to search the users in AD all okay, not able to update any field, however.

    Even tried to update other fields "homePhone", that too fails with same error, please help.



    When you post a question post the complete error message with line numbers.  If you post partial code find and highlight the line causing the error.  There are at least three lines that can cause that error so there is no way to know what the issue is.


    \_(ツ)_/

    Saturday, July 9, 2016 4:50 PM
  • You are right jrv, I was looking at PowerShell code that uses DirectorySearcher, where I retrieve AdsPath from the Properties collection. I also do that in VB. There is no Path in the Properties collection, but the ResultsSet does have the Path property. My mistake.

    Richard Mueller - MVP Enterprise Mobility (Identity and Access)

    Saturday, July 9, 2016 5:16 PM
  • You are right jrv, I was looking at PowerShell code that uses DirectorySearcher, where I retrieve AdsPath from the Properties collection. I also do that in VB. There is no Path in the Properties collection, but the ResultsSet does have the Path property. My mistake.

    Richard Mueller - MVP Enterprise Mobility (Identity and Access)


    Yeah.  I always get that confused.  Too many name changes in Microsoft products.  Makes me crazy.

    \_(ツ)_/

    Saturday, July 9, 2016 5:27 PM
  • Thanks jrv for help.

    I found the issue was with my connection strings   Dim ADEntry As New DirectoryServices.DirectoryEntry("<Domain Name>")

    my "Domain Name" must contain the LDAP , however, I was using this

    Dim ADEntry As New DirectoryServices.DirectoryEntry("GC://DC=<DC Name>,DC=com")

    Changing it to Dim ADEntry As New DirectoryServices.DirectoryEntry("LDAP://DC=<DC Name>,DC=com")

    Worked for me.

    Reason I couldn't identify this earlier, as my search results were fine no error there.

    putting LDAP Solved the problem.

    • Marked as answer by kush86g Wednesday, July 13, 2016 7:59 AM
    Wednesday, July 13, 2016 7:59 AM
  • There was no way to know that from your post. One point I was trying to make.  You don't need to specify a search root when searching the whole domain.  The search is domain wide by default.

    You posted:

    Dim ADEntry As New DirectoryServices.DirectoryEntry("<Domain Name>")

    Not needed for a full search:

    The method I posted is more efficient and requires fewer trips to AD to gather the entries.  Adding the "properties" list also reduces overhead.

    Yes - a DirectoryEntry requires the full path of the object and not the distinguished name.


    \_(ツ)_/

    Wednesday, July 13, 2016 10:18 AM
  • Here is how to null the properties and add a su b OU search.

    $code = @'
    Imports System
    Imports System.DirectoryServices
    
    Public Class ADTest
    	Sub Main(userName As String)
    		Try
    			Dim filter As String = "(samAccountName=" + UserName + ")"
    			Dim searcher As New DirectorySearcher(filter,{}) 'pass empty properties
    			searcher.SearchRoot = New DirectoryEntry("LDAP://OU=TestOU,DC=testnet,DC=com")
    			Dim result As SearchResult = searcher.FindOne()
       			If result Is Nothing Then
        				Console.WriteLine("User Not " + userName)
    			Else
    				Console.WriteLine("FOUND USER  " + result.Properties.Item("cn")(0))
    				Dim dirEntry As  DirectoryEntry = result.GetDirectoryEntry()
    				Dim name as String = dirEntry.Properties.Item("cn").Value
    				Console.WriteLine("   CN:" + result.Properties.Item("cn")(0))
    				'dirEntry.Properties("mail").Value = "somethng@test.com"
    				dirEntry.CommitChanges()
    			End If
    		Catch e As Exception
    			' handle exceptiions
    			Throw e
    		End Try
    
    	End Sub
    End Class
    '@
    
    
    Add-Type $code -Language VisualBasic -ReferencedAssemblies System.DirectoryServices
    $adtest = New-Object ADTest
    $adtest.Main('jsmith')
    It is in a PowerShell test harness for convenience.


    \_(ツ)_/

    Wednesday, July 13, 2016 10:23 AM