PS Get/Set-ADGroup issues accepting variable/object input - powershell

I'm creating Distribution Lists, and trying to populate the AD Description field. Set-ADGroup appears to be the correct cmdlet for this task, however I'm having trouble using it inside a simple script, or using a variable to pass along the required parameters or objects.
This works:
Get-ADGroup -Identity "CN=My Group Name,OU=Distribution,OU=Groups,DC=subdomain,DC=domain,DC=tld"
But this doesn't:
$GroupDn = Get-Group -Identity "My Group Name" | Select-Object DistinguishedName
Get-ADGroup -Identity $GroupDn
And fails with this error:
get-adgroup : Cannot find an object with identity: '$GroupDn' under:
'DC=subdomain,DC=domain,DC=tld'. At line:1 char:1
+ get-adgroup -Identity '$GroupDn'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: ($GroupDn:ADGroup) [Get-ADGroup], ADIdentityNotFoundException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveDirectory.Management.Commands.GetADGroup
$GroupDn is storing this object:
PS D:\Scripts> $groupdn
DistinguishedName
-----------------
CN=My Group Name,OU=Distribution,OU=Groups,DC=subdomain,DC=domain,DC=tld
I assumed this is because Get-ADGroup is expecting string input, but I also know this is Powershell and objects and all that is the magic, the secret sauce, but my roux appears to be lumpy and I'm missing some key point.
So, is string input what I should be handling here? If so, what's the right way to get that DN into a string?
Or what part of the object secret sauce am I missing?

As requested.
The problem with your code is that it gets the distinghuished name as PSCustomObject with a property called 'DistinghuishedName', where you really want to get this property as String.
If you change that to (using Exchange Get-Group):
$GroupDn = Get-Group -Identity "My Group Name" | Select-Object -ExpandProperty DistinguishedName
or (using ActiveDirectory Get-ADGroup):
$GroupDn = Get-ADGroup -Identity "My Group Name" | Select-Object -ExpandProperty DistinguishedName
The variable $GroupDn will then contain just the DistinghuishedName of the group as string that can be used as -Identity parameter for other AD commands.
Get-ADGroup can also be used in another type of syntax, namely by passing an object through the pipeline. This object needs to have at least one of these properties: DistinguishedName, GUID, SID or SamAccountName.
$GroupObject = Get-Group -Identity "My Group Name"
$GroupObject | Get-ADGroup
Using this syntax, you do not need to set the Identity parameter.

I was also able to pipe like this:
Get-Group | % { Get-ADGroup -Identity $_.DistinguishedName }
It still seems not to play well with different domains though, but this would definitely work for groups in the same domain. The key as to why something like Get-Group | Select DistinguishedName or Get-Group | Get-ADGroup doesn't work is to use the Get-Member cmdlet. So running something like:
Get-Group | Get-Member
Get-Group | Select DistinguishedName | Get-Member
Should return something like this:
TypeName: Deserialized.Microsoft.Exchange.Data.Directory.Management.WindowsGroup
TypeName: Selected.System.Management.Automation.PSCustomObject
And as you can see from there, that is not what would be accepted from a pipeline into the Get-ADGroup cmdlet.

Related

Failing to iterate over AdComputer names to get description

I am using ActiveDirectory and Powershell to get the description of computers in the AD Group
However, when I try to get batch output, I get InvalidArgument error in powershell
When I use a single line:
Get-AdComputer -Filter * -Identity **COMPUTERNAME **-Properties * | Select-Object name, description
I get the correct response:
Name Description
---- -----------
COMPUTERNAME Computer description
However, when I use the this code to get a batch of results:
$UL = Get-ADGroupMember -identity "Groupname"| Select-Object name
Foreach ($i in $UL.Name)
{
$i.ToString()
Write-Host $i.GetType()
Get-AdComputer -Filter * -Identity "$i" -Properties * | Select-Object name, description
}
I keep getting this error:
Get-ADComputer : Parameter set cannot be resolved using the specified named parameters.
At C:\apps\ActiveDirectory_UserList.ps1:6 char:1
+ Get-AdComputer -Filter * -Identity "$i" -Properties * | Select-Object ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-ADComputer], ParameterBindingException
+ FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.ActiveDirectory.Management.Commands.GetADComputer
As commented by Abraham Zinala, you cannot use both -Filter and -Identity together as these parameter sets rule eachother out giving you the error message
Parameter set cannot be resolved using the specified named parameters.
Next, Get-ADGroupMember will not just return computer objects,
but also users and other groups can be members of one particular group.
Therefore, if you want to get output for computer objects only, you will need to filter out the other object types.
Luckily, each group member has a property called objectClass. This is a string containing either 'user', 'computer' or 'group',
so it is realy quite easy to check on that:
# get all members of the group, filter with a Where-Object clause to receive only computer objects
$members = Get-ADGroupMember -Identity "Groupname" | Where-Object {$_.objectClass -eq 'computer'}
foreach ($computer in $members) {
$computer | Get-ADComputer -Properties Description | Select-Object Name, Description
}
By default, Get-ADComputer returns objects with these properties:
DistinguishedName, DNSHostName, Enabled, Name, ObjectClass, ObjectGUID, SamAccountName, SID, UserPrincipalName, so in this case you only have to ask for the extra property Description

foreach loop gives error CategoryInfo : InvalidData: (:) [Get-ADUser], ParameterBindingValidationException

I am trying to run a cmdlet on each element of a list. but i am getting the error ObjectNotFound: (*#{samAccountName=my_ad_username}*:ADUser) [Get-ADUser], ADIdentityNotFoundException for each element of my list.
Bellow is cmdlet
$users = Get-ADUser -Filter "*" -SearchBase "OU=Europe,DC=myDC,DC=com" | select samAccountName
$fr_all_grp_assigned_to_different_users = Foreach ($user in $users){
#Get-AdUser $user
}
Result
> Get-ADUser : Cannot validate argument on parameter 'Identity'. The
> Identity property on the argument is null or empty. At line:6 char:20
> + Get-aduser $user
> + ~~~~~
> + CategoryInfo : InvalidData: (:) [Get-ADUser], ParameterBindingValidationException
> + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADUser
> Get-ADUser : Cannot validate argument on parameter 'Identity'. The
> Identity property on the argument is null or empty. At line:6 char:20
> + Get-aduser $user
Line 6 refers to #Get-AdUser $user
Can anyone help ?
Inside of your loop, you need to provide the SamAccountName value to the -Identity parameter of Get-ADUser.
Get-ADUser -Identity $user.SamAccountName
Explanation:
You can execute Get-ADUser by providing values manually to parameters or piping objects into the command and let advanced parameter assignment dynamically map values to parameters. Some parameters are positional in that you don't need to specify the parameter name when running the command with a value(s). These features/concepts exists across most PowerShell commands.
In the case of Get-ADUser Value, Value is automatically mapped to parameter -Identity. -Identity expects one of the following values:
A distinguished name
A GUID (objectGUID)
A security identifier (objectSid)
A SAM account name (sAMAccountName)
Get-ADUser has a convenient feature where if you pass it a Microsoft.ActiveDirectory.Management.ADUser object type (returned from a directory server) through a pipe or to the -Identity parameter, it will automatically perform a search based on the provided values. If you provide it any other object type, it will not automatically select property values to pass to -Identity. Piping to Select SamAccountName returns a PSCustomObject rather than an ADUser object and then you lose your convenience.
Once you are dealing with objects that are not ADUser, you must provide -Identity with the actual value you want to query. In your case, that leaves you with two options.
Option 1: Select only SamAccountName values in your initial query
With this option, you can make use of the -ExpandProperty or -Expand parameter of Select-Object to return only the values of the target property.
$users = Get-ADUser -Filter * -SearchBase "OU=Europe,DC=myDC,DC=com" |
Select-Object -ExpandProperty SamAccountName
$fr_all_grp_assigned_to_different_users = Foreach ($user in $users) {
Get-ADUser $user
}
Option 2: Use Member Access operator (.) to directly access the SamAccountName value
With this option you can use the syntax object.Property to retrieve the Property value.
# Using the singular object.Property ($user.SamAccountName)
$users = Get-ADUser -Filter * -SearchBase "OU=Europe,DC=myDC,DC=com" |
Select-Object SamAccountName
$fr_all_grp_assigned_to_different_users = Foreach ($user in $users) {
Get-ADUser $user.SamAccountName
}
Starting with PowerShell v3, you can use the same syntax on a collection to return a collection of values (collection.Property).
# Using collection.Property ($users.SamAccountName)
# $user contains only a SamAccountName value here
$users = Get-ADUser -Filter * -SearchBase "OU=Europe,DC=myDC,DC=com" |
Select-Object -ExpandProperty SamAccountName
$fr_all_grp_assigned_to_different_users = Foreach ($user in $users.SamAccountName) {
Get-ADUser $user
}

How to filter Get-ADComputer output

My Get-ADComputer script gives too much information. I would like to shorten it out a little.
$Computer = Read-Host -Prompt 'Input computer name'
$ManagedBy = Get-ADComputer $Computer -Properties ManagedBy |
foreach { $_.ManagedBy }
Write-Output $ManagedBy
When I tried to run my scrip it gives this to output
CN=Last Name First Name ,OU=XX ,OU=XXX ,OU=XXX ,DC=XXX,DC=XXX
I would like to get only CN in the output (First name and Las Name).
Your code returns the distinguished name of the computer's manager. You can use that DN to query the AD user object and obtain the desired properties from that (like FullName, or DisplayName, or the individual values FirstName and LastName).
Get-ADComputer $Computer -Properties ManagedBy |
Select-Object -Expand ManagedBy |
Get-ADUser -Property FullName |
Select-Object -Expand FullName
Firstly have you looked at the objects properties?
These Properties are auto assigned to the variable, when created.
You can see them with:
$ManagedBy | Get-Member
You may well find that $ManagedBy.Name will give exactly what you want.
Further reading for you: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-member?view=powershell-6

Get-ADGroup with -recursive is not working?

I am using get-adgroupmember command to fetch all the users in an AD group. -recursive is helping me fetch members from child groups if any in the parent group as well.
However, get-adgroupmember has an upper limit of 5000 entries only.
To tackle this if i use:
Get-ADGroup -Identity "DEPT_120_SA" -server "A" -Properties * | select-object -expandproperty members |get-aduser
this doesnt work as my Parent AD has child ADs and -recursive is not accepted by get-adgroup.
Error:
Get-ADGroup : A parameter cannot be found that matches parameter name
'recursive'. At line:2 char:79
+ Get-ADGroup -Identity "DEPT_120_SA" -server "mhf.mhc" -Properties * -recursive <<<< | select-object -expandproperty members
+ CategoryInfo : InvalidArgument: (:) [Get-ADGroup], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.ActiveDirectory.Management.Commands.GetADGroup
my aim is to display username and their mail iDS and this works for me:
Get-ADGroupMember -server $domain -identity $s -Recursive -ErrorAction Stop | Get-AdUser -Properties mail -ErrorAction Stop | select sAmAccountName, Mail
Any workaround ? (I am willing to write a recursive function to fetch large groups, but there must be a shorter and direct way)
The 5000 limit applies only to Get-ADGroupMembers not Get-ADUsers, so we can use the LDAP_MATCHING_RULE_IN_CHAIN matching rule (OID 1.2.840.113556.1.4.1941).
For example:
Get-AdUser -LdapFilter "(memberOf:1.2.840.113556.1.4.1941:=cn=group,cn=users,DC=ad,DC=local)"
where cn=group,cn=users,DC=ad,DC=local is the distinguished name of the group you want members for.

PowerShell script to add computers to group that are not part of another group?

I am trying to pull together a PS script to automatically add computers to a security group that are not part of another group.
In this case, add all computers to group_b that are not part of group_a.
This is what I tried..
#get list of computers from group_a
$tpmobjects = Get-ADGroupMember -Identity "group_a" | Select name
#add computers to group_b that are not in group_a
Get-ADComputer -Filter {SamAccountName -notlike $tpmobjects} | Foreach-Object { Add-ADPrincipalGroupMembership -Identity $_.SamAccountName -MemberOf "group_b" }
The error I get is...
Get-ADComputer : Type: 'System.Object[]' is not supported for extended attribute 'SamAccountName'.
At line:2 char:1
+ Get-ADComputer -Filter {SamAccountName -notlike $tpmobjects}...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-ADComputer], ArgumentException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:System.ArgumentException,Microsoft.ActiveDirectory.Management.Commands.GetADComputer
Anyone have a way to do this?
Thanks.
What happens is that Get-ADGroupMember returns multiple objects and the -Filter parameter doesn't support matching against multiple objects.
There are multiple ways around this, but the easiest is to simply filter the output from Get-ADGroupMember with Where-Object:
$Computers = Get-ADGroupMember group_a |Where-Object {$_.objectClass -eq 'computer'}
You also don't need to wrap Add-ADPrincipalGroupMembership in ForEach-Object, it accepts pipeline input, and an ADComputer object can be bound to the -Identity parameter directly without problems:
$Computers |Add-ADPrincipalGroupMembership -MemberOf group_a