STRemoteLocalGroupManagement.psm1

#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\n]+', ' '
                        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\n]+', ' '
                            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\n]+', ' '
                        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\n]+', ' '
                            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")