0 votes

I've got an Adaxes scheduled task that will export records out of AD into a JSON text file. All is working well except for the ability to sort the objects returned from DirectorySearcher function. The code doesn't fail, it just doesn't sort by employeeID as expected. Can you give me an idea of what I'm missing. The code is attached below.

Import-Module Adaxes

# Formats output as JSON
function ConvertTo-Json20([object] $item){
    add-type -assembly system.web.extensions
    $ps_js=new-object system.web.script.serialization.javascriptSerializer
    return $ps_js.Serialize($item) 
}

# Read the txt file that has the file export location and field information and then export data to Sharepoint

$Context.LogMessage("About to export data to Sharepoint","Information")
$filePath = "c:\DirInt0118_Exp_Info.csv"   #Read file from Adaxes c: drive that contain export information

# Read the file and put into array variables
$ExpPath = @()
$LDAPNames = @()
$JSONNames = @()

Import-Csv $filePath |`
    ForEach-Object {
        $ExpPath += $_."ExportPath"
        $LDAPNames += $_."LDAPName"
        $JSONNames += $_."FieldsOut"
    }

if($ExpPath.Length -eq 0)
{
    $Context.LogMessage("No data found to import", "Information")
    return
}

$Context.LogMessage("Export path is: " + $ExpPath, "Information")
$Context.LogMessage("LDAP Names are: " + $LDAPNames, "Information")
$Context.LogMessage("Output Fields labels are: " + $JSONNames, "Information")

# Parse fields

$eachFieldIn = @($LDAPNames[0].split(","))
$eachFieldOut = @($JSONNames[0].split(","))

if (($eachFieldIn.Length -eq 0) -or ($eachFieldOut.Length -eq 0))
{
   $Context.LogMessage("Fields missing during import.  Processing terminated.", "Warning")
    return 
}

if (($eachFieldIn.Length) -ne ($eachFieldOut.Length))
{
   $Context.LogMessage("Field in/out count mismatch during import.  Processing terminated.", "Warning")
    return 
}

# Build path for the user report file
$exportFile = $ExpPath[0]

# Delete the existing file
Remove-Item $exportFile

# Create new file for the user report
New-Item $exportFile -Type File

# Get AdsPath of target object
$targetObject = $Context.BindToObjectByDN("%distinguishedName%")
$targetObjectPath = $targetObject.ADsPath

$Context.LogMessage("Domain being searched is: " + $targetObjectPath, "Information")

# Search all users in the target OU
$userSearcher = New-Object "Softerra.Adaxes.Adsi.Search.DirectorySearcher" $NULL, $False
$userSearcher.SearchParameters.BaseObjectPath = $targetObjectPath
$userSearcher.SearchParameters.PageSize = 1000
$userSearcher.SearchParameters.SearchScope = "ADS_SCOPE_SUBTREE"
# Filter for User objects that are not disabled and employeeID doesn't contain zeros or 'NMU' or employeeID is not blank
$userSearcher.SearchParameters.Filter = "(&(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(!(employeeID=000000))(!(employeeID=NMU))(employeeID=*))"
$userSearcher.SetPropertiesToLoad($eachFieldIn)

$userResult = $userSearcher.ExecuteSearch()

# Sort by employeeID
[color=#BF0000]$sortedUsers = $userResult.FetchAll() | sort-Object $_.properties.employeeID
[/color]
$totalUserCount = $sortedUsers.Count
$Context.LogMessage("The number of users is: " + $totalUserCount, "Information")

$count = 0

# Get the user information from the search results, convert to JSON and add them to the file

# Write out opening bracket
Add-Content $exportFile "["

foreach ($user in $sortedUsers)
{

    $hash1 = @{}
    for ($i=0; $i -lt $eachFieldIn.length; $i++) 
    {
        $fldValue = $user.Properties[$eachFieldIn[$i]].Value
        $hash1.Add($eachFieldOut[$i] , $fldValue)
    }

    $result = ConvertTo-Json20($hash1)

    $count++

    # If it's not the last record, add a comma to the end of the content, otherwise, leave it off
    if ($count -ne $totalUserCount) {
        Add-Content $exportFile "`n$result,"  
    } else {
        Add-Content $exportFile "`n$result"
    }

}

$userResult.Dispose()

# Write out closing bracket
Add-Content $exportFile "`n]"

$Context.LogMessage("Total records written = " + $count, "Information")
by (790 points)

1 Answer

0 votes
by (215k points)
selected by
Best answer

Hello,

Actually, you can specify sort options in the parameters of the DirectorySearcher class and return search results already sorted the way you need. To do this, add the following lines before calling the DirectorySearcher::ExecuteSearch() method:

$sortOption = New-Object "Softerra.Adaxes.Adsi.AdmSortOption"
$sortOption.PropertyName = "<LdapPropertyName>" # TODO: modify me
$sortOption.Direction = "<Direction>" # TODO: modify me

$userSearcher.SearchParameters.Sort = $sortOption

where:

  • <LdapPropertyName> specifies the LDAP display name of the property to sort by. For example, if you want to sort users by the username, specify sAMAccountName.
  • <Direction> - specifies the sort direction. Possible values: Ascending, Descending.

Also, to properly release the resources used by the search, we strongly recommend using the try... finally block:

...
try
{
    $sortedUsers = $userSearcher.ExecuteSearch()
    $totalUserCount = $sortedUsers.Count
    ...
}
finally
{
   # Release resources used by the search
   $sortedUsers.Dispose()
}
...

Also, have a look at the following example in our Script Repository: Inactive users. The script in the example also searches for user accounts, and search results are also sorted.

0

Thank you so much! That did the trick!!!

Related questions

0 votes
1 answer

I have Search configured for one of our web interfaces. One of the fields that can be searched is a custom attribute admCustomAttributeText4 (with a friendly name of ... are definitely some accounts with that attribute populated. Is this behaving as designed?

asked Sep 19, 2018 by sandramnc (790 points)
0 votes
1 answer

Is there an option to set a default sort order of the results of a query in the web interface? For example, if I want to allow someone to select from a list of groups, ... user can click on the column to sort, but I would like to control the initial results.

asked May 10, 2018 by adaxes_user (420 points)
0 votes
1 answer

I have a powershell scrip that runs as a Action on a custom command, and this scrip calls the ExecuteCustomCommand PS Function on a user. Is there ... .ExecuteCustomCommand($command.CommandID, $commandArguments) And have the result contain the log messages.

asked Jun 17, 2020 by Justinc (60 points)
0 votes
1 answer

Need help creating and updating users from a fixed formatted file exported daily by the HR system system. I just want to make sure that I am on the right track before ... this work? Any suggestions as to how to handle this scenario, best practices? Thanks!

asked Feb 2, 2016 by afshin (50 points)
0 votes
1 answer

I have a dropdown-field on the web surface, which is populated by a script. The script looks up all groups in a specific OU and displays them. In the Property Pattern ... random order. What should i do to show the groups in alphabetical order in the portal?

asked Sep 15, 2020 by lohnag (100 points)
2,757 questions
2,491 answers
6,523 comments
1,468,848 users