3

I can use Add-LocalGroupMember to add a user to the local group:

Add-LocalGroupMember -Group  "Administrators" -Member  "foobar"

but it isn't idempotent. If the user already exists then you get this error

Add-LocalGroupMember : foobar is already a member of group Administrators

What is the best way to make this command not error when you want to run this command repeatedly?

The reason is this is part of an Octopus deploy and I don't want to use a prebaked step for something so simple.

fiat
  • 797
  • 11
  • 16
  • 2
    Guessing `Add-LocalGroupMember -Group $group -Member $member -ErrorAction SilentlyContinue` is not quite idempotent either... – jscott Oct 17 '17 at 00:16
  • `-ErrorAction SilentlyContinue` works great! I'd consider it idempotent. You should make this an answer and I'll accept that – fiat Oct 18 '17 at 00:38
  • 1
    The problem with `SilentlyContinue` is that it will suppress _any_ errors that the cmdlet produces. This may not be a desired side effect. – jscott Oct 18 '17 at 10:30

3 Answers3

6

You can simplify your wrapper down to a try/catch block. This example only catches when the member already exists, so you can still evaluate and deal with other errors.

try {
    Add-LocalGroupMember -Group $group -Member $member -ErrorAction Stop
} catch [Microsoft.PowerShell.Commands.MemberExistsException] {
    Write-Warning "$member already in $group"
}
jscott
  • 24,484
  • 8
  • 79
  • 100
1

I came up with this function to wrap it

function Add-LocalGroupMemberSilent($groupName, $username)
{
    $existingMember = Get-LocalGroupMember -Name $groupName | Where {$_.Name -eq "$username"}

    if ($existingMember)
    {
        Write-Host "'$username' is already a member of '$groupName'"
    }
    else
    {
        Write-Host "Adding '$username' to '$groupName'"
        Add-LocalGroupMember -Group "$groupName" -Member "$username"
    }
}

but I feel there might be a more elegant way that eludes me

fiat
  • 797
  • 11
  • 16
1

I think you might be looking for 'erroractionpreference', this article explains through a few examples of how it works.

https://blogs.technet.microsoft.com/heyscriptingguy/2010/03/08/hey-scripting-guy-how-can-i-use-erroractionpreference-to-control-cmdlet-handling-of-errors/

Given the other answer, if your script is larger than this function and you need to continue troubleshooting, then you'd need to wrap this bit of code by setting it at the beginning and setting it back to 'continue' after you are done processing. This will suppress non-terminating errors like that so they are not printed to your host.

Kyp
  • 303
  • 1
  • 9
  • This was on the right track but I like @jscott's targeted `-ErrorAction` – fiat Oct 18 '17 at 00:41
  • Yep for more specific single errors that's much better. You can use it to activate your try/catch. I've done this by changing my error action to 'STOP' so it is guaranteed to call my catch block, but jscott's is more elegant, it's making a call to the .NET class for the error handling and only suppressing that exact error (or doing whatever you wrote in the catch block) - clarifying, in the past i've simply assumed any error, rather than specifying it, that's what I was trying to say. :) – Kyp Oct 18 '17 at 02:04