Powershell Expression gives no results - powershell

I have created an expression that should return the OU canonical name. A small outline:
#(Search-ADAccount -LockedOut -UsersOnly) | Select-Object Name,SamAccountName,#{Name="OU";Expression={((Get-ADOrganizationalUnit -Identity $($_."DistinguishedName")).CanonicalName)}}
However, this expression returns an empty OU column, the other 2 columns are filled.
My question is what is wrong with this expression? Any feedback is appreciated.
With kind regards,
TheStingPilot

A troubleshooting technique for calculated properties:
The script block stored in the Expression entry of a hashtable defining a calculated property:
runs in a child scope relative to the caller's scope.
more importantly, it quietly ignores any errors that occur.
However, such errors are recorded in the automatic $Error variable, so to diagnose your problem you can do the following:
$Error.Clear()
Search-ADAccount -LockedOut -UsersOnly |
Select-Object Name, SamAccountName, #{Name="OU";Expression={(Get-ADOrganizationalUnit -Identity $_.DistinguishedName).CanonicalName}}
$Error # Output the errors that occurred inside the calculated property's script block.
Solution to your specific problem:
As Santiago Squarzon's helpful answer explains, you need to extract the OU's distinguished name (DN) from the user's and pass the former to Get-ADOrganizationalUnit -Identity.
While $_.DistinguishedName.Split(',',2)[1], which removes the first ,-separated token from the user's DN will typically work, it can fail with DNs that use escaped , chars. (\,) that are to be treated as part of a value; e.g.:
# !! Simple splitting by the first "," is NOT enough here:
PS> 'CN=Martin Luther King\, Jr.,OU=Ministry,DC=example,DC=org'.Split(',',2)[1]
Jr.,OU=Ministry,DC=example,DC=org # !! WRONG - split at the *escaped* ","
To also handle these edge cases, i.e. to robustly extract the OU's DN from a user's, a sophisticated regex is required, in combination with the -replace operator:
# OK: The regex correctly recognizes the escaped \, as such.
PS> 'CN=Martin Luther King\, Jr.,OU=Ministry,DC=example,DC=org' -replace '^.+?((?<=[^\\])(?:\\\\)*),'
OU=Ministry,DC=example,DC=org # OK
To put it all together:
Search-ADAccount -LockedOut -UsersOnly |
Select-Object Name,
SamAccountName,
#{
Name = 'OU'
Expression = {
(Get-ADOrganizationalUnit -Identity ($_.DistinguishedName -replace '^.+?((?<=[^\\])(?:\\\\)*),')).CanonicalName
}
}

The issue with your code is that you're trying to feed Get-ADOrganizationalUnit a user's DistinguishedName instead of an OU's DistinguishedName which is not valid.
It's also worth mentioning, you're missing -Properties CanonicalName on Get-ADOrganizationalUnit.
Try this instead:
$e={(Get-ADOrganizationalUnit -Identity $_.DistinguishedName.Split(',',2)[1] -Properties CanonicalName).CanonicalName}
Search-ADAccount -LockedOut -UsersOnly |
Select-Object Name, SamAccountName, #{Name="OU";Expression=$e}

Related

How to query the Active Directory using a list of users in a text file for a specific attribute with PowerShell

I'm somewhat basic to Powershell and use one-liner commands only to keep it short and basic.
I would like to do the following: I have a list of users in a text file in the form of UserPrincipalName. I'd like to query this list of users if their accounts are still active/enabled or not. To do so, I'm trying to run the following command, which just reveals nothing in the end (blank output):
gc .\users.txt | foreach {get-aduser -server "corp.xxx.com"
-f 'name -like "$_"' -properties *}| select displayname,enabled
As mentioned, the output is blank with no errors or whatsoever.
I read that aduser doesn't work with pipelines, but I need to find a solution.
Kindly request your support :)
Thanks
Your use of single quotes in your filter is not allowing the expansion of the variable. Double-quotes should be wrapping the filter expression so as to allow the interpolation of the automatic variable $_:
Get-ADUser -Filter "name -like '$_'" ...
Single-quoted strings:
A string enclosed in single quotation marks is a verbatim string. The string is passed to the command exactly as you type it. No substitution is performed.
Also note, you mention in your question that the file has the user's UserPrincipalName attribute, yet you're querying the Name attribute, if that's the case, the filter should be:
Get-ADUser -Filter "UserPrincipalName -eq '$_'" ...
Note the use of -eq instead of -like, for exact matches you should always use this operator, see about_ActiveDirectory_Filter for usage details and examples of each operator.
If you're only interested in DisplayName and Enabled for your output, there is no reason in querying all the user's attributes, -Properties * should be just -Properties DisplayName since Enabled is already part of the default attributes returned by Get-ADUser.
Finally, the -Identity parameter can be bound from pipeline, and this parameter accepts a UserPrincipalName as argument, hence ForEach-Object is not needed in this case:
Get-Content .\users.txt |
Get-ADUser -server "corp.xxx.com" -Properties DisplayName |
Select-Object DisplayName, Enabled

Simple PowerShell, Variable inside bracket no working

I'm missing formatting or something simple having to do with the variable. When I enter the variable data, no output. If I enter the SMTP: address manually script works fine.
$EmailAddressAlias=Read-Host "Enter the FULL Email Address to find the associated Mailbox "
Get-Mailbox -Identity * |
Where-Object {$_.EmailAddresses -like 'SMTP:$EmailAddressAlias'} |
Format-List Identity, EmailAddresses
I see two issues here, and a suggestion. You've got a variable inside single quotes, and you have no wildcards in your -like comparison. In order for the variable to expand into its value you need to use double quotes like this:
$_.EmailAddresses -like "SMTP:$EmailAddressAlias"
Also, when you use -like with no wildcards you may as well be using -eq. Lastly, you should really filter at the Get-Mailbox level rather than getting all mailboxes, and then filtering for just the one you want. You may want to try this instead:
Get-Mailbox -Filter "EmailAddresses -like '*$EmailAddressAlias*'" | Format-List Identity, EmailAddresses

Filter result from Get-ADUser using sAMAccountname

I would like to extract a username from AD using Get-ADUser. The issue I'm having is when using sAMAaccount name as filter, I get multiple results if the value is found in multiple entries. To illustrate, if my samaccountname is 'a123b', and my coworker's is 'c1234d', I get both our names when I run this:
get-aduser -ldapFilter "(samaccountname=*123*)"| select Name
I would like to return only my information based on '123' and not '1234'
I've already tried the following as well to no avail:
get-aduser -Filter "samaccountname -like '*123*'" | select Name
You can narrow it down with a regular expression:
$filter = "[a-zA-Z]123[a-zA-Z]"
Get-ADUser -Filter "samaccountname -like '*123*'" | where { $_.samaccountname -match $filter} | select name
$filter is a simple regex pattern looking for 123 surrounded by letters (uppercase or lowercase)
-match is the operator that allows a regex comparison
When using a partial SamAccountName in a Filter or LDAPFilter, it is more than likely to get multiple results.
To test and return a specific user account, you need the filter to be more specific if possible (depends on what policies your environment uses for accountnames), like
Get-ADUser -Filter "SamAccountName -like 'a123*'" | Select-Object Name
or use an extra Where-Object clause to narrow down the results by some other user property like the firstname for instance:
Get-ADUser -Filter "SamAccountName -like '*123*'" | Where-Object { $_.GivenName -eq 'John' } | Select-Object Name
Mind you, the above examples can still return multiple user objects..
If you have it, the absolute sure way of retrieving a single user object is by using the DistinghuishedName of that user and get the object by using the -Identity parameter. See Get-ADUSer
P.S.:
When using the -like operator or an LDAPFilter, use wildcard characters on the parts of the name that can vary.
Since you can't use regex in the LDAP query, you could use a query like this to tell it to find user accounts that contain 123 but not with a fourth digit:
(&(objectClass=user)(samaccountname=*123*)(!samaccountname=*1231*)(!samaccountname=*1232*)(!samaccountname=*1233*)(!samaccountname=*1234*)(!samaccountname=*1235*)(!samaccountname=*1236*)(!samaccountname=*1237*)(!samaccountname=*1238*)(!samaccountname=*1239*)(!samaccountname=*1230*))
It's ugly, but it works.
Note that, if you have a filter that starts with a wildcard, the index for that attribute cannot be used, so it will have to look at every account to find a match. I added a filter for objectClass, since that is indexed and it will ensure it only looks at user objects.

How to filter out which users are allowed to log in to a computer?

I am needing to parse through user information to find which computers a specific user has access to, and then filter that out to generate txt docs for each computer listing the allowed users for that machine. However, my script isn't returning expected results and is creating incomplete lists.
Get-Content c:\temp\computers.txt | ForEach-Object {
$computername = $_
Get-ADUser -Filter "LogonWorkstations -like '*$computername'" -Properties LogonWorkstations |
Format-Table SamAccountName, Enabled |
Out-File -FilePath c:\temp\Accounts\"$computername-$fileDate".txt
}
I am fairly certain the issue lies in my filtering, because some of the files are returning info, however only ones where the username matches the computer name in some regard. Rather than listing users whose "LogonWorkstation" includes said computer, which is what I am looking to do. (If I pull a user's "LogonWorkstation" separately, that information is correct.)
I believe the issue is that the logonworkstations property stores the list of computers as a string rather than a collection. Since the -Filter parameter has limited operators, you will need to use -like in order to introduce wildcards. Then you can use whatever method to build your computer name string to include surrounding asterisks.
Get-Content c:\temp\computers.txt |
ForEach-Object {
Get-ADUser -Filter "LogonWorkstations -like '*$_*'" -Properties LogonWorkstations |
Format-Table SamAccountName, Enabled |
Out-File -FilePath c:\temp\Accounts\"$_-$fileDate".txt
}

Powershell script to display all Users in a Group AD

I have created the below
Get-ADGroup -Filter * -SearchBase "DC=Domain,dc=.com" -properties name, members |
Select-Object *,#{Name='Member';Expression={$_.Members -replace '^CN=([^,]+).+$','$1'}} |
FT Name, Member -Autosize |
out-file c:\text.txt
Ignore Domain and .com I have them populated with my relevant information, but for sake of here removed them.
When I run this it returns what I'm after but when looking at the members within the group they all end with ... and don't show all the members
There are a few things to correct. Let's look at them in order. The actual AD query can be simplified: you only need to specify 'Members' as an additional property to retrieve as 'Name' is brought back by default:
Get-ADGroup -Filter * -SearchBase "DC=Domain,dc=.com" -properties members
Given that you only want to output two properties ('Name' and your custom one 'Member'), use your select to retrieve only the ones you want:
Select-Object Name ,#{Name='Member';Expression={$_.Members -replace '^CN=([^,]+).+$','$1'}}
Remove the Format-Table: we have already limited the selection in the previous command. Format cmdlets are designed to format the output to the console window and best practice dictates that they should only be used for that purpose and that they should always be the last element of a pipeline.
Piping all of that to Export-Csv will then produce what you want:
Export-Csv -NoTypeInformation -Path C:\text.csv
This one did the trick for me
Get-ADGroupMember -Identity Administrators | Select-Object name, objectClass,distinguishedName | Export-CSV -Path “adgroupmembers.csv”
I got this here.
https://www.lepide.com/how-to/export-members-of-a-particular-ad-group-using-poweshell.html#:~:text=The%20PowerShell%20Get%2DADGroupMember%20cmdlet,group%20you%20want%20to%20use.