Get-ADComputer save results as string array? - powershell

What is the output format of Get-ADComputer? I'm trying to do something like this to take an inventory.
[string[]]$server_list = Get-ADComputer -Filter * -Property Name # Select-Object Name
However, when I use $server_list in a foreach, I see the object curly brackets like so
foreach ($machine_name in $server_list) {
"processing : $machine_name";
}
output:
#{Name=some-machine-name-123-here}
I just need the actual name value, how do i get that?

The -Property Name parameter is unnecessary, as Get-ADComputer always retrieves the Name property. (This doesn't select only the Name property, as you seem to have thought.)
Rather than -Property Name, append | Select-Object -ExpandProperty Name to your Get-ADComputer command line.

So, my query returned a different result. Thus you might need to do a little work on this.
Basically, -Property says that you want an object with a certain field. Select does more or less the same thing.
If you want to keep your existing solution, expand the property instead of selecting it. This is the best way to do that:
[string[]]$server_list = (Get-ADComputer -Filter * -Property Name).Name
You returned #{} which is powershell's way of representing an object inside a string. In this case, an object that contains properties about your ADComputers, of which you chose to only include "Name". If you included additional properties, you would see a larger comma separated list of type=value.
You can actually remove -Property Name, however this will take longer to run, since you're filtering on the right. (Gathering a lot of data and THEN filtering it to only Name.)

Related

Issues getting get-adcomputer to recognize variable in filter

Below is the code I am working with. I have verified that the initial import-csv is working as it should be, and if I change out the variable object for a concrete object, the script works as it should. It just seems to not recognize/use the variable the way that it should.
$CSVOutput = "C:\temp\output.csv"
$Output = foreach($u in $userlastname)
{
Get-ADComputer -Filter {Description -Like '*$u*'} -properties Description | Select Name, Description
}
$Output | Export-Csv $CSVOutput
If I replace the $u in the filter with one of the values from the $userlastname variable, it works, but it just runs the search with the set value as many times as it runs the foreach loop. I am expecting to see several different computer objects that have the different values from $userlastname in their description. Currently it returns nothing, as if it found no values that matched in the description field.
While it’s technically possible to use a scriptblock as a filter in the ADCommands, it isn’t recommended - use a string instead:
Get-ADComputer -Filter "Description -like '*$($u.name)*'" -Properties ...
Using a string will solve your variable substitution issue.
ETA: Comments indicated that you were getting #{Name=User} as the expansion for $u in the filter expression. This is because $u was a structured [PSCustomObject], and you were looking for a single field from that object. The easiest way to get the value of the desired field of the object is simply to use the PowerShell evaluation construct, as given in the edited answer.

Powershell Get-ADGroupMember does not return list

I am trying to utilize PowerShell to audit all of our security group members in AD. I have been trying to get Get-ADGroupMember to work but anytime I try it, it returns the message 'Cannot find an object with identity 'groupName' under: 'DC=xxxx,DC=xxxx,DC=xxxx,DC=xxxx'.
Ive tried the following with no luck:
$groupNames = 'groupName1' , 'groupName2' , 'groupName3'
foreach ($group in $groupNames) {
Get-AdGroupMember -Identity $group
}
Has anyone successfully compiled a list of group members in security groups from AD and exported them into a .CSV?
There are few things to consider when querying AD groups using the Get-AdGroup* commands.
The -Identity parameter only accepts values that match an object's Guid, ObjectSid, DistinguishedName, or SamAccountName. If your input is something other than one of those attribute values, you will either need to run another command to retrieve the proper data or change your list.
-Identity only accepts a single value, which means if you want to supply a list of values, you need to loop through them.
Get-AdGroupMember does not output as many attribute/value pairs as Get-AdUser. You cannot force it to output more attributes than it does. It does not have a -Properties parameter like Get-AdUser. Sometimes it requires using both commands to get all of the required data.
You can send Get-Ad* output to CSV using Export-Csv. If you do not use any property filtering like with Select-Object, the returned property names will be the columns of the CSV. The associated values of the properties will appear in rows with each row representing one returned object. You can choose to either send the entire results of the command once to the CSV or each time the command runs using Export-Csv -Append.
Use Select-Object to only output properties you care about. Select-Object Property outputs a custom object that includes only the property Property and the value(s) of Property for each object returned. If you only want to return the value rather than a custom object, you can use Select-Object -Expand Property.
Get-Content can be used to read a file. If the file contains only a list of values, perhaps SamAccountName values, you can use Get-Content file.txt to retrieve that list. The list will be an array that can be looped through.
Since Get-AdUser can be verbose, it is wise to use the -Properties parameter to explicitly list any extra properties beyond the default set you want to return. -Properties * will return all properties, but that is not best practice.
Given the above considerations, I would do the following:
$groupNames = 'groupName1' , 'groupName2' , 'groupName3'
# Alternatively, if you have a file (file.txt) with your group names listed as one group per line
$groupNames = Get-Content file.txt
# The Foreach-Object section is only needed if $groupNames does not contain a valid -Identity value
# The Filter below uses Name attribute as an example because it assumes $groupNames contains Name attribute values. If it contains another attribute, update the filter accordingly.
$SamAccountNames = $groupNames | Foreach-Object {
Get-AdGroup -Filter "Name -eq '$_'" | Select-Object -Expand SamAccountName
}
# Storing the loop output into a variable is efficient provided you have enough memory for the operation.
# Alternatively, you can just pipe the `Get-AdGroupMember` into `Export-Csv -Append` but that could be a lot of writes!
$output = foreach ($group in $SamAccountNames) {
Get-AdGroupMember -Identity $group # You can use Select-Object here for specific properties
}
$output | Export-Csv -Path output.csv -NoTypeInformation

Find missing prefix for computer name

I am trying to write a script that will automatically find the full asset tag based on the ID of the computer.
For example:
The PC ID is: PC0001
$computerID = PC0001;
But the full asset tag that I need is: WKSPC0001
But these asset tags might have different prefixes, for example DSTPC0002, TBLPC0003 etc. But they all have common pattern: Prefix+PC+ID (the ID is unique and there is no repetition).
I am trying to figure out how to write a query for that in PowerShell but I cant figure it out. I've tried:
$current = Get-ADComputer -Filter {Name -like "*$computerId.text"} |
Select -Property Name
But I was having issues to get it to work.
What am I doing wrong?
A few observations.
You want $computerId to be a string, so $computerID = "PC0001";
The filter expression for Get-ADComputer is expected to be a string also, using curly braces here is wrong. So Get-ADComputer -Filter "..."
Powershell can expand variable values in strings, but it only does that in double-quoted strings. "Name -like '$variable'" will work, but 'Name -like "$variable"' won't.
There is no .text in your $computerId variable. It's a plain string.
Knowing that, try:
$current = Get-ADComputer -Filter "Name -like '*$computerId'"
Other notes
Don't do ... | Select Name unless you really must. Storing the computer object itself will be more versatile. You can do $current.Name when you need it anytime.
Querying the AD with a filter that begins with a wildcard is slow. Try to avoid.
If you have a fixed number of possible prefixes, an LDAP filter like the following will be much faster:
$current = Get-ADComputer -LDAPFilter "(|(cn=WKS$computerId)(cn=DST$computerId)(cn=TBL$computerId))"

-contains operator failing when it should not be

I am writing a script to create new AD users and doing a test to make sure an existing displayname is not found because New-ADUser will fail if one is found. Can someone help me understand why I might never get a true outcome from the following array list?
$ExistingDNs= Get-ADUser -SearchBase 'OU=whateverOU' -Filter * -Property displayname | select displayname | Out-string
My goal is to load up all the existing displaynames in an OU and then compare this with a method in which I read a CSV file to create a displayname, but I can't seem to get it to return as true.
If ($ExistingDNs.DisplayName -contains $DisplayName)
I was told this should work, but when I try looking at the array it is empty? Only $ExistingDSs shows me the list visually in ISE, where I can see clearly that a name exists that is the same in my CSV file, but the match is never found and never comes back as true even though both are string values I believe.
I'm sure it is because you are using Out-String which breaks the object array that select displayname would have created. Currently your $ExistingDNs is a newline delimited string when you really want a string array.
$ExistingDNs = Get-ADUser -SearchBase 'OU=whateverOU' -Filter * -Property displayname | select -ExpandProperty displayname
Also we use -ExpandProperty so you just end up with an array of strings. That way your conditional statement can be reduced to...
If ($ExistingDNs -contains $DisplayName)

How to append string literals to properties returned from a Select-Object command

How do you concatenate a string literal and parameter in a Select-Object.
For Example I have:
Get-AdUser -filter * | Select-Object 'sip'+SamAccountName,Name, Email, etc
Basically I want to return the property SamAccountName from the AdUser with the string literal sip before it.
I tried everything I can think of.
Thanks!
Edit: added parameters and multiple users
You can specify an expression in a script block to do this. Like this:
Get-AdUser foo#bar.com | select-object {"sip"+$_.SamAccountName}
Though if you do it this way, the name of resultant property looks a bit weird. To specify the property name as well, enclose the script block as part of a hashtable that specifies the name of the new property as well as the scriptblock expression to generate it. It would look like this:
Get-AdUser foo#bar.com | select-object #{name="SamAccountName"; expression={"sip"+$_.SamAccountName}}
You don't need to use Select-Object, because you're not trying to create a new object with specific properties; you're trying to select a single property (SamAccountName) and manipulate it.
"sip" + (Get-ADUser foo#bar.com).SamAccountName