RemoteLocalGroups.psm1
|
function Get-RemoteLocalGroup { <# .SYNOPSIS Retrieves local groups (or specific local group objects) from one or more remote Windows computers. .DESCRIPTION Get-RemoteLocalGroup queries local groups on remote systems using PowerShell Remoting (Invoke-Command). You may select from common preset local groups (tab-complete/validation) and/or supply custom group names. If no group names are supplied, the function returns all local groups on the remote host(s). The function accepts optional credentials for remote connections. .PARAMETER Computername One or more target computer hostnames (or IPs). Required. Accepts pipeline input. .PARAMETER LocalGroupPreset Optional. One or more preset local group names (validated). Examples: Administrators, Remote Desktop Users, Power Users, Backup Operators, Remote Management Users, Event Log Readers, Print Operators, Guests. Use this parameter for convenience and tab-completion. .PARAMETER LocalGroup Optional. One or more custom local group names. Can be combined with -LocalGroupPreset. .PARAMETER Credential Optional. PSCredential used for remote connections if the current account does not have access to the targets. If omitted, the current user's credentials are used. .OUTPUTS When no group names supplied: raw Get-LocalGroup output from each remote host. When one or more group names supplied: PSCustomObject with properties: - ComputerName - Group - DisplayName - Description - SID - Error (null when successful, message string on failure) .EXAMPLE # List all local groups on two servers using current credentials Get-RemoteLocalGroup -Computername srv01,srv02 .EXAMPLE # Query Administrators and Remote Desktop Users using explicit credential $cred = Get-Credential Get-RemoteLocalGroup -Computername srv01 -LocalGroupPreset Administrators,'Remote Desktop Users' -Credential $cred .EXAMPLE # Query a mix of preset and custom group names Get-RemoteLocalGroup -Computername srv01 -LocalGroupPreset Administrators -LocalGroup 'My Custom Group' .NOTES - Requires PowerShell Remoting enabled on targets and appropriate rights to query local groups. - Uses Get-LocalGroup on the remote host; older OS versions may behave differently. .LINK Author: Luis Carrillo GitHub: https://www.github.com/LuisCarrilloTech #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0, HelpMessage = 'Target computer name(s)')] [ValidateNotNullOrEmpty()] [String[]]$Computername, [Parameter(Mandatory = $false, HelpMessage = 'Select one or more common local groups (preset)')] [ValidateSet( 'Administrators', 'Remote Desktop Users', 'Power Users', 'Backup Operators', 'Remote Management Users', 'Event Log Readers', 'Print Operators', 'Guests', IgnoreCase = $true )] [String[]]$LocalGroupPreset, [Parameter(Mandatory = $false, HelpMessage = 'Provide custom local group names (can be used with preset)')] [String[]]$LocalGroup, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Credentials for remote access')] [PSCredential]$Credential ) begin { # Merge presets + custom groups; if none provided, $TargetLocalGroups stays $null to indicate "list all" $TargetLocalGroups = @() if ($LocalGroupPreset) { $TargetLocalGroups += $LocalGroupPreset } if ($LocalGroup) { $TargetLocalGroups += $LocalGroup } $TargetLocalGroups = $TargetLocalGroups | ForEach-Object { $_.ToString().Trim() } | Where-Object { $_ -ne '' } | Select-Object -Unique if ($TargetLocalGroups.Count -eq 0) { $TargetLocalGroups = $null } # Scriptblock for listing all groups $sbListAll = { try { Get-LocalGroup | Select-Object Name, Description, @{n = 'SID'; e = { $_.SID.Value } } | Sort-Object Name } catch { throw "Get-LocalGroup failed: $($_.Exception.Message)" } } # Scriptblock for specific group(s) $sbByName = { param($Groups) $out = @() foreach ($g in $Groups) { try { $grp = Get-LocalGroup -Name $g -ErrorAction Stop $out += [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME Group = $g DisplayName = $grp.Name Description = $grp.Description SID = if ($grp.SID) { $grp.SID.Value } else { $null } Error = $null } } catch { $out += [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME Group = $g DisplayName = $null Description = $null SID = $null #Error = $_.Exception.Message } } } return $out } } process { foreach ($server in $Computername) { try { if (!($TargetLocalGroups)) { if ($Credential) { Invoke-Command -ComputerName $server -Credential $Credential -ScriptBlock $sbListAll -ErrorAction Stop } else { Invoke-Command -ComputerName $server -ScriptBlock $sbListAll -ErrorAction Stop } } else { if ($Credential) { Invoke-Command -ComputerName $server -Credential $Credential -ArgumentList ($TargetLocalGroups) -ScriptBlock $sbByName -ErrorAction Stop } else { Invoke-Command -ComputerName $server -ArgumentList ($TargetLocalGroups) -ScriptBlock $sbByName -ErrorAction Stop } } } catch { Write-Warning "Error gathering local group info for system: $server - $($_.Exception.Message)" } } } } function Get-RemoteLocalGroupMembers { <# .SYNOPSIS Retrieves local group members from one or more remote Windows computers. .DESCRIPTION Get-RemoteLocalGroupMembers queries specified local groups on remote systems using PowerShell Remoting (Invoke-Command). You may select from common preset local groups (tab-complete/validation) and/or supply custom group names. The function normalizes inputs, defaults to the 'Administrators' group when none are provided, and returns structured PSCustomObjects that include per-machine, per-group results and any retrieval errors. .PARAMETER Computername One or more target computer hostnames (or IPs). Required. Accepts pipeline input. .PARAMETER LocalGroupPreset Optional. One or more preset local group names (validated). Examples: Administrators, Remote Desktop Users, Power Users, Backup Operators. Use this parameter for convenience and tab-completion. .PARAMETER LocalGroup Optional. One or more custom local group names. Can be combined with -LocalGroupPreset. .PARAMETER Credential Optional. PSCredential used for remote connections if the current account does not have access to the targets. .OUTPUTS PSCustomObject with properties: - ComputerName - Group - Name (member display name) - ObjectClass (User / Group / SID type) - SID - Error (null when successful, message string on failure) .EXAMPLE # Query Administrators on two servers using current credentials Get-RemoteLocalGroupMembers -Computername srv01,srv02 -LocalGroupPreset Administrators .EXAMPLE # Query multiple preset groups and a custom group using explicit credential $cred = Get-Credential Get-RemoteLocalGroupMembers -Computername srv01 -LocalGroupPreset 'Remote Desktop Users','Event Log Readers' -LocalGroup 'My Custom Group' -Credential $cred .NOTES - Requires PowerShell Remoting enabled on targets and appropriate rights to query local groups. - Uses Get-LocalGroupMember on the remote host; older OS versions may not populate all properties (PrincipalSource supported on Win10/Server2016+). - Returns per-group error information rather than terminating the entire run for a single failure. .LINK Author: Luis Carrillo GitHub: https://www.github.com/LuisCarrilloTech #> [CmdletBinding()] param ( [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Target computer name(s)')] [ValidateNotNullOrEmpty()] [String[]]$Computername, [Parameter( Mandatory = $false, HelpMessage = 'Select one or more common local groups (preset)')] [ValidateSet( 'Administrators', 'Remote Desktop Users', 'Power Users', 'Backup Operators', 'Remote Management Users', 'Event Log Readers', 'Print Operators', 'Guests', IgnoreCase = $true )] [String[]]$LocalGroupPreset, [Parameter( Mandatory = $false, HelpMessage = 'Provide custom local group names (can be used with preset)')] [String[]]$LocalGroup, [Parameter( Mandatory = $false, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Credentials for remote access')] [PSCredential]$Credential ) # Merge presets + custom, normalize and default to Administrators $TargetLocalGroups = @() if ($LocalGroupPreset) { $TargetLocalGroups += $LocalGroupPreset } if ($LocalGroup) { $TargetLocalGroups += $LocalGroup } $TargetLocalGroups = $TargetLocalGroups | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' } | Select-Object -Unique if (-not $TargetLocalGroups -or $TargetLocalGroups.Count -eq 0) { $TargetLocalGroups = @('Administrators') } # Remote scriptblock accepts groups as argument and returns standardized objects $sb = { param($Groups) $out = @() foreach ($g in $Groups) { try { $members = Get-LocalGroupMember -Group $g -ErrorAction Stop foreach ($m in $members) { $out += [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME Group = $g Name = $m.Name ObjectClass = $m.ObjectClass SID = $m.SID Error = $null } } } catch { $out += [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME Group = $g Name = $null ObjectClass = $null SID = $null Error = $_.Exception.Message } } } return $out } foreach ($server in $Computername) { try { if ($Credential) { $results = Invoke-Command -ComputerName $server -ScriptBlock $sb -ArgumentList ($TargetLocalGroups) -Credential $Credential -ErrorAction Stop } else { $results = Invoke-Command -ComputerName $server -ScriptBlock $sb -ArgumentList ($TargetLocalGroups) -ErrorAction Stop } # Output results as table or objects $results | Select-Object ComputerName, Group, Name, ObjectClass, SID, Error | Format-Table -AutoSize } catch { Write-Warning "Error gathering local group info for system: $server - $($_.Exception.Message)" } } } function Add-RemoteLocalGroupMembers { <# .SYNOPSIS Adds one or more members to local groups on remote Windows computers. .DESCRIPTION Add-RemoteLocalGroupMembers adds specified account(s) to one or more local groups on remote systems using PowerShell Remoting (Invoke-Command). You may select from common preset local groups (tab-complete/validation) and/or supply custom group names. The function normalizes inputs, defaults to the 'Administrators' group when none are provided, and returns PSCustomObjects that include per-machine, per-group results and any errors. .PARAMETER ComputerName One or more target computer hostnames (or IPs). Accepts pipeline input. .PARAMETER LocalGroupPreset Optional. One or more preset local group names (validated). Examples: Administrators, Remote Desktop Users, Power Users, Backup Operators, Remote Management Users, Event Log Readers, Print Operators, Guests. Use this parameter for convenience and tab-completion. .PARAMETER LocalGroup Optional. One or more custom local group names. Can be combined with -LocalGroupPreset. .PARAMETER Members One or more user/group accounts to add to the target local groups. Provide DOMAIN\User or local user names as required. .PARAMETER Credential Optional. PSCredential used for remote connections if the current account does not have rights on the targets. .OUTPUTS PSCustomObject with properties: - ComputerName - Group - Member - Result (Success / Failed) - Error (null when successful, message string on failure) .EXAMPLE # Add DOMAIN\User1 and DOMAIN\User2 to Administrators on two servers $cred = Get-Credential Add-RemoteLocalGroupMembers -ComputerName srv01,srv02 -LocalGroupPreset Administrators -Members 'CORP\User1','CORP\User2' -Credential $cred .EXAMPLE # Add a custom group on a single server using current creds Add-RemoteLocalGroupMembers -ComputerName srv03 -LocalGroup 'My App Admins' -Members 'svc-app' .NOTES - Requires PowerShell Remoting enabled on targets and appropriate rights to modify local groups. - Uses Add-LocalGroupMember on the remote host; account names must be valid on the target (or domain-qualified). .LINK Author: Luis Carrillo GitHub: https://www.github.com/LuisCarrilloTech #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)] [ValidateNotNullOrEmpty()] [String[]]$ComputerName, [Parameter(Mandatory = $false, HelpMessage = 'Select one or more common local groups (preset)')] [ValidateSet( 'Administrators', 'Remote Desktop Users', 'Power Users', 'Backup Operators', 'Remote Management Users', 'Event Log Readers', 'Print Operators', 'Guests', IgnoreCase = $true )] [String[]]$LocalGroupPreset, [Parameter(Mandatory = $false, HelpMessage = 'Provide custom local group names (can be used with preset)')] [String[]]$LocalGroup, [Parameter(Mandatory = $true, HelpMessage = 'One or more members to add to the group(s)')] [String[]]$Members, [Parameter(Mandatory = $false, HelpMessage = 'Credential for remote session (optional)')] [PSCredential]$Credential ) begin { # Build final target group list (presets + custom), normalize and default to Administrators $TargetLocalGroups = @() if ($LocalGroupPreset) { $TargetLocalGroups += $LocalGroupPreset } if ($LocalGroup) { $TargetLocalGroups += $LocalGroup } $TargetLocalGroups = $TargetLocalGroups | ForEach-Object { $_.ToString().Trim() } | Where-Object { $_ -ne '' } | Select-Object -Unique if (-not $TargetLocalGroups -or $TargetLocalGroups.Count -eq 0) { $TargetLocalGroups = @('Administrators') } # remote scriptblock: accepts Groups[] and Members[] and returns structured results $sb = { param($Groups, $Members) $out = @() foreach ($g in $Groups) { foreach ($m in $Members) { try { # Ensure group exists $grp = Get-LocalGroup -Name $g -ErrorAction Stop Add-LocalGroupMember -Group $g -Member $m -ErrorAction Stop $out += [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME Group = $g Member = $m Result = 'Success' Error = $null } } catch { $out += [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME Group = $g Member = $m Result = 'Failed' Error = $_.Exception.Message } } } } return $out } } process { foreach ($server in $ComputerName) { try { if ($Credential) { $res = Invoke-Command -ComputerName $server -ScriptBlock $sb -ArgumentList ($TargetLocalGroups, $Members) -Credential $Credential -ErrorAction Stop } else { $res = Invoke-Command -ComputerName $server -ScriptBlock $sb -ArgumentList ($TargetLocalGroups, $Members) -ErrorAction Stop } # Emit results objects to pipeline $res | Select-Object ComputerName, Group, Member, Result, Error } catch { # Emit error object for this server [PSCustomObject]@{ ComputerName = $server Group = $null Member = $null Result = 'Failed' Error = $_.Exception.Message } } } } } function Remove-RemoteLocalGroupMembers { <# .SYNOPSIS Removes one or more members from local groups on remote Windows computers. .DESCRIPTION Remove-RemoteLocalGroupMembers removes specified account(s) from one or more local groups on remote systems using PowerShell Remoting (Invoke-Command). You may select from common preset local groups (tab-complete/validation) and/or supply custom group names. The function normalizes inputs, defaults to the 'Administrators' group when none are provided, and returns PSCustomObjects that include per-machine, per-group results and any errors. .PARAMETER ComputerName One or more target computer hostnames (or IPs). Accepts pipeline input. .PARAMETER LocalGroupPreset Optional. One or more preset local group names (validated). Examples: Administrators, Remote Desktop Users, Power Users, Backup Operators, Remote Management Users, Event Log Readers, Print Operators, Guests. Use this parameter for convenience and tab-completion. .PARAMETER LocalGroup Optional. One or more custom local group names. Can be combined with -LocalGroupPreset. .PARAMETER Members One or more user/group accounts to remove from the target local groups. Provide DOMAIN\User or local user names as required. .PARAMETER Credential Optional. PSCredential used for remote connections if the current account does not have rights on the targets. .OUTPUTS PSCustomObject with properties: - ComputerName - Group - Member - Result (Success / Failed) - Error (null when successful, message string on failure) .EXAMPLE # Remove DOMAIN\User1 and DOMAIN\User2 from Administrators on two servers $cred = Get-Credential Remove-RemoteLocalGroupMembers -ComputerName srv01,srv02 -LocalGroupPreset Administrators -Members 'CORP\User1','CORP\User2' -Credential $cred .EXAMPLE # Remove a custom group member on a single server using current creds Remove-RemoteLocalGroupMembers -ComputerName srv03 -LocalGroup 'My App Admins' -Members 'svc-app' .NOTES - Requires PowerShell Remoting enabled on targets and appropriate rights to modify local groups. - Uses Remove-LocalGroupMember on the remote host; account names must be valid on the target (or domain-qualified). .LINK Author: Luis Carrillo GitHub: https://www.github.com/LuisCarrilloTech #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)] [ValidateNotNullOrEmpty()] [String[]]$ComputerName, [Parameter(Mandatory = $false, HelpMessage = 'Select one or more common local groups (preset)')] [ValidateSet( 'Administrators', 'Remote Desktop Users', 'Power Users', 'Backup Operators', 'Remote Management Users', 'Event Log Readers', 'Print Operators', 'Guests', IgnoreCase = $true )] [String[]]$LocalGroupPreset, [Parameter(Mandatory = $false, HelpMessage = 'Provide custom local group names (can be used with preset)')] [String[]]$LocalGroup, [Parameter(Mandatory = $true, HelpMessage = 'One or more members to remove from the group(s)')] [String[]]$Members, [Parameter(Mandatory = $false, HelpMessage = 'Credential for remote session (optional)')] [PSCredential]$Credential ) begin { $TargetLocalGroups = @() if ($LocalGroupPreset) { $TargetLocalGroups += $LocalGroupPreset } if ($LocalGroup) { $TargetLocalGroups += $LocalGroup } $TargetLocalGroups = $TargetLocalGroups | ForEach-Object { $_.ToString().Trim() } | Where-Object { $_ -ne '' } | Select-Object -Unique if (-not $TargetLocalGroups -or $TargetLocalGroups.Count -eq 0) { $TargetLocalGroups = @('Administrators') } $sb = { param($Groups, $Members) $out = @() foreach ($g in $Groups) { foreach ($m in $Members) { try { $grp = Get-LocalGroup -Name $g -ErrorAction Stop Remove-LocalGroupMember -Group $g -Member $m -ErrorAction Stop $out += [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME Group = $g Member = $m Result = 'Success' Error = $null } } catch { $out += [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME Group = $g Member = $m Result = 'Failed' Error = $_.Exception.Message } } } } return $out } } process { foreach ($server in $ComputerName) { try { if ($Credential) { $res = Invoke-Command -ComputerName $server -ScriptBlock $sb -ArgumentList ($TargetLocalGroups, $Members) -Credential $Credential -ErrorAction Stop } else { $res = Invoke-Command -ComputerName $server -ScriptBlock $sb -ArgumentList ($TargetLocalGroups, $Members) -ErrorAction Stop } $res | Select-Object ComputerName, Group, Member, Result, Error } catch { [PSCustomObject]@{ ComputerName = $server Group = $null Member = $null Result = 'Failed' Error = $_.Exception.Message } } } } } |