Question

I'm trying to search for users in an instance of AD LDS (ADAM) where a property is not set, for example where the "company" property is not set to a value in the ADAM store (or AD for that matter).

When I use a PrincipalSearcher and a custom UserPrincipal with a custom AdvancedSearchFilters object, I get the error:

An unhandled exception of type 'System.ArgumentException' occurred in System.DirectoryServices.dll

Additional information: The (&(objectClass=user)(!(company=))) search filter is invalid.

Here is my sample code:

using System;
using System.DirectoryServices.AccountManagement;
using System.Security.Permissions;
using System.Linq;

namespace AdamDump
{
    class Program
    {
        static void Main(string[] args)
        {
            PrincipalContext context = new PrincipalContext(ContextType.ApplicationDirectory, "MyAdamInstance:50000", "OU=Adam Users,dc=apps01,dc=mydomain", "queryaccount", "password");        

            // initialize a Query By Example
            using (MyUserPrincipal myUserPrincipal = new MyUserPrincipal(context))
            {
                myUserPrincipal.MyAdvancedFilters.WhereCompanyNotSet();

                PrincipalSearchResult<Principal> principals = null;

                // do the search...
                using (PrincipalSearcher principalSearcher = new PrincipalSearcher(myUserPrincipal))
                {
                    principals = principalSearcher.FindAll();
                }

                var myUsers = principals.Select(principal => principal as MyUserPrincipal).ToList();

                foreach (var user in myUsers)
                    Console.WriteLine("Name: {0}, Account{1}", user.DisplayName, user.SamAccountName);

                Console.WriteLine("Total found: {0}", myUsers.Count);
            }                 
        }
    }


    [DirectoryObjectClass("user")]
    [DirectoryRdnPrefix("CN")]
    [EnvironmentPermissionAttribute(SecurityAction.LinkDemand, Unrestricted = true)]
    public class MyUserPrincipal : UserPrincipal
    {
        private MyAdvancedFilters _myAdvancedFilters;

        /// <summary>
        /// Initializes a new instance of the <see cref="MyUserPrincipal"/> class.
        /// </summary>
        /// <param name="context">A <see cref="PrincipalContext"/> to associate this instance with.</param>
        [EnvironmentPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
        public MyUserPrincipal(PrincipalContext context)
            : base(context) { }

        public MyAdvancedFilters MyAdvancedFilters
        {
            get
            {
                return this.AdvancedSearchFilter as MyAdvancedFilters;
            }
        }

        public override AdvancedFilters AdvancedSearchFilter
        {
            get
            {
                if (_myAdvancedFilters == null)
                {
                    _myAdvancedFilters = new MyAdvancedFilters(this);                    
                }

                return _myAdvancedFilters;
            }
        }
    }

    public class MyAdvancedFilters : AdvancedFilters
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="MyAdvancedFilters"/> class.
        /// </summary>
        /// <param name="principal">The source <see cref="Principal"/></param>
        public MyAdvancedFilters(Principal principal) : base(principal) { }

        public void WhereCompanyNotSet()
        {
            this.AdvancedFilterSet("company", "", typeof(string), MatchType.NotEquals);
        }
    }
}
Was it helpful?

Solution

Modifying my AdvanceFilters class to the following gets the results I need.

public class MyAdvancedFilters : AdvancedFilters
{
    /// <summary>
    /// Initializes a new instance of the <see cref="MyAdvancedFilters"/> class.
    /// </summary>
    /// <param name="principal">The source <see cref="Principal"/></param>
    public MyAdvancedFilters(Principal principal) : base(principal) { }

    public void WhereCompanyNotSet()
    {
        this.AdvancedFilterSet("company", "*", typeof(string), MatchType.NotEquals);
    }
}

It is the "*" for the value part in the AdvancedFilterSet.

Thanks to Sean for leading to the right trail to come up with the answer appropriate for the AccountManagement objects.

OTHER TIPS

Try using this as your query:

(&(objectClass=user)(!(company=*)))

Docs: http://msdn.microsoft.com/en-gb/library/windows/desktop/aa746475(v=vs.85).aspx about half way down the page it says "Get all entries without an email attribute:"

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top