Archive for the 'one-liner' Category

Group Membership Unions and Intersections

A friend of mine recently asked for one-liners for Active Directory group membership union and intersection.

These are the one-liners which I sent him:

Group Union – users present in either of the groups (he needed a list of DNs of direct members of two groups):

(Get-QADGroupMember GroupA –Type user) + (Get-QADGroupMember GroupB –Type user) | 
 Select-ExpandProperty DN
 Sort | Select-Unique

Group Intersection – users present in both groups at the same time:

Compare-Object (Get-QADGroupMember GroupA –Type user) `
 (Get-QADGroupMember GroupB –Type user) `
 -ExcludeDifferent -IncludeEqual | Select-ExpandProperty InputObject

You can obviously tweak them to add indirect users (with -indirect parameter) or enabled only (-enabled), etc. – see Get-QADGroupMember help for all options.

I am pretty sure that there are multiple ways to skin these cats – so if you have better alternatives – please post these in the comments.


Clean up expired certificates from AD

Security MVP Vadims Podans just did a great post on using PowerShell to remove expired user certificates from Active Directory.

In a nutshell,

  • If your company is using certificates for user authentication or encryption, these expire every now and then,
  • Your Enterprise CA in that case appends new certificates to users’ userCertificate attribute, while leaving expired certs there as well,
  • Over time these increasingly clutter your AD, making administration more difficult and negatively affecting AD replication traffic.

Luckily, cleaning up expired certificates with PowerShell is extremely easy.

To do the clean-up for a specific user you can run this one-liner:

Get-QADUser username | Remove-QADCertificate -Valid:$false

To clean-up the entire domain, just do:

Get-QADUser | Remove-QADCertificate -Valid:$false

See Vadim’s original post for details.

Read more about PKI management with PowerShell here.

Find everyone rolling up to me

Yesterday someone asked me to help create a distribution list for everyone reporting to a particular manager (directly or indirectly). Needless to say, that PowerShell makes getting a list of such user accounts a piece of cake!

Here’s the quick script (using AD cmdlets) which I emailed back:

function Get-QADIndirectReport {
param ($Identity)
  # Find all direct reports
  Get-QADUser -Manager $Identity | ForEach-Object {
      # Output direct report
    # Then recursively call this function for all
    # reports of this report
    Get-QADIndirectReport -Identity $_


# usage example
Get-QADIndirectReport 'Dmitry Sotnikov'

Basically, AD cmdlets natively can retrieve all direct reports, and I have created a function which keeps going deeper level-by-level getting everyone reporting indirectly as well.

You can then take this a few steps further. For example, say, you want to get a list of users you could then just copy/paste into Outlook. Simply select the Email property from the user objects and ask PowerShell to put semicolon between the addresses:

# get a list of addresses for an email message
(Get-QADIndirectReport 'Dmitry Sotnikov' | 
  Select-Object -ExpandProperty Email) -join '; '

Or you could indeed use the list to populate a group:

# add everyone to a group
Get-QADIndirectReport 'Dmitry Sotnikov' |
  Add-QADGroupMember DmitrysReports

Or you could further restrict the list by City, Department and so on by simply tweaking Get-QADUser parameters in the code above. PowerShell is super-flexible!

Clear AD attribute

Just yesterday a colleague of mine asked me how to undo an Active Directory object property change from the value he erroneously put back to <not set>. It turned out that I never actually blogged about that – so here you go. 🙂

Clearing AD attributes us actually as easy as just setting the value to $null. For example, here’s how you do it for properties which we have exposed in Set- cmdlets parameters:

Set-QADUser 'Amy Hardy' -City $null

Or for more internal attributes:

Set-QADUser 'Amy Hardy' -ObjectAttributes @{adminDescription=$null}

Hope that helps!

Find group members by location

Today I had to promote a local event to everyone on our cloud taskforce. The distribution list we have for everyone interested in cloud projects is quite large so I thought I would share this one-liner with you.

The first version I tried was quite straight-forward – simply get all team members and filter out the members based on their city:

Get-QADGroupMember Cloud -Indirect |
    where { $_.City-eq "Aliso Viejo" }

However, this actually was quite slow – because the group is big and all the filtering was happening on the client side (all objects were extracted from domain controller and then filtered by PowerShell on my workstation). The solution is to use parameters of the initial Get cmdlet. Get-QADGroupMember unfortunately does not have the City parameter yet, so I used the universal LdapFilter parameter to do the proper filtering.

Get-QADGroupMember Cloud -Indirect -LdapFilter '(l=Aliso Viejo)'

This second one-liner performed almost twice faster – so this is the one I would recommend for large group use!


Resolving external accounts in domain groups

You do not have to do anything to do that. If you group contains an account from a trusted domain, good old

Get-QADGroupMember MyGroup

will resolve foreign security principals and show them as regular users.

However, in some cases – for example for performance reasons – you might not want AD cmdlets to perform these look-ups in trusted domains. For that, you just need to use the KeepForeignSecurityPrincipals parameter that we added in AD cmdlets 1.4:

Get-QADGroupMember MyGroup -KeepForeignSecurityPrincipals

Resolving Foreign Security Principals

Starting with version 1.4 AD cmdlets can retrieve and provide detailed information on all properties for foreign security principals.

When you add a user from a trusted domain to a group in your domain, AD creates a local auxilliary object – foreign security principal – to represent this external account. You can essentially think about this object as a pointer to the actual account in a trusted domain. You can read more about them in the Security Principals section of this TechNet article.

Now QAD cmdlets can resolve these “pointers” and show you real accounts to which they point.

For example, this command will retrieve all foreign security principals which you have in your domain (i.e. all foreign accounts ever granted any rights) and try to resolve them to external accounts from original domains:

Get-QADObject -ResolveForeignSecurityPrincipals -Type foreignSecurityPrincipal

Remove disabled accounts from groups

Get-QADGroupMember now has Disabled and Enabled parameters which are very handy when it comes to tasks such as cleaning up a group from disabled accounts:

Get-QADGroupMember MyGroup -Disabled |
    Remove-QADGroupMember MyGroup

Or obviously helps when you need to do something with group members and need to make sure that they are all valid enabled accounts:

Get-QADGroupMember MyGroup -Enabled

Happy scripting! 🙂

Manage Email addresses without Exchange cmdlets

AD cmdlets 1.4 added new cmdlets and parameters which let you manage email addresses in your environment even if you do not have Exchange Management Shell. This is very handy if you are on Exchange 2003, do not have Exchange cmdlets installed, or just don’t want to switch between snapins.

Here’s the quick overview of what we have added:

Retrieving accounts by any proxy addresses:

Now Get-QADObject, Get-QADGroup, and Get-QADUser all have PrimaryProxyAddress, ProxyAddress and SecondaryProxyAddress parameters which can let you be more specific in your queries and thus retrieve objects much faster (compared to just supplying the address as identity parameter and relying on default resolution).

For example, you could do:

Get-QADUser -ProxyAddress 'x400:C=US;A= ;P=Quest Software;O=Aliso Viejo;S=Sotnikov;G=Dmitry;I=A;'


Get-QADUser -SecondaryProxyAddress '*'

Adding email addresses:

Just use Add-QADProxyAddress and specify various parameters for specifics (pair with Clear-QADProxyAddress to replace previous addresses):

Get-QADUser company\jsmith |
  Add-QADProxyAddress -Address '' |
  Add-QADProxyAddress -Type SMTP -Address '' -Primary |
  Add-QADProxyAddress -CustomType 'sip' -Address ''

Removing all addresses:

Did I mention Clear-QADProxyAddress?

Get-QADUser company\jsmith |
  Clear-QADProxyAddress |
  Add-QADProxyAddress -Address '' |
  Add-QADProxyAddress -Type SMTP -Address '' -Primary |
  Add-QADProxyAddress -CustomType 'sip' -Address ''

Removing individual addresses:

Use Remove-QADProxyAddress and it’s parameters to operate on a specific address or a set of addresses:

Get-QADUser |
  Remove-QADProxyAddress -Pattern '*'

Modifying addresses:

Set-QADProxyAddress lets you pick and replace specific addresses:

Get-QADUser |
  Set-QADProxyAddress -From '*' -MakePrimary


Get-QADUser |
  Set-QADProxyAddress -From '*' -To '*'

Enabling or disabling email address policy:

Enable-QADEmailAddressPolicy and Disable-QADEmailAddressPolicy are your respective friends and can be applied to individual objects. For example:

Get-QADUser DomainName\UserName | Disable-QADEmailAddressPolicy
Get-QADUser -City London | Enable-QADEmailAddressPolicy

Happy scripting!

List all workstations in the domain

Here’s another quick oneliner I had to create for someone today and wanted to share with you:

Get-QADComputer -ComputerRole member -SizeLimit 0 -OSName 'Windows XP*', 'Windows 2000 Professional', 'Windows 7*', 'Windows Vista*'

The initial one-liner the customer was using was retrieving all Member computers but then using Where to filter by $_.operatingsystem whatever did not have Server in the name. This took longer (because Where is filtering on the client side after all objects are already retrieved) and resulted in extra computers being reported such as non-Windows storage systems.

Using cmdlet parameters makes sure that filtering is done during the object retrieval which is more efficient. And, as you can see, OSName parameter – as most parameters in QAD cmdlets – supports multiple values.

Depending on your environment you might want to modify the OS list to include Windows 8 or Mac OS 😉

If you want to get full list of operating systems in use in your company you would probably execute something like:

Get-QADComputer -SizeLimit 0 | group operatingsystem | sort Count -Descending

Hope this helps!


The posts on this blog are provided “as is” with no warranties and confer no rights. The opinions expressed on this site are mine and mine alone, and do not necessarily represent those of my employer - WSO2 or anyone else for that matter. All trademarks acknowledged.

© 2007-2014 Dmitry Sotnikov

May 2023

%d bloggers like this: