I am attempting to get these Custom headers to display correctly when bringing in content from Import-CSV
The CSV contains a column titled Surname with a Surname in each row, it also contains a header titled "Email" with no data in any of the cells below.
$csv = Import-csv C:\temp\tester.csv
$csv | select Surname,#{Name='Email';Expression={Get-ADUser -Filter 'Surname -like "$_.Surname"' | Select -ExpandProperty UserPrincipalName}}
executes correctly when I hardcode the surnames in. Any ideas?
You enclose the filter in single quotes, this prevents Powershell from substituting $_.Surname for a value. If a string is enclosed in single quotes, it is treated as is, without any attempts to replace symbols, including escape symbols, prior to passing the string as an argument or an expression result. Replace the expression with this:
Expression={Get-ADUser -Filter "Surname -like `"$_.Surname`"" | Select -ExpandProperty UserPrincipalName}
The backticks are used to escape the quotes that should be passed into AD filter.
Related
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
I am trying to write a script to pull all e-mail addresses but I am finding that the output of my first get command is adding alot of white space to the result text file
Get-AdUser -Filter * -Properties * | Select EmailAddress | Out-File "C:\T2\EMailAddresses.txt"
Can anyone tell me what I am doing wrong here?
You are seeing whitespace because not every AD account has a value assigned to that property in your environment so it appears as a blank line, I get the same thing upon a quick test.
This should help.
$Emails = Get-ADUser -Filter * -Properties EmailAddress
$Emails | select EmailAddress | Where {$_.EmailAddress -ne $null} | Out-File "C:\T2\EMailAddresses.txt"
td;dr
The following writes all email addresses to the target file, ignoring AD users that don't have one:
([string[]] (Get-AdUser -Filter * -Properties EmailAddress).EmailAddress) -ne '' |
Set-Content C:\T2\EMailAddresses.txt
By writing just the - non-empty - .EmailAddress property values to the file, you're avoiding the problems that stem from saving for-display formatted object representations, which is what your attempt does (see below).
Note that -ne '' acts as a filter here, because its LHS operand is an array; that is, the result of the operation is the sub-array of those LHS elements that aren't the empty string ('').
As for what you tried:
By using Out-File in combination with objects subject to PowerShell's output formatting system, you're saving a for-display representation of your objects to a file, which, in the case at hand includes a table header, a leading and a trailing blank line and - in Windows PowerShell (but no longer in PowerShell (Core) 7+) - right-space-padding to the full console-line width of each line.
Even though you're only asking for one property - EmailAddress - Select-Object outputs not just that property's value for each input object, but a [pscustomobject] instance with an .EmailAddress property, and the resulting objects are implicitly formatted with Format-Table.
To get just the EmailAddress property values, use Select-Object -ExpandProperty EmailAddress. The resulting string values are not subject to formatting, so your command would work as intended except that it would still include $null values from those AD users who happen not to have a value stored in their .EmailAddress property.
While it often won't matter, for string input it's slightly faster to use Set-Content than Out-File / >; note that in Windows PowerShell you'll end up with different character encodings by default (ANSI vs. UTF-16 LE a.k.a "Unicode") - use the -Encoding parameter as needed; PowerShell Core 7+ fortunately now consistently defaults to BOM-less UTF-8.
The - faster, but more potentially memory-intensive - alternative to using Select-Object -ExpandProperty EmailAddress for extracting the EmailAddress property values is to use member-access enumeration ((...).EmailAddress, as shown above).
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
I have following script:
Get-ADUser -Filter {SamAccountName -like "z*"} -Properties * | select samaccountname, name, Email
Address, #{Name="LastLogonTimeStamp";Expression={([datetime]::FromFileTime($_.LastLogonTimeStamp))}}, #{n='ParentContai
ner';e={$_.distinguishedname -replace '^.+?,(CN|OU.+)','$1'}} | Format-Table
RESULT EXAMPLE
How to get description of second OU|CN container?
Try:
$_.DistinguishedName -replace '^.+?,((CN|OU)=[^,]+).*','$1'
Note the trailing .*, which ensures that the regex matches the entire input string and replaces it with the substring of interest as a whole; without .*, only part of the input would be replaced, followed by whatever part of the original that didn't match.
This assumes that all components are ,-separated (not sure why your images shows a . after the 2nd OU component) and that the CN/OU values have no embedded, escaped , instances.
You could make the inner (...) subexpression - whose match needn't be captured - slightly more efficient with (?:...).
I'm learning powershell right now.
I need to import a CSV like this:
lastname,firstname
lastname,firstname
lastname,firstname
etc
Then create a list of usernames no longer then 8 characters and check for collisions.
I have found bits and pieces of scripting around but not sure how to tie it all together.
I use Import-Csv to import my file.csv:
$variablename = import-csv C:\path\to\file.csv
but then I am not sure if I just import it into an array or not. I am not familiar with how for loops work in powershell exactly.
Any direction? Thanks.
There are a couple of concepts that are central to understanding PowerShell. Firstly, remember that you are always working with objects. So after importing your CSV file, your $variablename will refer to a collection of sub-objects.
Secondly, you can use the PowerShell pipeline to send the output of one cmdlet to the input of another. Some cmdlets will understand if you send them a collection, and automatically process each row.
If think what you're looking for though is the foreach-object cmdlet, which will allow you to run code against each item in the collection. Code inside the foreach-object block can refer to the $_ automatic variable which will contain the current object.
Assuming your CSV file is well formatted and has a header row with the column names, you can refer to each column by name e.g. $_.lastname & $_.firstname.
To put it all together:
import-csv C:\path\to\file.csv |
foreach-object {
write-host "Processing: $($_.lastname), $($_.firstname)"
# logic here to calculate username and create AD account
}
PowerShell can have a bit of a learning curve if you are coming from a different scripting environment. Here are a couple of resources that I've found helpful:
PowerShell 'gotchas' http://www.rlmueller.net/PSGotchas.htm
Keith Hill's Effective PowerShell: https://rkeithhill.wordpress.com/2009/03/08/effective-windows-powershell-the-free-ebook/
Also, check out the Technet Script Center, where there are many hundreds of Active Directory scripts. https://technet.microsoft.com/en-us/scriptcenter/bb410849.aspx
The script below should help you grasp a few concepts on how to work with csvs and manipulate data using PowerShell.
# the code below uses a 'here string' to mimic the import of a csv.
$users = #'
smith,b
smith,bob
smith,bobby
smith,sonny
smithson,john
smithson,jane
smithers,rob
'# -split "`r*`n"
$users |
ConvertFrom-Csv -Header 'surname','firstname' |
Select-Object #{Name='username'; Expression={"$($_.surname)$($_.firstname) "}}, surname, firstname |
Group-Object { $_.username.Substring(0,8).Trim() } |
Select-Object #{Name='username'; Expression={$_.Name}}, Count |
Format-Table -AutoSize
The $users | line takes the list of $users and pipes into the next command.
The ConvertFrom-Csv -Header... line converts the string into a csv.
The Select-Object #{Name... line creates an expression alias, which concatenates surname+forename. You'll notice the extra 8 spaces we append to the end of the string so we know we will have at least 8 characters in the string.
The Group-Object {... line groups the username, using the first 8 characters, if available. The .Trim() gets rid of any trailing spaces.
The Select-Object #{Name='username'... line takes the Name field from the group-object and renames to username and also shows the count from the grouping operation.
The Format-Table -AutoSize line is purely for output formatting to the console and gives you an output like the one below.
username Count
-------- -----
smithb 1
smithbob 2
smithson 3
smithers 1
An amended version of the above code, which you can use on your real csv. Change the surname, firstname column names to suit your csv.
# you would use the code below, to import your list of names
# uncomment the `# -Header surname,firstname` bit if your csv has no headers
$users = Import-Csv -Path 'c:\path\to\names.csv' # -Header surname,firstname
$users |
Select-Object #{Name='username'; Expression={"$($_.surname)$($_.firstname) "}}, surname, firstname |
Group-Object { $_.username.Substring(0,8).Trim() } |
Select-Object #{Name='username'; Expression={$_.Name}}, Count