From Svendsen Tech PowerShell Wiki

Here is PowerShell code for adding/removing groups and users from local groups on remote servers, wrapped into two quite feature-complete functions that act similarly to native cmdlets when imported from the module.

The code is public domain, so you may do with it as you please.

The code is compatible with PowerShell version 2 and up.

You can manage groups with group policies (GPO), but the system was encumbered with flaws in that - last time I checked, which was in the 2008 R2 days (it's fixed now with GPO preferences for Win 7 / 2008 R2) - you couldn't enforce group membership without also excluding all other members not in your predefined list. I always thought this was curiously lacking as a feature/capability. I would have liked a check box that said "enforce these members, but do not remove others". I've been made aware there are Group Policy Preferences for 2008 R2 that indeed let you "Update membership" on the group (and also build group names using variables like "%domain%\Local_Admin_%computername%").

Regardless, in the wild, sometimes you need to add or remove members from local groups on remote servers - and sometimes it's a huge benefit to script it. That's why I decided to write this article about a simple script module that I wrote over three years ago now and rewrote and added features to this evening (it's almost 5 AM - I should in theory be in bed since I have work in the morning).

There's a -PSRemoting parameter that can also use different credentials (specify -Credential ($cred = Get-Credential)) in case that's helpful. Also remember runas.exe (runas /user:domain\username powershell.exe).

The code is basically just this, wrapped in convenience:

#([adsi]"WinNT://$env:COMPUTERNAME/Administrators,Group").Add("WinNT://ad.example.com/Role Local Admin Servers")

... and with .Remove() for removing.





Tweet









Screenshot example

Download

STRemoteLocalGroupManagement.zip - download, unblock, unzip into a modules folder, Import-Module it. Tip: See $Env:PSModulePath.

If you have Windows Management Framework (WMF) version 5 and up, you can install it easily from the PowerShell gallery by simply running this command (requires an internet connection):

Install-Module -Name STRemoteLocalGroupManagement





PowerShell code

#requires -version 2 function Add-STLocalGroupADEntity { <# .SYNOPSIS Adds an AD user or group to a remote server's local group. By default the "Remote Desktop Users" group is targeted. Use -LocalGroup to specify a different group, like "Administrators". This code is compatible with PowerShell version 2 and up. Author: Joakim Borger Svendsen, 2014-12-03. Minor tweaking on 2017-03-31. The code is public domain, do with it as you please. .PARAMETER ComputerName Remote computer(s) on which to add user/group to a local group. .PARAMETER LocalGroup Local group name (on the remote computer). Default "Remote Desktop Users". .PARAMETER Domain Domain the AD entity belongs to. Long/dotted form. .PARAMETER Identity Group(s) or user(s) to add to the remote computer's local group (by default to its "Remote Desktop Users" group). .PARAMETER PSRemoting Use PowerShell remoting instead of remote ADSI. .PARAMETER Credential A PowerShell credentials object. Only used with PowerShell remoting. See Get-Help Get-Credential. .EXAMPLE Add-STLocalGroupADEntity -ComputerName 2012r2 -LocalGroup Administrators ` -Domain whatever.local -Identity TestUser0001 ComputerName : 2012r2 Identity : TestUser0001 Success : True Error : LocalGroup : Administrators Domain : whatever.local #> [CmdletBinding()] param( # Remote computer(s) on which to add user/group to a local group. [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [Alias('Cn', 'Name', 'PSComputerName')] [string[]] $ComputerName, # Local group name (on the remote computer). Default "Remote Desktop Users". [string] $LocalGroup = 'Remote Desktop Users', # Domain the AD entity belongs to. Long/dotted form. [Parameter(Mandatory=$true)] [string] $Domain, # AD group(s) or user(s) to add to the remote computer's local group (by default to its "Remote Desktop Users" group). [Parameter(Mandatory=$true)] [string[]] $Identity, # Use PowerShell remoting instead of remote ADSI. [switch] $PSRemoting, # A PowerShell credentials object. Only used with PowerShell remoting. See Get-Help Get-Credential. [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty) begin { # For use with PSRemoting. $ScriptBlock = { param( [string] $Computer, [string] $LocalGroup, [string] $Domain, [string[]] $Identity) foreach ($Id in $Identity) { Write-Verbose "Processing ${Computer} and ${Id}" $ErrorActionPreference = 'Stop' try { ([adsi]"WinNT://${Computer}/${LocalGroup},Group").Add("WinNT://${Domain}/${Id}") New-Object PSObject -Property @{ ComputerName = $Computer Identity = $Id Success = $true Error = $null LocalGroup = $LocalGroup Domain = $Domain } } catch { New-Object PSObject -Property @{ ComputerName = $Computer Identity = $Id Success = $false Error = $_.ToString() -replace '[\r

]+', ' ' LocalGroup = $LocalGroup Domain = $Domain } } $ErrorActionPreference = 'Continue' } } } process { @(foreach ($Computer in $ComputerName) { #Write-Verbose -Message "Processing ${Computer} and ${Id}" if ($PSRemoting) { if ($Credential.Username -match '\S') { Invoke-Command -ComputerName $Computer -ScriptBlock $ScriptBlock -ArgumentList $Computer, $LocalGroup, $Domain, $Identity -Credential $Credential } else { Invoke-Command -ComputerName $Computer -ScriptBlock $ScriptBlock -ArgumentList $Computer, $LocalGroup, $Domain, $Identity } } else { foreach ($Id in $Identity) { Write-Verbose "Processing ${Computer} and ${Id}" $ErrorActionPreference = 'Stop' try { ([adsi]"WinNT://${Computer}/${LocalGroup},Group").Add("WinNT://${Domain}/${Id}") New-Object PSObject -Property @{ ComputerName = $Computer Identity = $Id Success = $true Error = $null LocalGroup = $LocalGroup Domain = $Domain } } catch { New-Object PSObject -Property @{ ComputerName = $Computer Identity = $Id Success = $false Error = $_.ToString() -replace '[\r

]+', ' ' LocalGroup = $LocalGroup Domain = $Domain } } $ErrorActionPreference = 'Continue' } } }) | Select-Object ComputerName, Identity, Success, Error, LocalGroup, Domain } } function Remove-STLocalGroupADEntity { <# .SYNOPSIS Removes an AD user or group from a remote server's local group. By default the "Remote Desktop Users" group is targeted. Use -LocalGroup to specify a different group, like "Administrators". This code is compatible with PowerShell version 2 and up. Author: Joakim Borger Svendsen, 2014-12-03. Revisited on 2017-03-31. The code is public domain, do with it as you please. .PARAMETER ComputerName, Remote computer(s) on which to remove user/group from a local group. .PARAMETER LocalGroup Local group name (on the remote computer). Default "Remote Desktop Users". .PARAMETER Domain Domain the AD entity belongs to. Long/dotted form. .PARAMETER Identity Group(s) or user(s) to remove from the remote computer's local group (by default its "Remote Desktop Users" group). .PARAMETER PSRemoting Use PowerShell remoting instead of remote ADSI. .PARAMETER Credential A PowerShell credentials object. Only used with PowerShell remoting. See Get-Help Get-Credential. .EXAMPLE Remove-STLocalGroupADEntity -ComputerName 2012r2 -LocalGroup "Administrators" ` -Domain whatever.local -Identity TestUser0001 # Removing now ComputerName : 2012r2 Identity : TestUser0001 Success : True Error : LocalGroup : Administrators Domain : whatever.local #> [CmdletBinding()] param( # Remote computer(s) on which to remove user/group from a local group. [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [Alias('Cn', 'Name', 'PSComputerName')] [string[]] $ComputerName, # Local group name (on the remote computer). Default "Remote Desktop Users". [string] $LocalGroup = 'Remote Desktop Users', # Domain the -ADEntity belongs to. Long/dotted form. [Parameter(Mandatory=$true)] [string] $Domain, # AD group(s) or user(s) to remove from the remote computer's local group (by default its "Remote Desktop Users" group). [Parameter(Mandatory=$true)] [string[]] $Identity, # Use PowerShell remoting instead of remote ADSI. [switch] $PSRemoting, # A PowerShell credentials object. Only used with PowerShell remoting. See Get-Help Get-Credential. [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty) begin { # For use with PSRemoting. $ScriptBlock = { param( [string] $Computer, [string] $LocalGroup, [string] $Domain, [string[]] $Identity) foreach ($Id in $Identity) { Write-Verbose "Processing ${Computer} and ${Id}" $ErrorActionPreference = 'Stop' try { ([adsi]"WinNT://${Computer}/${LocalGroup},Group").Remove("WinNT://${Domain}/${Id}") New-Object PSObject -Property @{ ComputerName = $Computer Identity = $Id Success = $true Error = $null LocalGroup = $LocalGroup Domain = $Domain } } catch { New-Object PSObject -Property @{ ComputerName = $Computer Identity = $Id Success = $false Error = $_.ToString() -replace '[\r

]+', ' ' LocalGroup = $LocalGroup Domain = $Domain } } $ErrorActionPreference = 'Continue' } } } process { @(foreach ($Computer in $ComputerName) { #Write-Verbose -Message "Processing ${Computer} and ${Id}" if ($PSRemoting) { if ($Credential.Username -match '\S') { Invoke-Command -ComputerName $Computer -ScriptBlock $ScriptBlock -ArgumentList $Computer, $LocalGroup, $Domain, $Identity -Credential $Credential } else { Invoke-Command -ComputerName $Computer -ScriptBlock $ScriptBlock -ArgumentList $Computer, $LocalGroup, $Domain, $Identity } } else { foreach ($Id in $Identity) { Write-Verbose "Processing ${Computer} and ${Id}" $ErrorActionPreference = 'Stop' try { ([adsi]"WinNT://${Computer}/${LocalGroup},Group").Remove("WinNT://${Domain}/${Id}") New-Object PSObject -Property @{ ComputerName = $Computer Identity = $Id Success = $true Error = $null LocalGroup = $LocalGroup Domain = $Domain } } catch { New-Object PSObject -Property @{ ComputerName = $Computer Identity = $Id Success = $false Error = $_.ToString() -replace '[\r

]+', ' ' LocalGroup = $LocalGroup Domain = $Domain } } $ErrorActionPreference = 'Continue' } } }) | Select-Object ComputerName, Identity, Success, Error, LocalGroup, Domain } } Export-ModuleMember Add-STLocalGroupADIdentity, Remove-STLocalGroupADIdentity #([adsi]"WinNT://$env:COMPUTERNAME/Administrators,Group").Add("WinNT://ad.example.com/Role Local Admin Servers")