Hi Again,
Recently we’ve been fed up with Deployed Printer Connections through Group Policy and have decided to map printers using a PowerShell logon script. We wanted printer additions, removals and defaults to be based on AD groups, and for the script to work with PowerShell 2.0. Our clients are Windows 7 and therefore have PowerShell 2.0 installed by default, with no Active Directory module included.
Checking if a user or computer is a member of a group recursively can be achieved easily in later versions of PowerShell by using Get-ADGroupMember with the recursive switch, this requires the Active Directory module. However this wasn’t an option for us.
What we ended up doing was writing a function that performed an LDAP query using the “In Chain” Object Identifier. This Page explains more about the different LDAP search filters. This is the LDAP filter we used:
(&(|(&(objectClass=user)(sAMAccountName=*USERNAMEHERE*))((&(objectClass=computer)(sAMAccountName=*COMPUTERNAMEHERE*))))(memberof:1.2.840.113556.1.4.1941:=*DISTINGUISHEDNAMEOFGROUPHERE*))”
It’s important to note that this LDAP query is an OR query and requires both the computer name and username to function properly, so it reads:
Object Class = User AND SAMAccountName = *USERNAMEHERE* OR Object Class = Computer AND SAMAccountName = *COMPUTERNAMEHERE* AND is a chained member of *DISTINGUISHEDNAMEOFGROUPHERE*
Here’s the script we came up with:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Function IsInGroup($Username,$ComputerName,$GroupName) { $DomainController = $ENV:LOGONSERVER.Replace("\\","") $Domain = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$DomainController") $Searcher = New-Object System.DirectoryServices.DirectorySearcher($Domain) $Searcher.PageSize = 100 $Searcher.SearchScope = "subtree" $Searcher.Filter = "(&(objectCategory=Group)(sAMAccountName=$GroupName))" $colProplist = "name","distinguishedName" foreach ($i in $colPropList){$Searcher.PropertiesToLoad.Add($i) | Out-Null} $GResult = $Searcher.FindOne() If($GResult -ne $null) { #Get the DN of the group $GroupDN = $GResult.Properties.distinguishedname $Searcher.Filter = "(&(|(&(objectClass=user)(sAMAccountName=$Username))((&(objectClass=computer)(sAMAccountName=$ComputerName))))(memberof:1.2.840.113556.1.4.1941:=$GroupDN))" $Result = $Searcher.FindAll() If ($Result -ne $null) {Return $True } Else {Return $False} } } |
Again the function requires both the User’s sAMAccountName and Computer’s sAMAccountName (E.g MYComputer$) supplied or the function will fail.
The function returns True if the user or computer is a member of the group, and False if they are not.
The username should be supplied without the domian, E.g $ENV:Username or “JohnW”
The Computername argument is the sAMAccountName of the computer E.g “MYCOMPUTER$”
The GroupName argument is the name of the group you want to query. E.g “MyGroup”
The script does the following:
- Finds the Logon Server of the user running the function
- Searches for the group by name to find its Distinguished Name
- If we found the group – perform the LDAP query with the supplied arguments and the Distinguished Name of the group.
- Return True if the LDAP query returns a result. Return False if not.
As always, let us know if you find a use for this, or if you have any questions or comments!
Nice work!