Exporting multi-valued attributes to new lines on a CSV - powershell

A bit of background on this.
I have approx 900 user accounts in active directory that are disabled and need to be deleted. They all have mailboxes attached, and to prevent these email addresses being recycled and reused for new users, I want to add each email address, along with any email aliases to a distribution group that essentially won't go anywhere.
I have a list of the FQDNs off all 900 users, and I have created a script in Powershell that will take my list, and then it will do a "for each" loop for each user. The script gathers their email addresses and then exports them to a CSV file.
The end goal is to have a long list of email addresses so that I can add them to the distribution group.
Because the emailaddresses attribute has multiple values, I'm finding that when it exports it to excel, it exports each email address to the same line, currently separated by a semicolon.
What I am looking to achieve, is for each individual email address to be listed on a brand new line on the export. Is this possible?
# Get list of users that we want to delete.
$Users = Get-Content "c:\temp\UsersToDelete.txt"
# For each user - find their email addresses and append them to a CSV.
foreach ($User in $Users) {
Get-Mailbox -Identity "$User" | select #{Name=’emailaddresses’;Expression={$_.emailaddresses -join “;”}} | export-csv -append "c:\temp\CollectedEmailAddresses.csv"
}

You would need an inner loop for each value in the .emailaddresses property:
Get-Content "c:\temp\UsersToDelete.txt" | ForEach-Object {
foreach($email in (Get-Mailbox -Identity $_).emailaddresses) {
[pscustomobject]#{
User = $_
Email = $email
}
}
} | Export-Csv "c:\temp\CollectedEmailAddresses.csv" -NoTypeInformation
Also your code would be more efficient moving Export-Csv as the last statement in your pipeline and removing -Append assuming this is a new file. Appending a CSV line per loop iteration is inefficient and only slowing down your script.

Related

Powershell: Pulling from a list (CSV) running a command and outputting to a different CSV

very new to heavier powershell and I've been hacking at this all day and can't figure it out.
I need to get a list of UPNs from office 365 accounts. I have the names in a CSV file. It has one column, with a long list of names. Heading is "name"
I want to run the get-user command against every name with the pipe format-list name, universalprincipalname and then output it to a new file.
I tried this:
get-content "m:\filename.csv" |
foreach {get-user '$_.user' -identity -resultsize unlimited} |
format-list name, userprincipalname |
out-file -FilePath m:\newfilename.csv
But it did not work (I also tried it with import-csv). It seemed to instead of pulling from my list, pull right from the office365 exchange server and when it finally finished had way more names in it than I have in my list.
My overall goal is to generate a list of upns of all the people who do not have mobile devices with their account so I can use a powershell command to disable active sync and OWA for mobile devices. Unfortunately, the command I used to generate my list of users produced the list in first name, last name format...and we have so many users I can't just concatenate the thing in excel, because there would be a ton of mistakes.
CSV is laid out like this:
Column1
name
first last
first last
first last
first last
Assuming the CSV's header is Name, the code should look like this:
Import-Csv "m:\filename.csv" | ForEach-Object {
Get-User -Identity $_.Name.Trim() -ResultSize Unlimited
} | Select-Object Name, UserPrincipalName |
Export-Csv "m:\newfilename.csv" -NoTypeInformation
Note that I'm using Select-Object instead of Format-Table. You should only use Format-Table to display your output to the PowerShell host, objects passed through the pipeline to this cmdlet will be recreated into a new object of the type FormatEntryData which you do not want if your intent is to export the data.

Get samaccountname from display name - but with extras

First time poster but site has helped me so much in the past.
We are an MSP and regularly get requests from clients to pull various details off a list of users they send us. Unfortunately though their lists rarely (if ever) contain any unique identifiers for AD such as samAccountName or even e-mail.
So typically I only get their first and last names, job titles etc. and use a slight variation on the below to try and get the required samAccountNames to work in batch modify scripts.
Get Samaccountname from display name into .csv
The problem comes (and caused a big headache recently) when I try to put that output back into a table to line up with the displaynames. As if the script can't find the displayname it just moves onto the next one in the list and puts the samAccountName directly below the last one it found. making it out of line with the displayname column I've put it beside.
My question is is there something I can add to the below script that when an error occurs it simply inputs null or similar into the samAccountName output csv so I could spot that easily in an excel sheet.
Similarly some users have multiple accounts like an admin and non-admin account with the same display name but different samAccountName so it pulls both of them, which is less of a problem but also if there was any way to have the script let me know when that happens? That would be super useful for future.
Import-Module activedirectory
$displayname = #()
$names = get-content "c:\temp\users.csv"
foreach ($name in $names) {
$displaynamedetails = Get-ADUser -filter { DisplayName -eq $name } -server "domain.local"| Select name,samAccountName
$displayname += $displaynamedetails
}
$displayname | Export-Csv "C:\temp\Samaccountname.csv"
So the problem lies in that you rely on Get-ADUser to provide you with user objects and when it doesn't you have gaps in your output. You instead need to create an object for every name/line in your "csv" regardless of whether Get-ADUser finds anything.
Get-Content 'c:\temp\users.csv' |
ForEach-Object {
$name = $_
$adUser = Get-ADUser -Filter "DisplayName -eq '$name'" -Server 'domain.local'
# Create object for every user in users.csv even if Get-ADUser returns nothing
[PSCustomObject]#{
DisplayName = $name # this will be populated with name from the csv file
SamAccountName = $adUser.SamAccountName # this will be empty if $adUser is empty
}
} | Export-Csv 'C:\temp\Samaccountname.csv'

Getting All Calendar SubFolders from CSV List of Users

I am trying to get a list of all the subfolders for a list of users from importing a CSV. Here is the code I have:
Import-Csv "C:\Users\177626\Desktop\Calendar.csv" | foreach {Get-MailboxFolder -identity "$($_.CalendarUsers):\Calendar" -GetChildren}
$_.CalendarUsers is what I am using as the column in the CSV for the user email addresses.
The issue is whenever I run the script, it reads the first users but then tell me any user after that, that the mailbox does not exist. See attached:
Any help would be much appreciated to figure this out...also, is it possible to also list the User's Name and PrimarySMTP from the output of this script?
Thanks!
Please check if all the mailboxes and the calendars in the .csv file are provisioned.
Import-Csv "C:\Users\177626\Desktop\Calendar.csv" | foreach {Get-Mailbox -identity $_.CalendarUsers}
Import-Csv "C:\Users\177626\Desktop\Calendar.csv" | foreach {Get-MailboxCalendarFolder -Identity "$($_.CalendarUsers):\Calendar"}
ref: https://learn.microsoft.com/en-us/powershell/module/exchange/get-mailboxcalendarfolder?view=exchange-ps

Adding AD group members to CSV list of AD groups

I have a list of AD security groups contained in a .csv file, in the following format:
Groups,
Groupname1,
Groupname2,
Groupname3,
What I want to do is feed this .csv file to a PowerShell script, so it can report on the group membership of the groups listed in the .csv file (I don't care about recursive groups, as I don't have any). The script should then dump the results to a further .csv file.
So, ideally, I want the final .csv produced output from the scripts to be something like.
Groupname1, name
Groupname1, name
Groupname2, name
Groupname2, name
Groupname3, name
Groupname3, name
You get the idea.
What I am struggling with is getting some sort of for loop going, to look through all the groups from the .csv and output the results as shown above (groupname and then user).
$list = Import-Csv -Path C:\temp\ADGroups.csv
foreach ($groups in $list) {
$ADGroup = $groups.groupname
Get-ADGroupmember -Identity $ADGroup | Get-ADUser -Property Name
Export-Csv -Path "c:\temp\dump.csv"
}
I've seen other suggestions (see example here), but these don't read the groups from a .csv file.
You need to add the group name to the output. I would do this with a calculated property. You also need to move the Export-Csv outside the loop or use -Append. If not, the groups will overwrite the file every time and it will only contain the results from the last group. Try this:
Import-Csv -Path C:\temp\ADGroups.csv | Foreach-Object {
$ADGroup = $_.Groups
Get-ADGroupmember -identity $ADGroup | Select-Objects #{n="Groupname";e={$ADGroup}}, Name
} | Export-CSV -Path "c:\temp\dump.csv" -NoTypeInformation

Powershell Query AD to export emails of all users in .txt file?

I would like to write a PS script that exports a .csv for all users that are specified in a separate .txt file. So, for instance, I could create a text file that has
Timmy Turner
Silly Sally
Then, when the script is ran, it searches AD for those two users and exports a CSV with their first name, last name, and email address.
I originally got hung up a bit on how the "Get-ADUser" filter worked, but I produced something semi-usable. However, what I've come up with just asks who you are searching for and then uses that. I think it would be much easier to just have it reference a pre-made text file, especially when searching for a large number of users. Or, there may be an even easier way to do this that I am not thinking of. Here is what I currently have:
$SamAc = Read-Host 'What is the first and last name of the person you would like to search for?'
$filter = "sAmAccountname -eq ""$SamAc"""
Get-ADUser -Filter $filter -Properties FirstName, LastName, EmailAddress | select FirstName, LastName, EmailAddress | Export-CSV "C:\Scripts\PS_ADQuery\Email_Addresses.csv"
I feel like the "Get-Content" cmdlet is close to what I am looking for, but I can't seem to get it to function correctly. I may be going in the totally wrong direction, though.
I found the answer. It turns out I even had the AD properties totally wrong. Take my comments with a grain of salt since I may not fully understand the processes behind each line of code, but this does exactly what I was looking to do.
#creates a $users variable for each username listed in the users.txt file. the ForEach
#command allows you to loop through each item in the users.txt array. the scriptblock
#nested into the ForEach command queries each username for specific properties.
$users = ForEach ($user in $(Get-Content C:\Scripts\PS_ADQuery\users.txt)) {
Get-AdUser $user -Properties GivenName,sn,mail
}
#takes the $users variable defined by the ForEach command and exports listed properties
#to a csv format.
$users |
Select-Object GivenName,sn,mail |
Export-CSV -Path C:\Scripts\PS_ADQuery\output.csv -NoTypeInformation