Using System.DirectoryServices.Protocols from Powershell

This simple Powershell module demonstrates how to use robust and powerfull objects from System.DirectoryServices.Protocols (S.DS.P) from Powershell.

S.DS.P.zip
 
 
 
 
 
4.4 Star
(5)
9,550 times
Add to favorites
Active Directory
5/4/2019
E-mail Twitter del.icio.us Digg Facebook
Sign in to ask a question


  • find-ldapobject returning empty results
    3 Posts | Last post January 12, 2017
    • I have a rather complex ldap setup that includes certificates and authentication.  I have been able to get the connection to successfully bind and I can send requests.  So I used the find-ldapobject commandlet to return the results
      
      However, when I return the results using the line: 
      $results = find-ldapobject -ldapconnection $LDAPconnection -searchfilter "(ou=arch,*)" -searchbase "ou=people,dc=umich,dc=edu" -pagesize 0 -PropertiesToLoad @("cn","mobile") | select-object *
      
      I get a bunch of blank lines.  It seems to be working because when I limit the query down to 1 result, it only returns 1 blank line.  When it is set to the ou=arch,*  it returns about the number of blank lines as people in the ou.
      
      I had to set the pagesizse to 0 because when I ran it with the pagesize of 100, it said 0
      Exception calling "SendRequest" with "2" argument(s): "The server does not support the control. The control is critical."  So 0 (non-paged) seemed to be the only option.
      
      I know cn and mobile are valid properties because I can see them when I connect to the ldap directory with Windows' LDAPAdmin.exe
    • Hi Jeff,
      hard to tell what's wrong in your case - generally it is expected to work against any LDAP server (I tested against AD and AD LDS, and I have successful reports from non-MS LDAP servers usage as well)
      
      If you give me remote access to your lab, I will give it some time to debug to see what's wrong there.
      
      Regarding not supported controls: yes, different LDAP servers support different controls, so this error is expected for servers that do not support this control
      
      Regards,
      Jiri
    • As a feature request, the code should interrogate the supported controls for the specified LDAP server and gracefully degrade if some options are not supported. The current implementation seems mostly tested against AD which supports several controls (and authentication mechanisms) that aren't widely used elsewhere.
  • Converting type of results (objectSID, msRTCSIP-originatorSID...)
    2 Posts | Last post December 05, 2016
    • Hi,
      Thanks for this great script, it helps a lot.
      Just one question. When I do this request :
      
      Find-LdapObject -searchFilter:"(displayname=TEST*)" -searchBase:"DC=xxxx,DC=xxxx,DC=xx" -LdapServer:"xxxxx" -PageSize 1000 -propertiesToLoad:@("objectsid")
      
      It returns that :
      
      objectsid                               distinguishedName
      ---------                               -----------------
      ☺♣     ♣§   ??~/???L?;+☻?☻             CN=XXXXXXX,OU=XXXX,DC=XXXXX,DC=XXXX,...
      ☺♣     ♣§   ??~/???L?;+►?☻             CN=YYYYYYY,OU=YYYY,DC=YYYYY,DC=YYYY,...
      ☺♣     ♣§   ??~/???L?;+??♦             CN=ZZZZZZZ,OU=ZZZZ,DC=ZZZZZ,DC=ZZZZ,...
      
      How to translate objectSID to something readable (like 00 1F 2C 00 ... or S-1-5-21-14544...) ?
      
      Regards
      AT
    • Hello AT,
      try like this:
      Find-LdapObject -searchFilter "(&(objectClass=user)(objectSid=*))" -searchBase "dc=xx,dc=xy,dc=yz" -PropertiesToLoad @("objectSid") -BinaryProperties @("objectSid") | %{$_.objectSid=new-object System.Security.Principal.SecurityIdentifier($_.objectSid,0);$_}
      
      Remember:
      - SID is binary value, so you need to instruct cmdlet to treat it as binary - do it by passing the objectSid property name in both PropertiesToLoad and BinaryProperties parameter
      - to get real SID, you need to transform binary data fetched to SID - I just do it by constructing .NET SecurityIdentifier object using the binary data retrieved from AD
      
      Hope this helps,
      Jiri
  • Not sure how to build the credential
    3 Posts | Last post May 27, 2016
    • Hi Jiri,
      
      Thanks for this script, it seems to work great against the domain my host machine lives on.  
      
      Unfortunately when I try to target a specific LDAP server outside my domain, I'm having issues getting it to accept a -Credential.  I tried using Get-Credential, but it appears the module is looking for a System.String value rather than a System.Management.Automation.PSCredential.
      
      Can you tell me what format to put my username/password in for the -Credential parameter to digest it properly?
      
      Thanks,
      
      Justen
    • Hi Justen,
      actually, type of Credential parametr is [System.Net.NetworkCredential]. You build it with one of constructors available, as described here: https://msdn.microsoft.com/en-us/library/system.net.networkcredential(v=vs.110).aspx
      
      Such as $cred=new-object System.Net.NetworkCredential("MyUserName", "myPassword", "myDomain")
      
      Hope this helps,
      Jiri
    • That was exactly it!  Thanks Jiri, hopefully my question wasn't too silly.
  • Getting error while import on 2008R2 DC
    2 Posts | Last post May 24, 2016
    • Hello Jiri,
      
      When i try to import this module in 2008R2 DC i am getting the below error message in powershell
      
      PS C:\> import-module .\S.DS.P.psd1
      Import-Module : The 'C:\S.DS.P.psd1' module cannot be imported because its manifest contains one or more members that a
      re not valid. The valid manifest members are ('ModuleToProcess', 'NestedModules', 'GUID', 'Author', 'CompanyName', 'Cop
      yright', 'ModuleVersion', 'Description', 'PowerShellVersion', 'PowerShellHostName', 'PowerShellHostVersion', 'CLRVersio
      n', 'DotNetFrameworkVersion', 'ProcessorArchitecture', 'RequiredModules', 'TypesToProcess', 'FormatsToProcess', 'Script
      sToProcess', 'PrivateData', 'RequiredAssemblies', 'ModuleList', 'FileList', 'FunctionsToExport', 'VariablesToExport', '
      AliasesToExport', 'CmdletsToExport'). Remove the members that are not valid ('RootModule'), then try to import the modu
      le again.
      At line:1 char:14
      + import-module <<<<  .\S.DS.P.psd1
          + CategoryInfo          : InvalidData: (C:\S.DS.P.psd1:String) [Import-Module], InvalidOperationException
          + FullyQualifiedErrorId : Modules_InvalidManifestMember,Microsoft.PowerShell.Commands.ImportModuleCommand
      
      
      Could you please let me know why ?
      
      
    • Hi Meera,
      most likely your DC is still using older version of PowerShell. Just replace 'RootModule' keyword by 'ModuleToProcess' keyword and give it a try
      PowerShell team replaced ModuleToProcess by RootModule keyword in PowerShell 3.0 and newer (ModuleToProcess is still there for backward compatibility)
      
      And yes, you're right - I've forgotten to update required PS Host version accordingly. Will upload updated version soon)
      
      Hope this helps,
      Jiri
      
  • Cannot connect
    4 Posts | Last post December 02, 2015
    • Hi, first sorry for asking a noobish question, but I can't make this cmdlet to work for me. I have an LDAP, that allows anonymous binds, and I cannot connect to it with the following:
      Find-LdapObject -LdapServer ldapserver01 -searchBase "ou=Users,dc=domain,dc=com" -searchFilter "(uid=myusername)"
      It's the same if I try to auth as user, adding username and password.
      
      The error I always recieve is Exception calling "SendRequest" with "2" argument(s): "An unknown error occurred."
      At C:\Windows\system32\WindowsPowerShell\v1.0\Modules\S.DS.P\S.DS.P.psm1:245 char:17
      +                 $rsp = $LdapConnection.SendRequest($rq, (new-object System.Times ...
      + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
          + FullyQualifiedErrorId : DirectoryOperationException
      
      Which I see is realted to psm1 of the module, but I don't know what's wrong. I get the same error when I try to connect with Basic auth.
      
      Thanks in advance!
    • Hello,
      hard to tell what may be wrong with the connection. Exception thrown from SendRequest() contains error passed by underlying LDAP provider, and is not helpful in this case.
      I guess your LDAP server is not a MS LDAP (AD/ADAM)? I did not test with 3rd party LDAP servers; I have feedback from users of this module it works for them with 3rd party.
      In case it's MS LDAP, please share your configursation details, I will look for repro
      
      Thanks,
      Jiri
    • No, it's not, it's openLDAP, but it allows anonymous cotions and I get results just running ldapsearch on Linux (#ldapsearch -x -h ldapserver01 -b "dc=domain,dc=com". Also, Windows tool call LDAPSearch (GUI app) works fine as well, but my idea was to get data from PowerShell and then use EPPlus to format it in Excel. 
      
      Do you have any references besides than comments here of users using it with OpenLDAP? Really don't want to switch to another solution, this one seems just fine from the start :)
      
      Thanks,
      Petar
    • Never tested with OpenLDAP; will look into it when time permits. If you have an interface to bind to, I will test against
      
      Regards,
      Jiri
  • Looking up every object it finds?
    2 Posts | Last post October 23, 2015
    • So I have to ask, I can run a single LDAP query using same directoryservices dirsearcher etc. and before I findall simply add all the properties to load. If I run it with 3 properties, it's scrolling so fast you can't read it yet with your module looking at the code I had to ask why on earth such good structure yet you perform the initial search using standard passed LDAP filter (ie. (&(objectClass=user)(objectCategory=Person)) ) yet then your code loops through the results and THEN performs ANOTHER query on every DN to get whatever properties.  Why?
      
      Add the properties make it a single query with 3 or 30 however many, execute it once get the 9000 results in an array or hash table.  Now, you perform 9001 queries 1 to get the list and 9000 lookups and it's really slow.
      
      Thoughts/comments?  I love the function I think it's cleanly written but I can't for the life of me figure out why the mult calls and would love to hear your thought process behind it maybe I'm just missing something!
    • Hi Collin,
      thanks for thinking on the article and apologies for answering that late - notification about your post got lost among other emails.
      Reasons why I developed script the way it is are:
      - multivalued propertis: search that returns multiple objects is subject of MaxValRange LDAP Query policy, so multival props with large amount of vals may never return all the pop unless loaded via ranged property retrieval as demostrated in this sample
      - computed props: they aren't returned unless baseDN is object itself
      
      So the script offers slower performance, but at the same time guaranteed results and unified behavior.
      
      BTW performance is not that bad anyway (on fast network) - see measurement Steve Renard recently performed: http://powershell.org/wp/2015/03/06/the-fastest-powershell-2-count-all-users-in-active-directory-domain/
      
      Hope this will help,
      Jiri
  • Comment and Feature Request
    1 Posts | Last post October 20, 2015
    • Great script.  I've added a few items to make it work in my mixed AD/eDirectory environment such as the "Determine if using AD" code below.  I needed this because eDirectory had issue when using "range=" as part of the attribute name during a search -- nothing was returned.  
      
      I'd like to see an Add and Delete Object Function.  
      Keep up the good work.
      ...Nick
      
      # Determine if using AD
      $ADInUse = $False
      $rq=New-Object System.DirectoryServices.Protocols.SearchRequest
      $rq.Filter = "(objectClass=*)"
      $rq.Scope = [System.DirectoryServices.Protocols.SearchScope]::Base
      $rq.Attributes.Add("highestCommittedUSN") | Out-Null
      $rsp = $LDAPConnection.SendRequest($rq, (New-Object System.Timespan(0,0,$TimeoutSeconds))) -as [System.DirectoryServices.Protocols.SearchResponse];		
      If ([int]$rsp.Entries[0].Attributes.count -gt 0) { $ADInUse = $True;Write-Verbose "Using Active Directory" -Verbose}
  • How do you load this?
    2 Posts | Last post September 02, 2014
    • I apologize for not knowing this, but I'm NOT a programmer. However, this is exactly what I'm looking for. Something that can simply connect over TCP 389 regardless of it's Active Directory, OpenLDAP, eDirectory, iPlanet, etc. The thing is... I'm not sure if I just open a powershell console, import-module of this or what? It isn't working as it should so obviously I'm doing something wrong. Could you offer a little more guidance on how to get this working?
      
      Thanks,
      
      Rodney
    • Hello,
      usage is pretty simple:
      - you just create folder %Systemroot%\system32\WindowsPowershell\v1.0\Modules\S.DS.P
      - download the file from here
      - extract both files in downloaded archive into newly created folder
      - open PowerShell window
      - run cmdlet Import-Module S.DS.P
      - and you're ready (you may need to set PS execution policy to something like RemoteSigned so as the module could load
      
      You can then use Find-LdapObject cmdlet to connect to any LDAP server and fetch data from it - see examples in the article
      
      Do you receive any errors or why it does not work for you?
      
      Hope this helps,
      Jiri
  • Working?
    2 Posts | Last post September 11, 2012
    • I'm trying to get this code to run but have not hade any luck. Has anyone else got this code to work?
      
      /j
    • Hello,I believe the sample is working. Can you describe in more detail what errors you're getting or what are you doing, so I could repro?
      
      Regards,
      Jiri
11 - 19 of 19 Items