none
Get OAB OfflineABSchedule value RRS feed

  • Question

  • Dear All,

    I would like to ask this question. How to get get OAB offlineABSchedule value by LDAP in powershell? actually, I have been implementation this feature in C# code. Now, I don't know how to implement  in powershell.

    Any help is appreciated!

    Monday, January 26, 2015 10:08 AM

Answers

  • Hi Simon,

    you can use the ExchangeShell's Get-OfflineAddressBook cmdlet to retrieve OABs. Those have a schedule property. Getting a Schedule list is a bit more problematic (just trying to list them throws a casting error), but $Oab.Schedule.SyncRoot will get you to your target.

    You can also use the Get-ADObject -Identity [dn] -Properties "offLineABSchedule" call, however you will need to interprete the output (not fun).

    Cheers,
    Fred

    Ps.: If you already know how to do this in C# ... why not use the same technique in Powershell?


    There's no place like 127.0.0.1


    • Edited by FWN Monday, January 26, 2015 4:32 PM
    • Marked as answer by lxd_DD Wednesday, January 28, 2015 1:10 AM
    Monday, January 26, 2015 4:31 PM
  • Hi Simon,

    glad to have been of assistance.

    The first thing you need to understand is the structure of Active Directory. For all practical purposes, it consists of three separate segments:

    • "Regular Space"
    • Configuration Space
    • Schema Space

    In an Active Directory Forest, Configuration and Schema are replicated to all Domains in the Forest, while the regular space is domain specific.

    Schema contains the information on how the AD is structured and is of no further interest to us. Configuration however contains the information of interest to all domains in the Forest, including most of the Exchange Information. So you need to search in the Configuration Space.

    To set the search root to Configuration, you can do this:

    # Create a new entry for default space
    $objDomain = New-Object System.DirectoryServices.DirectoryEntry
    
    # Get the DN of your domain
    [string]$string = $objDomain.distinguishedName
    
    # Prepend the configuration entry and LDAP protocol
    $string = "LDAP://CN=Configuration," + $string
    
    # Initialize new DirectoryEntry that points at configuration
    $objDomain = New-Object System.DirectoryServices.DirectoryEntry($string)

    Once you are searching in the correct space, you can search for OABs :)

    Cheers,
    Fred


    There's no place like 127.0.0.1

    • Marked as answer by lxd_DD Thursday, January 29, 2015 9:23 AM
    Wednesday, January 28, 2015 8:19 AM
  • Here is the purist's method.

    $searcher=[adsisearcher]'(cn=Offline Address Lists)'
    $searcher.SearchRoot="LDAP://CN=Configuration,$(([adsi]'').distinguishedName)"
    $lists=$searcher.FindOne()
    $Searcher.Filter='objectClass=msExchOAB'
    $searcher.SearchRoot=$lists.Path
    $searcher.FindAll()
    
    


    ¯\_(ツ)_/¯

    • Marked as answer by lxd_DD Thursday, January 29, 2015 1:29 PM
    Thursday, January 29, 2015 10:26 AM

All replies

  • Hi Simon,

    you can use the ExchangeShell's Get-OfflineAddressBook cmdlet to retrieve OABs. Those have a schedule property. Getting a Schedule list is a bit more problematic (just trying to list them throws a casting error), but $Oab.Schedule.SyncRoot will get you to your target.

    You can also use the Get-ADObject -Identity [dn] -Properties "offLineABSchedule" call, however you will need to interprete the output (not fun).

    Cheers,
    Fred

    Ps.: If you already know how to do this in C# ... why not use the same technique in Powershell?


    There's no place like 127.0.0.1


    • Edited by FWN Monday, January 26, 2015 4:32 PM
    • Marked as answer by lxd_DD Wednesday, January 28, 2015 1:10 AM
    Monday, January 26, 2015 4:31 PM
  • thanks a lot for your reply. Indeed, It works fine by Get-OfflineAddressBook.

    Otherwise, I still want to know that search AD with Powshell by LDAP, As you said, use the same technique in Powershell to fix it. I also tried it, but I found some problems. Could you please help me check it ?

    The following is my code, I found that "$colResults.Count" is null(0), I don't know why, Any Idea ? Thanks!

     $MailboxServer = Get-MailboxServer -Identity $Env:COMPUTERNAME -ErrorAction SilentlyContinue
    	     $dc = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() 
    	     $cfgNC = "LDAP://" + $dc.Name + "/cn=Offline Address Lists,cn=Address Lists Container, " + $MailboxServer.ServerDistinguishedName
    		 #Connect to the configuration partition and search for the Exchange Server object
    		 $configConnection = New-Object System.DirectoryServices.DirectoryEntry ($cfgNC)
    		 $exchSearchString = "(&(objectClass=msExchExchangeServer)(name=*" + $Env:COMPUTERNAME + "*))"
    		 $configSearcher = New-Object System.DirectoryServices.DirectorySearcher($configConnection, $exchSearchString)
    		 $colProplist = "cn","offLineABSchedule","offLineABStyle"
             foreach ($i in $colPropList)
    		 {
    		    $configSearcher.PropertiesToLoad.Add($i)
    		 }
    	     $colResults = $configSearcher.FindAll()

    Tuesday, January 27, 2015 9:59 AM
  • Hi Simon,

    well, if you're searching for Exchange Servers, I recommend searching in a folder where they actually exist. Basically, you really want to change $cfgNC to point to the configuration section of your ActiveDirectory.

    Having done that you will get good results, however, you won't find the OAB as a property on the exchange server, as far as I can see.

    After using Get-OfflineAddressBook, you can read the distinguished name of the property to search for. That will have you looking at the correct target. (Btw, you can directly get all OABs by filtering for objectClass msExchOAB and searching in the configuration part of the AD)

    That's when you receive all those helpful bytes for your schedule, too :)

    Cheers,
    Fred


    There's no place like 127.0.0.1

    Tuesday, January 27, 2015 10:59 AM
  • Thanks Fred, maybe I should to continue understand what you said, because i'm new for Exchange Servers. But it might be useful for me that you mentioned objectClass msExchOAB point.

    Anyway, appreciated!

    Wednesday, January 28, 2015 1:43 AM
  • Hi Simon,

    glad to have been of assistance.

    The first thing you need to understand is the structure of Active Directory. For all practical purposes, it consists of three separate segments:

    • "Regular Space"
    • Configuration Space
    • Schema Space

    In an Active Directory Forest, Configuration and Schema are replicated to all Domains in the Forest, while the regular space is domain specific.

    Schema contains the information on how the AD is structured and is of no further interest to us. Configuration however contains the information of interest to all domains in the Forest, including most of the Exchange Information. So you need to search in the Configuration Space.

    To set the search root to Configuration, you can do this:

    # Create a new entry for default space
    $objDomain = New-Object System.DirectoryServices.DirectoryEntry
    
    # Get the DN of your domain
    [string]$string = $objDomain.distinguishedName
    
    # Prepend the configuration entry and LDAP protocol
    $string = "LDAP://CN=Configuration," + $string
    
    # Initialize new DirectoryEntry that points at configuration
    $objDomain = New-Object System.DirectoryServices.DirectoryEntry($string)

    Once you are searching in the correct space, you can search for OABs :)

    Cheers,
    Fred


    There's no place like 127.0.0.1

    • Marked as answer by lxd_DD Thursday, January 29, 2015 9:23 AM
    Wednesday, January 28, 2015 8:19 AM
  • The easiest way to get the default OAB is this:

    $searcher=[adsisearcher]'(&(cn=Default Offline Address Book)(objectclass=msExchOAB))'
    $searcher.SearchRoot="LDAP://CN=Configuration,$(([adsi]'').distinguishedName)"
    $oab=$searcher.FindOne()
    

    AD knows where it is and it has a fixed name (CN).  You can always get the domain with [adsi]''.

    Fast and works from any client system.


    ¯\_(ツ)_/¯

    • Proposed as answer by jrv Thursday, January 29, 2015 9:25 AM
    Wednesday, January 28, 2015 3:09 PM
  • Hi Fred,

    First, I'm very grateful to you for all of your help. Actually, It was really solved my problem. With your assistance, I know understand is the structure of AD and how to configuration root. Before, I always used incorrect path to access OABs, so ignorant.

    After, I need to keep studying! Thanks again!

    Best Regards,
    Simon
    Thursday, January 29, 2015 9:22 AM
  • It's really good way to get OAB, so easy! But I want to know what's difference between them. Which approach is used more frequently? Otherwise, If I want to access several OAB of folder(cn=Offline Address Book Lists objectclass=msExchContainer) , not only one item(default OAB), how to write with adsiearcher ? 

    How to loop this folder, get several item, like default OAB, MyBuildOAB...etc.

    Thursday, January 29, 2015 10:08 AM
  • This is one easy way assuming you don't have thousands of OABs.

    $searcher=[adsisearcher]'(&(objectclass=msExchOAB))'
    $searcher.SearchRoot="LDAP://CN=Configuration,$(([adsi]'').distinguishedName)"
    $searcher.FindAll() |?{$_.DistinguishedName -match 'Offline Address Lists'}
    


    ¯\_(ツ)_/¯

    Thursday, January 29, 2015 10:15 AM
  • Hi Simon,

    well, if you have multiple OABs, then the search should find all of them, so you can loop through them:

    $colResults = $configSearcher.FindAll()
    foreach ($OAB in $colResults)
    {
        # Do whatever you want to do with it
        # ...
    }

    This works just fine with a single OAB as with hundreds of them.

    Cheers,
    Fred


    There's no place like 127.0.0.1

    Thursday, January 29, 2015 10:17 AM
  • Here is the purist's method.

    $searcher=[adsisearcher]'(cn=Offline Address Lists)'
    $searcher.SearchRoot="LDAP://CN=Configuration,$(([adsi]'').distinguishedName)"
    $lists=$searcher.FindOne()
    $Searcher.Filter='objectClass=msExchOAB'
    $searcher.SearchRoot=$lists.Path
    $searcher.FindAll()
    
    


    ¯\_(ツ)_/¯

    • Marked as answer by lxd_DD Thursday, January 29, 2015 1:29 PM
    Thursday, January 29, 2015 10:26 AM
  • Hi Fred,

    This morning, I already have been implementation it by your way. I just don't know using adsisearcher to search. I think using adsisearcher is very easy, isn't it? But I still fix it by directoryentry in my work. So, Thanks!

    Thursday, January 29, 2015 12:51 PM
  • Nice! In chinese word is "赞一个!"  It works fine. I learned a new way. Thanks!
    Thursday, January 29, 2015 1:27 PM
  • This [adsisearcher]
    is the net type name for this:
    This [adsisearcher]
    is the net type name for this:
    System.DirectoryServices.DirectorySearcher

    Try this at a prompt

    [adsisearcher]

    then this

    [System.DirectoryServices.DirectorySearcher]

    You will see they are identical.

    All things like [string],[int],[object]  are called "type accelerators" and are built into PowerShell

    [adsi],[adsisearcher],[wmi],[wmiclass],[psobject],[pscustomobject]

    All and many more are what gives access to long names that are frequently used.

    [adsi]'' always retuns the current domain object.  It does the samme thing as GetCurrentDomain.

    You can use those but they are what we use in C# or VB.Net.  Even there we shorted using the codes memthids like "using" and "imports".  the type accelerators are the same thing.

    any adsisearcher automaticall defaults to the curent domain so you don't ever need too set that.  The default string constructor is the filter.

    This:

    $configConnection = New-Object System.DirectoryServices.DirectoryEntry ($cfgNC)
    $exchSearchString = "(&(objectClass=msExchExchangeServer)(name=*" + $Env:COMPUTERNAME + "*))"
    $configSearcher = New-Object System.DirectoryServices.DirectorySearcher($configConnection, $exchSearchString)

    is the same as this:

    $exchSearchString = "(&(objectClass=msExchExchangeServer)(name=*" + $Env:COMPUTERNAME + "*))"
    $configSearcher = New-Object System.DirectoryServices.DirectorySearcher($exchSearchString)

    is the same as

    $searcher=[System.DirectoryServices.DirectorySearcher]'objectClass=msExchExchangeServer'

    which is identical to this:

    $searcher=[adsisearcher]'objectClass=msExchExchangeServer'

    All of the other bits you aare using are redundant or unnecessary.

    This would only beused if you have more than one Exchange server in  your domain.

    "(&(objectClass=msExchExchangeServer)(name=*$Env:COMPUTERNAME*))"

    We would set searchroot easily here to:

    $searcher.SearchRoot="LDAP://CN=Configuration,$(([adsi]'').distinguishedName)"

    I prefer this method:

    $searcher.SearchRoot=([adsi]'LDAP://rootDSE').configurationNamingContext


    ¯\_(ツ)_/¯




    • Edited by jrv Thursday, January 29, 2015 1:56 PM
    Thursday, January 29, 2015 1:47 PM
  • Little trick.

    You can get any domain or any confiuration by just referencing the domain name.

    ([adsi]'LDAP://testnet.local/rootDSE').configurationNamingContext

    or

    ([adsi]'LDAP://testnet/rootDSE').configurationNamingContext

    or by referencing any remote DC.

    You can get any of the other context and the schema the same way.


    ¯\_(ツ)_/¯

    Thursday, January 29, 2015 2:00 PM
  • Too detailed, appreciated! It was very helpful. I was thinking along with your description and understand it.Now I have all been recorded. Thanks for share !
    Friday, January 30, 2015 7:50 AM