Add User to Local Group

2

This function should run on Windows Server 2003 and 2008 R2 Using the command line to execute it line by line is SUCCESSFULL! Execution by script fails.

function addUser2Group([string]$user,[string]$group)
{    
    $cname = gc env:computername
    $objUser = [ADSI]("WinNT://$user")
    $objGroup = [ADSI]("WinNT://$cname/$group,group")  
    $members = $objGroup.PSBase.Invoke('Members')
    $found = $false

    foreach($m in $members)
    {
        if($m.GetType().InvokeMember('Name', 'GetProperty', $null, $m, $null) -eq $user)
        {
            $found = $true
        }
    }

    if(-not $found)
    {
        $objGroup.PSBase.Invoke('Add',$objUser.PSBase.Path)
    }

    $members = $objGroup.PSBase.Invoke('Members')
    $found = $false
    foreach($m in $members)
    {
        if($m.GetType().InvokeMember('Name', 'GetProperty', $null, $m, $null) -eq $user)
        {
            $found = $true
        }
    }

    return $found
}

addUser2Group('MyGlobalMonitoringUser',"SomeDBGroup")

It should add a user to a local group. But it only gives me the following error:

Exception calling "Invoke" with "2" argument(s): "Unknown error (0x80005000)"
+     $members = @($objGroup.PSBase.Invoke <<<< ("Members"))
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException





Edit: the error message that occurs with /add is

The following exception occurred while retrieving member "Add": "Unknown error (0x80005000)"


Code is:

function addUser2Group([string]$user,[string]$group)
{
    $cname = gc env:computername
    try
    {
        ([adsi]"WinNT://$cname/$group,group").Add("WinNT://$cname/$user,user")
    }
    catch
    {
        write2log($_)
        return $false
    }

    return $true
}
powershell
asked on Stack Overflow Dec 18, 2012 by Marco Alka • edited May 3, 2017 by ekad

5 Answers

14

Why go through the pain of reflection when PowerShell will do it for you? Example:

$group = [ADSI]"WinNT://./Power Users,group"
$group.Add("WinNT://SYSTEM,user")

The above adds the SYSTEM local account to the local Power Users group. I am not sure why you are getting the specific error above, you might get it with this abbreviated syntax as well. The particular COM interface that is being used is IADsGroup - reference here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa706021.aspx

Note: Because you are actually consuming COM objects wrapped in .NET objects, it is a good idea to call the Dispose method on any ADSI objects that are created when you are finished with them.

answered on Stack Overflow Jan 10, 2013 by Goyuix
2

Why wouldn't you use net localgroup /add in your script instead of all that nasty looking WMI? PowerShell is a shell, not an operating system :)

answered on Stack Overflow Dec 19, 2012 by x0n • edited Mar 5, 2015 by cmcginty
1

Observations and assumptions

There are a couple of assumptions that are made based on the code.

  1. You only passed ONE parameter object with two values. Use the Param statement
  2. Call the function differently addUser2Group -user 'MyGlobalMonitoringUser' -group "SomeDBGroup"
  3. Validate the parameters passed. They should be checked for empty/null at least.
  4. This would only work if you had the $group variable assigned a value before the script ran.

Based on the fact that the incorrect parameter passing the value of the $group variable remains empty. It then caused the rest of the code to fail always returning the value of $False.


Proposed solution

Recommended Reading: Simplify your PowerShell Script with Parameter Validation

Include the Param "switch" in the function Change the way you call the function.

Here's a copy of the code that works.

function addUser2Group
{   
    # Added the Param Switch 
    Param(
        [string]$user,
        [string]$group
    )

    $cname = gc env:computername
    $objUser = [ADSI]("WinNT://$user")
    $objGroup = [ADSI]("WinNT://$cname/$group,group")
    #$members = $objGroup.Invoke('Members')
    $found = $false

    foreach($m in $members)
    {
        if($m.GetType().InvokeMember('Name', 'GetProperty', $null, $m, $null) -eq $user)
        {
            $found = $true
        }
    }

    if(-not $found)
    {
        $objGroup.PSBase.Invoke('Add',$objUser.PSBase.Path)
    }

    $members = $objGroup.PSBase.Invoke('Members')
    $found = $false
    foreach($m in $members)
    {
        if($m.GetType().InvokeMember('Name', 'GetProperty', $null, $m, $null) -eq $user)
        {
            $found = $true
        }
    }

    return $found
}

addUser2Group -user 'testing' -group "Administrators"
answered on Stack Overflow Mar 1, 2014 by Ethol Palmer • edited Mar 1, 2014 by Ethol Palmer
0

•0x80005000 ("The specified directory service attribute or value does not exist").

Parameter binding or Environmental culprit perhaps?

As for the issue with net localgroup: examine the error message carefully:

The following exception occurred while retrieving member "Add"

Evidentally the /add flag is not being properly set as it is being interpreted as a member name, but since no code is provided, can't say why.

answered on Stack Overflow Jan 10, 2013 by Yevgeniy • edited Jan 10, 2013 by Yevgeniy
0

Just to add a more uptodate approach roughly five years later:

$group = Get-LocalGroup SomeDBGroup
$user = Get-LocalUser MyGlobalMonitoringUser
Add-LocalGroupMember $group $user
answered on Stack Overflow Jun 16, 2018 by TNT

User contributions licensed under CC BY-SA 3.0