Everyone now and then, there comes a moment you need to add a user into Administrators group on each computer in domain. It's not a big problem, if all your systems are in one language, or if you have to just add one user to multiple systems which you can easily accomplish with Group Policies. It gets a bit harder if you need to add one user per machine, and even harder if you need to add one user per machine with unknown language.
There are different approaches to this problem and many batch and powershell solutions. One of those approaches is to get the Administrators group name in multiple languages and simply code it in. The other approach which we describe below is to use Domain Admins name which is consistent across the domain and is based on language name of domain controller rather than on system it's used on. We simply scan all local groups for the standard Domain Admins group which should only be available in local Administrators group on local machine, and when that group is found we add the user inside without checking the rest of the groups. It's not the fastest solution but it surely gets the job done without knowing all the Administrators group names in all languages, and additionally you can always use it for different purposes. The last approach described in here is the fastest one and it's using Well-Known-SIDs allowing to add user directly to the group without knowing it's name.
If you're into old approach (multiply this per each language changing Administrators to respective group names):
net localgroup Administrators Evotec\user1 /add
If you would like to go with approach of finding Domain Admins first and then adding a user you can simply use this code:
$gComputerName = $env:COMPUTERNAME # Computer to ADD user to
$gLookFor = "Administratorzy domeny" # Domain Admins group for Domain Controller in Polish Language
$gDomain = "Evotec" # Domain Name
$gUser = "user1" # UserName to ADD
function DoWork($computerName, $groupToLookFor, $domain, $user) {
cls
$groups = get-wmiobject -Query "select * from Win32_Group Where Domain='$computerName'" -ComputerName $computerName
Foreach ($group in $($groups.Name)) {
Write-Host "Checking group $group" -ForegroundColor Magenta
$members = (Get-LocalGroupMembers -ComputerName $computerName -GroupName $group).Members
foreach ($member in $members) {
if ($member -eq $groupToLookFor) {
Write-Host "Found $member" -ForegroundColor Magenta
Write-Host "Adding User $gDomain\$gUser " -ForegroundColor Magenta
Set-User $computerName $group $domain $user
Write-Host "Quitting. My job is done." -ForegroundColor Magenta
exit
}
}
}
}
function Set-User ($computer, $group, $domain, $user) {
try {
$de = [ADSI]"WinNT://$computer/$Group,group"
$de.psbase.Invoke("Add",([ADSI]"WinNT://$domain/$user").path)
} catch {
write-host "User not added, already exists or not running as Administrator" -ForegroundColor Red
}
}
function Get-LocalGroupMembers {
param(
[parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
[Alias("Name")]
[string]$ComputerName,
[string]$GroupName = "Administrators"
)
begin {}
process
{
# If the account name of the computer object was passed in, it will
# end with a $. Get rid of it so it doesn't screw up the WMI query.
$ComputerName = $ComputerName.Replace("`$", '')
# Initialize an array to hold the results of our query.
$arr = @()
$wmi = Get-WmiObject -ComputerName $ComputerName -Query ` "SELECT * FROM Win32_GroupUser WHERE GroupComponent=`"Win32_Group.Domain='$ComputerName',Name='$GroupName'`""
# Parse out the username from each result and append it to the array.
if ($wmi -ne $null)
{
foreach ($item in $wmi)
{
$arr += ($item.PartComponent.Substring($item.PartComponent.IndexOf(',') + 1).Replace('Name=', '').Replace("`"", ''))
}
}
$hash = @{ComputerName=$ComputerName;Members=$arr}
return $hash
}
end{}
}
DoWork $gComputerName $gLookFor $gDomain $gUser
The output of the script is pretty simple. When run first time:
Checking group Access Control Assistance Operators
Checking group Administrators
Found Administratorzy domeny
Adding User Evotec\user1
Quitting. My job is done.
The output of the script when run 2nd time on same machine where user already exists:
Checking group Access Control Assistance Operators
Checking group Administrators
Found Administratorzy domeny
Adding User Evotec\user1
User not added, already exists or not running as Administrator
Quitting. My job is done.
As there's not much error checking being done on each level and you're little paranoid you can always add more protection. Of course if you would like to deploy this script to multiple computers and different computer requires different user some modifications are required for this scenario.
Our final approach by finding SID of the group (below is a list of all well known SIDs just in case you need one.
$gComputerName = $env:COMPUTERNAME # Computer to ADD user to
$gLookForBySid = "S-1-5-32-569" # group sid Cryptographic Operators
$gDomain = "Evotec" # Domain Name
$gUser = "user1" # UserName to ADD
function DoWork($computerName, $groupSidToLookFor, $domain, $user) {
cls
Write-Host "Checking group SID $groupSidToLookFor" -ForegroundColor Magenta
$group = Get-GroupBySid $computerName $groupSidToLookFor
Write-Host "Adding User $gDomain\$gUser to group $group" -ForegroundColor Magenta
Set-User $computerName $group $domain $user
Write-Host "Quitting. My job is done." -ForegroundColor Magenta
exit
}
function Set-User ($computer, $group, $domain, $user) {
try {
$de = [ADSI]"WinNT://$computer/$Group,group"
$de.psbase.Invoke("Add",([ADSI]"WinNT://$domain/$user").path)
} catch {
write-host "User not added, already exists or not running as Administrator" -ForegroundColor Red
}
}
function Get-GroupBySid () {
param(
[parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
[Alias("Name")]
[string]$ComputerName,
[string]$GroupNameSid = "S-1-5-32-544"
)
$objSID = New-Object System.Security.Principal.SecurityIdentifier($GroupNameSid)
$objgroup = $objSID.Translate( [System.Security.Principal.NTAccount])
$objgroupname = ($objgroup.Value).Split("\")[1]
return ,$objgroupname
}
DoWork $gComputerName $gLookForBySid $gDomain $gUser
Successful script output
Checking group SID S-1-5-32-569
Adding User Evotec\user1 to group Cryptographic Operators
Quitting. My job is done.
Something went wrong script output
Checking group SID S-1-5-32-569
Adding User Evotec\user1 to group Cryptographic Operators
User not added, already exists or not running as Administrator
Quitting. My job is done.