Get-ADCompter command returns back null response - powershell

I'm trying to combine a string and an int together to get the output JWang1 but everytime I run this command it keeps returning back null, any help is appreciated, thank you
$pcname = "Jwang"
$number = 1
Get-ADcomputer -filter "name -like '$pcname + $number'" | select -ExpandProperty name
The goal is to get the command to search "JWANG1", but the result keeps coming back null
Alternatively if I do this, I get a search result posted back to me
$pcname = "Jwang1"
Get-ADcomputer -filter "name -like '$pcname'" | select -ExpandProperty name
The difference here is that I am not trying to combine the string and int, but how do I get it to combine and work?

The issue is how string expansion works, and how you're using it. Right now you have:
"name -like '$pcname + $number'"
Once you sub in the values for those variables it reads like this:
"name -like 'JWANG + 1'"
There's several ways you could go about correcting this. The first is to simply remove the + from the string so it reads like this:
"name -like '$pcname$number'"
The second way is to put in a subexpression like this:
"name -like '$($pcname + $number)'"
Or you could combine them before you reference it like:
$pcname = "Jwang"
$number = 1
$combinedname = $pcname + $number
Get-ADcomputer -filter "name -like '$combinedname'" | select -ExpandProperty name

In this case you would need to use the Subexpression operator $(..) to resolve the concatenation operation:
$pcname = "Jwang"
$number = 1
"name -like '$pcname + $number'"
# Interpolates both variables without resolving the concatenation
# Results in: name -like 'Jwang + 1'
"name -like '$($pcname + $number)'"
# Resolves the expression inside `$(..)` before interpolating it
# Results in: name -like 'Jwang1'
As aside, the right operator for your query to Active Directory should be -eq instead of -like since you're not using any wildcard for your query.

Related

Powershell: How to reference the columns in a select

I'm using PowerShell 5.1 to iterate through a list of computers from active directory, and I'm struggling with something that should be simple.
In the code below, I'm selecting the name and description for each computer in a foreach loop. How should I reference the name and description individually inside the loop?
$OU=#('OU=...')
$computers = $OU | foreach {Get-ADComputer -filter {
Name -notlike 'xxx*'
-and Name -notlike 'yyy*'
} -searchbase $_ -Properties description | Select name, description }
foreach ($computer in $computers) {
$computerName = $computer | select -ExpandProperty name
$computerDescription = $computer | select -ExpandProperty description
Write-Host "Host: $computerName [$computerDescription]"
}
I was able to get it to work using select -ExpandProperty , but this seems unnecessarily complicated. The $computer variable holds key/value pairs like this:
#{name=ABCDE12345; description=Kiosk PC [Domain Separated]}
I tried using dot notation $computer.name $computer.description but the dot was ignored and treated as text.
I have tried googling this, but I'm new to PowerShell and not sure how to phrase my question!
I tried using dot notation $computer.name $computer.description but the dot was ignored and treated as text.
String expansion only applies to simple variable references. If you want to dereference properties inside a string expression, you'll need the subexpression operator $():
"Host: $($computer.name) [$($computer.description)]"
PowerShell will now evaluate the subexpressions separately when resolving the string value

Function to generate samaccountname in PowerShell

I am trying to write a PS function that can generate SamAccountName in a specific way, I have found another question here but it is not similar to what i'm trying to do.
I need the SamAccountName to be generated like this:
UNIT + initial_of_firstName + initial_of_lastName
for example employee Jane Doe in unit FLN could have FLNjd as SamAccountName, and the function should check if that ID is taken by another user and if true then SamAccountName should be:
UNIT + initial_of_firstName + first_two_initials_of_lastName such as FLNjdo
and if that is also taken then SamAccountName should be:
UNIT + first_two_initials_of_firstName + first_two_initials_of_lastName such as FLNjado
and if that is also taken then SamAccountName should be:
UNIT + first_two_initials_of_firstName + first_two_initials_of_lastName + 1 such as FLNjado1
and from here it starts adding numbers 2, 3, 4.... as long as the function finds that the ID exists.
I only managed to extract the initials needed:
$first_of_fname = ($_.Fname).Substring(0,1).ToLower()
$first_of_lname = ($_.Lname).Substring(0,1).ToLower()
$FirstandSecond_of_fname = ($_.Fname).Substring(0,2).ToLower()
$FirstandSecond_of_lname = ($_.Lname).Substring(0,2).ToLower()
I need now to know how to generate the the SamAccountName in the above form and order.
ANy help will be very much appreciated.
You can do the following:
Function Get-SamAccountName {
Param(
[Parameter(Position=0,ValueFromPipelineByPropertyName)]
$Unit,
[Parameter(Position=1,ValueFromPipelineByPropertyName)]
$First,
[Parameter(Position=2,ValueFromPipelineByPropertyName)]
$Last
)
$fcount = 1
$lcount = 1
$inc = 1
$Sam = "{0}{1}{2}" -f $unit,$first.substring(0,$fcount).ToLower(),$last.substring(0,$lcount++).ToLower()
while (Get-AdUser -Filter "SamAccountName -eq '$Sam'") {
if ($fcount -le 2) {
$Sam = "{0}{1}{2}" -f $unit,$first.substring(0,$fcount++).ToLower(),$last.substring(0,$lcount).ToLower()
} else {
$Sam = "{0}{1}{2}{3}" -f $unit,$first.substring(0,2).ToLower(),$last.substring(0,2).ToLower(),$inc++
}
}
$Sam
}
Usage Option 1: Using Named Parameters
Get-SamAccountName -Unit 'FLN' -First 'Sam' -Last 'Wise'
Usage Option 2: Using positional parameters (unnamed)
Get-SamAccountName 'FLN' 'Sam' 'Wise'
Usage Option 3: Having A Text List Of Units and Names
$users = Get-Content users.txt
$users
FLN,Sam,Wise
HRS,John,Doe
COM,Jane,Doe
$users | ConvertFrom-Csv -Header 'Unit','First','Last' | Foreach {
$_ | Get-SamAccountName
}
The pipe to ConvertFrom-Csv can be skipped here if your file is already a CSV with the proper headers.
Explanation:
The function returns a string that represents an available SamAccountName value.
$fcount is the first name character count that we want to retrieve. $lcount is the last name character count that we want to retrieve. $inc is the number we want to append to the username if needed.
$var++ notation increments the $var value by one after its line is executed. The timing of $fcount++ and $lcount++ allows us to retrieve (1,1),(1,2),(2,2) characters from (first,last) while minimizing code. $inc++ will increment after the current $inc value is retrieved.
-f is the string format operator.
The while loop will only execute if the current created SamAccountName value is found.
Note: The code shortening complexity may or may not be worth it. It does not gain much from a performance perspective, but I do feel code complexity on this level is merely relative.
To take a different approach, instead of multiple if statements, you can use the switch statement "backwards" to find out what is $null or not available, and fall back to the default switch which is the final while iteration loop incrementing the count.
#Get substrings
$first_of_fname = ($_.Fname).Substring(0,1).ToLower()
$first_of_lname = ($_.Lname).Substring(0,1).ToLower()
$FirstandSecond_of_fname = ($_.Fname).Substring(0,2).ToLower()
$FirstandSecond_of_lname = ($_.Lname).Substring(0,2).ToLower()
#create patters to match on
$pattern1 = $UNIT + $first_of_fname + $first_of_lname
$pattern2 = $UNIT + $first_of_fname + $FirstandSecond_of_lname
$pattern3 = $UNIT + $FirstandSecond_of_fname + $FirstandSecond_of_lname
#evaluate what is available
switch($null){
(Get-ADUser -Filter "samAccountName -like '$pattern1'"){
Write-Host "$pattern1 - Free"
break
}
(Get-ADUser -Filter "samAccountName -like '$pattern2'"){
Write-Host "$pattern2 - Free"
break
}
(Get-ADUser -Filter "samAccountName -like '$pattern3'"){
Write-Host "$pattern3 - Free"
break
}
default {
$cnt = 1
while (Get-ADUser -Filter "SamAccountName -like '$pattern3$cnt'") {
$cnt++
}
Write-Host "$pattern3$cnt - Free"
break
}
}

Foreach is not processing each item, tries to process all as one line

I am building a script to pull the mac addresses of a computer, and convert them to GUIDs that are then queried to AD to find a match and retrieve the hostname associate with that guid.
Everything I've read about "Foreach" suggests that the code I am using "SHOULD" work.
$NIC = Get-WMIObject Win32_NetworkAdapterConfiguration | select MacAddress
$NICMacs = $NIC.MacAddress
Foreach ($NICMac in $NICMacs)
{
$MacString = $NICMacs -replace ":", ""
$MactoGUID = "00000000000000000000" + $MacString
$MactoGUID = $MactoGUID -replace " ", ''
$NBG = [GUID]$MactoGUID
$CompDetails = Get-ADComputer -Filter 'netbootGUID -like $NBG' -Properties netBootGUID -Server our.AD.server.ca -Credential $sessionKey
This should process each mac address found, stripping away the: characters and prepending 20 '0s' then convert to GUID format and query AD for a match.
Instead, it takes all the mac addresses found, concatenates them to one line and tries to process with all those numbers. Of course AD rejects it as an incorrect GUID.
If I use the same code with only 1 mac address, it is correctly formatted.
Some of your steps can be combined and thus save intermediate vars using
Select-Object -ExpandProperty MacAddress
.PadLeft() method
As #RobV already pointed out in his comment usage of the wrong var caused the malfunction.
Foreach ($NICMac in (Get-WMIObject Win32_NetworkAdapterConfiguration |
Where-Object MacAddress -ne '' |
Select-Object -ExpandProperty MacAddress) ) {
$NBG = [GUID]($NICMac -replace ':').PadLeft(32,'0')
$CompDetails = Get-ADComputer -Filter 'netbootGUID -like $NBG' `
-Properties netBootGUID -Server our.AD.server.ca -Credential $sessionKey
}
I don't consider usage of a line continuation character esoteric,
here it allows keeping the overview.
I agree that Natural Line Continuations in PowerShell are preferable.
A couple items here:
In your code, in line 7, you reference $NICMacs, but you should be referencing $NICMac since the foreach is running through the logic separately, not as a batch.
You could simplify at least the top two lines into a single line without a pipe.
$NICMacs = (Get-WMIObject Win32_NetworkAdapterConfiguration).MacAddress
Foreach ($NICMac in $NICMacs)
{
$MacString = $NICMac -replace ":", ""
$MactoGUID = "00000000000000000000" + $MacString
[GUID]$NBG = $MactoGUID -replace " ", ''
$CompDetails = Get-ADComputer -Filter 'netbootGUID -like $NBG' -Properties netBootGUID -Server our.AD.server.ca -Credential $sessionKey
Edit: in my suggested code, I think making $NBG should work with the [GUID] tag in front but I've never tried it

How do I reference an object's property in a Powershell Active Directory cmdlet?

Related to this fantastic answer about how to properly construct a -Filter parameter argument, I'm working on a script that makes heavy use of the Active Directory cmdlets in PowerShell, and am having difficulty constructing filter arguments containing the property of an object variable.
The script basically manages distribution groups by reading in spreadsheet and processing each row as appropriate - creating Active Directory contacts if they don't exist, adding or removing them to the appropriate group and so on.
The spreadsheet is stored in an object array, with each row being treated as an object, with the columns defining the object properties.
For example, the below code takes each row of the imported spreadsheet and attempts to find a matching contact object in Active Directory.
Foreach ($contact in $NOClist)
{
$contactobject = Get-ADObject -filter ("name -eq `"$contact.name`" -and Objectclass -eq `"contact`"") -SearchBase "$NOCContactPath" -Server $ADServer;
#... do some more stuff.
}
The problem is that $contact.name is being evaluated literally, so it ends up searching for a contact in Active Directory with a name property that's literally $contact.name. I've tried the other variations in the previously referenced answer, (""$contact.name"", '$contact.name' and "' + $contact.name + '"), but they all either evaluate to the literal $contact.name or throw a syntax error on the . character.
The hacky workaround I've come up with is to assign the object property to a variable and use that instead, such as the below, but that just feels terrible.
Foreach ($contact in $NOClist)
{
$contactname = $contact.name;
$contactobject = Get-ADObject -filter ("name -eq `"$contactname`" -and Objectclass -eq `"contact`"") -SearchBase "$NOCContactPath" -Server $ADServer;
#... do some more stuff.
}
Is there a way to reference an object property inside the filter argument, or is this workaround of assigning it to a variable and then using the variable really the best approach?
PowerShell does only simple variable expansion in strings, no complex stuff like index or dot-property access. There are several ways to deal with this limitation, e.g.
concatenation:
-Filter ("name -eq '" + $contact.name + "' -and Objectclass -eq 'contact'")
subexpressions:
-Filter "name -eq '$($contact.name)' -and Objectclass -eq 'contact'"
the format operator:
-Filter ("name -eq '{0}' -and Objectclass -eq 'contact'" -f $contact.name)
Note that for the first and third approach you need to put the operation in a grouping expression (i.e. in parentheses), so that the result of that operation is passed to the parameter.
First, are you sure that $contact.name is valid within that that loop? For debug purposes, throw a write-host in there to make sure it's what you think it should be.
But the major thing is that you're using single-quotes around the variable, which blocks variable expansion. It looks like you're trying to escape the double-quotes, not sure if that's possible but if it is, that's not the right way to do it. You should be shooting for this from the link:
Get-ADUser -Filter ('sAMAccountName -eq "' + $SamAc + '"')
Example for me:
PS V:> $contactname = "finn2617"
PS V:> Get-ADuser -filter ('samaccountname -eq "' + $contactname + '"' ) | select name, samaccountname
name samaccountname
---- --------------
Finnigan, Matthew FINN2617
So, for you:
$contactobject = Get-ADObject -filter ('name -eq `"' + $contact.name + " -and Objectclass -eq "contact" ' ) -SearchBase "$NOCContactPath" -Server $ADServer;

Powershell - Get-aduser return no value using a $var

i'm using this command to query AD for usernames::
get-aduser -filter 'SamAccountName -like "trembto*"
The AD return me some result that comply with that search.
when I try to apply this line with a $var inside, I get no result:
$userloop = "trembto"
get-aduser -filter 'SamAccountName -like "$($userloop)*"'
I should get the same result but it always returning me nothing, no error message
I tried may alternative for the var part but in vain.
Thank for helping me
Variable expansion will not happen when single quotes are used to create a string. You must use double quotes to create a string for variable expansion to occur. In your case, you need to use double quotes to create the filter string, and use single quotes around the expanded variable.
Change to this:
$userloop = "trembto"
get-aduser -filter "SamAccountName -like '$($userloop)*'"
You can see this behavior by inspecting the string you use for your filter parameter.
Test:
$userLoop = "trembto"
$filter = 'SamAccountName -like "$($userLoop)*"'
Output of $filter:
SamAccountName -like "$($userLoop)*"
Changed to:
$userLoop = "trembto"
$filter = "SamAccountName -like '$($userLoop)*'"
Outputs:
SamAccountName -like 'trembto*'