Recently I was tasked with writing a PowerShell script that would gather both local and AD users/groups from Local Groups and return the total number of users. This was needed for accurate reporting of SPLA licensing for Remote Desktop Services and Office implementations. I had blogged previously about listing group membership from AD but this is taking the process a step further. I originally started out writing a script that would run on each machine, meaning locally on that machine. What really needed to happen, was to run the script from the administrative tools server, remotely connecting to each member server to gather the users from the local server groups and create a server specific file for each. The administrative tools server then parses those files for AD groups and adds those users to the appropriate server file. Once all users have been gathered, the final step is to count the rows in the CSV file and write it to the file.
The two scripts are included below. There is only one domain involved where this script is run. I needed to get all local and AD users and groups that are in the Administrators, Power Users, and Remote Desktop Users groups for the listed computers. That process is handled by the Get-UsersRemote script. The last line of the Get-UsersRemote calls the Get-ADGroupInfo script that runs locally on the administration tools server to complete the gathering of the AD group data. The ADUserList is updated and the final step is to add the count as the last line of each respective file.
Get-UsersRemote.ps1
#————————————————-
# Written by Terri Donahue
# This script gathers local group members retrieved from local computer groups remotely using the Invoke-Command
# with a computername parameter
# You can add any other computers to the $computers array
#————————————————-
#array of computers
$computers = @(“computer1″,”computer2”)
Foreach ($computer in $computers) {
#Runs the script block on the remote computer
Invoke-Command -ComputerName $computer -scriptblock {
#Creates new files locally on the machine where the script is running
$UserList = New-Item -Type file -Force “c:adminGet-GroupMembershipUserList.csv”
$ADUserList = New-Item -Type file -Force “c:adminGet-GroupMembershipADUserList.csv”
“Users” | Out-File $UserList -Encoding ASCII
#List of groups to gather members from. New Groups can be added to the array as needed
#The members of the group are written to the UserList.csv file
#on the machine where the command is running
$groupnames = @(“administrators”,”remote desktop users”,”power users”)
foreach ($group in $groupnames) {
$members = net localgroup $group |
where {$_ -AND $_ -notmatch “command completed successfully”} |
select -skip 4
$members | Out-File $UserList -Encoding ASCII -Append #writes retrieved group membership to UserList file
#This section writes all local users (non-domain users) to the ADUserList file
#which is the master list for the audit
if ($members -notlike “domain*”){ #replace domain with your domain designation
$member.Name | Out-File $ADUserList -Encoding ASCII -Append
}
}
}
}
& C:adminGet-GroupMembershipGet-ADGroupInfo.ps1
Get-ADGroupInfo.ps1
#————————————————-
# Written by Terri Donahue
# 8/13/2014
# This script is called by the Get-User.ps1 script to gather and count AD group members retrieved from local computer groups
# You can add any other needed computers to the $computers array
#————————————————-
#Import AD Module
Import-Module ActiveDirectory
#change to the AD provider
cd AD:
#List of computers for which to gather group data
$computers = @(“computer1″,”computer2”)
foreach ($computer in $computers) {
$UserList = “c:adminGet-GroupMembership” + $computer + “_UserList.csv”
$ADUserList = “c:adminGet-GroupMembership” + $computer + “_ADUserList.csv”
New-PSDrive -Name S -Root \$computerc$ -PSProvider FileSystem
Move-Item -Path s:adminGet-GroupMembershipUserList.csv -Destination $UserList -Force
Move-Item -Path s:adminGet-GroupMembershipADUserList.csv -Destination $ADUserList -Force
Remove-PSDrive S
}
Import-Csv $UserList | ForEach-Object {
foreach ($UName in $UserList) {
$UName =$_.Users
#This section excludes the local administrator and any groups with Admins or Users in the name. Any other entries
#are copied over to the ADUserList file for the specific computer and the count is incremented
if (($UName -notlike “Administrator”) -and ($UName -notlike “domain*Admins”) -and ($UName -notlike “domain*Users”)) {
$UName | Out-File $ADUserList -Encoding ASCII -Append
}
#This section test to see if the name matches Users or Admins while excluding Domain Admins
#If it matches, it removes the OW from the group name and queries AD to gather the users that
#are members of the group. Each user is copied to the ADUserList file for the specific
#computer. Domain Admins is excluded from the total count as well for SPLA reporting
if ((($UName -like “domain*Users”) -or ($UName -like “domain*Admins”)) -and ($UName -ne “domainDomain Admins”)){
$newUName = $UName.replace(“domain”,””) #strips the domain from the group name for the AD query
$group = Get-ADGroup $newUName
foreach ($member in Get-ADGroupMember $group){
$enabled = Get-ADUser $member | select -ExpandProperty Enabled
if ($enabled -like “True”) { #checks if the user is enabled
“domain” + $member.Name | Out-File $ADUserList -Encoding ASCII -Append #adds the domain information back and writes the user to the file
}
}
}
}
$a = (Get-Content $ADUserList | Measure-Object)
$count = $a.Count
#Adds the count to the end of the ADUserList file for the specific computer
“User Count = ” +$count | Out-File $ADUserList -Encoding ASCII -Append
}
Disclaimer: I am not a PowerShell guru but do try my hand occasionally at automating recurring tasks. This script is provided as a guide and may need tweaking for your specific environment. Test before running in production.
Terri is a Microsoft MVP (ASP .NET/IIS), an MCSA: Windows Server 2012, and a Cloud Administrator at OrcsWeb, a hosted server company providing managed hosting solutions