Sorting Office 365 user account / mailbox properties - powershell

I'm accessing my cloud Office 365 Exchange Server via Powershell. Showing all properties of an account can be done via Get-Mailbox 'username' | Select * (MS reference).
On most systems those properties are already sorted (e.g. Get-ADUser 'username' -Properties *). Is it possible to sort the Get-Mailbox output? I thought Get-Mailbox 'username' | Select * | Sort-Object would do the trick but it didn't make any difference (I guess a property doesn't constitute an object). What's the right command to sort the properties for a single user?
Note: Sorting properties of multiple accounts works fine e.g. Get-Mailbox -filter * | select Name, DisplayName | Sort-Object Displayname
Update:
I managed to get a sorted properties list using
(Get-Mailbox 'mailboxname' | select *).PSObject.properties | ForEach-Object {$_.Name} | Sort-Object Name
it gets me the following output:
AcceptMessagesOnlyFrom
AccountDisabled
AddressBookPolicy
ArchiveWarningQuota
...
$_.Name gives me the values but so far I couldn't combine both into one list, I'm trying to get s.th. like this:
AcceptMessagesOnlyFrom = {}
AccountDisabled = False
AddressBookPolicy =
ArchiveWarningQuota = 45 GB (48,318,382,080 bytes)
...

I'm not completely sure this is what you are after, let me know if I'm wrong. As in my comment, Sort-Object can handle sorting a list or an object[] by one or more of it's properties; but sorting one single object by it's properties, say alphabetically, would require a combination of accessing the object's properties with .PSObject.Properties.Name and then sorting this list with Sort-Object. And after that we can use Select-Object with this sorted list to display the object as we want.
Using the object below as an example as I have no idea how of the type Microsoft.Exchange.Data.Directory.Management.Mailbox looks.
$mailbox = [pscustomobject]#{
DisplayName = 'someuser'
UserPrincipalName = 'someuser#somedomain.com'
Mail = 'someuser#somedomain.com'
IsLicensed = $true
}
$properties = $mailbox.PSObject.Properties.Name | Sort-Object
$mailbox | Select-Object $properties
As you can see, object's properties are now sorted alphabetically:
DisplayName IsLicensed Mail UserPrincipalName
----------- ---------- ---- -----------------
someuser True someuser#somedomain.com someuser#somedomain.com
By looking at your edit, seems like you are looking for a one-liner, so this is how it could look:
Get-Mailbox 'mailboxname' | ForEach-Object {
$_ | Select-Object ($_.PSObject.Properties.Name | Sort-Object)
}

Related

PowerShell pipe ExpandProperty to another Select-Object

I want to get the aliases for all email recipients in my O365 tenant.
If I were doing this one traditional Exchange, the easiest is to Get-Recipient and pull out the SMTPAddress property using Exchange Manangement Console. (Note the Select piped into another Select; works like a champ.)
Get-Recipient | Select Name,SamAccountName -ExpandProperty EmailAddresses | Select Name,SamAccountName,SmtpAddress
The issue is when I try to do the same thing in EXO, the "EmailAddresses" property is output as a flat string and so when I try to pipe it to a 2nd select, the only Property is the Length, not the actual value of the string.
The following kind of works, but I feel like there has to be a better way?
Get-EXORecipient | Select Name -ExpandProperty EmailAddresses | % {Write-Output "$($_.Name),$($_)"}
What -ExpandProperty EmailAddresses expands to are strings, as you state.
The additional properties that these strings are decorated with if you also pass (positionally implied) -Property arguments, such as Name in your example, are present, but will typically not surface unless you explicitly access them on the now-decorated output strings.
If you want output objects that contain each email address as a property, more work is needed.
Get-EXORecipient | ForEach-Object {
foreach ($emailAddress in $_.EmailAddresses) {
[pscustomobject] #{
EmailAddress = $emailAddress
Name = $_.Name
# ... add further properties of interest here
}
}
}

Multiple rows in a grid [duplicate]

This question already has answers here:
Export hashtable to CSV with the key as the column heading
(2 answers)
Closed 4 years ago.
I'm trying to list all ad group memberships of specific users. The input would be a string of logins split with a comma 'login1,login2'.
So I go over each user and list their memberships with the username as title. Somehow it only shows the first entry. Also it shows the user groups in one row and I don't know how to change that.
Code below:
$users = $logon -split ','
$q = #()
foreach ($user in $users) {
$usernm = Get-ADUser -Filter 'samAccountName -like $user' | select Name
$useraccess = Get-ADPrincipalGroupMembership $user | Select-Object Name
$userobj = New-Object PSObject
$userobj | Add-Member Noteproperty $usernm.Name $useraccess.Name
$q += $userobj
}
Expected output would be something like:
fullnameuser1 fullnameuser2 list of users goes on...
------------- ------------- ------------------------
adgroup1 adgroup3 ...
adgroup2 adgroup4
... ...
In principle this would also mean that if i typed $q.'fullnameuser1' output would be:
fullnameuser1
-------------
adgroup1
adgroup2
...
Whenever the code is ran, it will only ever add the first user's access, also returning all groups on one row. So somehow I need to go over all the group memberships and add a row for each one.
First and foremost, PowerShell does not expand variables in single-quoted strings. Because of that Get-ADUser will never find a match unless you have a user with the literal account name $user. Also, using the -like operator without wildcards produces the same results as the -eq operator. If you're looking for an exact match use the latter. You probably also need to add nested quotes.
Get-ADUser -Filter "samAccountName -eq '${user}'"
Correction: Get-ADUser seems to resolve variables in filter strings by itself. I verified and the statement
Get-ADUser -Filter 'samAccountName -eq $user'
does indeed return the user object for $user despite the string being in single quotes.
If you want a fuzzy match it's better to use ambiguous name resolution.
Get-ADUser -LDAPFilter "(anr=${user})"
You may also want to avoid appending to an array in a loop, and adding members to custom objects after creation. Both are slow operations. Collect the loop output in a variable, and specify the object properties directly upon object creation.
$q = foreach ($user in $users) {
...
New-Object -Type PSObject -Property {
$usernm.Name = $useraccess.Name
}
}
Lastly, I'd consider using the user's name as the property name bad design. That would be okay if you were building a hashtable (which is mapping unique keys to values), but for custom objects the property names should be identical for all objects of the same variety.
New-Object -Type PSObject -Property {
Name = $usernm.Name
Group = $useraccess.Name
}
Basily query all the users and store it in $users, example:
Get-ADUser -Filter * -SearchBase "dc=domain,dc=local"
And then you can export the results as csv or a table.
To Export as CSV :
Get-ADPrincipalGroupMembership <Username> | select name, groupcategory, groupscope | export-CSV C:\data\ADUserGroups.csv`
To Format the result as Table in the console itslef :
Get-ADPrincipalGroupMembership <Username> | select name, groupcategory, groupscope | Format-Table

Insert parameter data from one output into another

This is directed towards Exchange/Office 365 powershell but can apply for other types as well.
If i have a list of users for example, and I use UserPrincipalName for their identity - now in all my scripts I can pull data using UserPrincipalName for the identity, but in most UserPrincipalName isn't actually an exportable value. So, if you take my two examples below I can pull data in both using UserPrincipalName for the identity, but in the 2nd one the ouput would be blank.
How can I insert for example the identity value UserPrincipalName into the 2nd. This would apply for more than the two scripts mentioned below.
$CSV | foreach {
Get-Mailbox -resultsize unlimited -Identity $_.UserPrincipalName
} | select userprincipalname, server |out-gridview
Example output:
UPN#something.com, server101
$csv | ForEach {
Get-ActiveSyncDeviceStatistics -Identity:$_.UserPrincipalName
} | select DeviceFriendlyName,UserPrincipalName |out-gridview
Example output:
2nd: DeviceIOS4,-
I don't have an Exchange at hand, but most likely the objects returned by Get-Mailbox do have a UserPrincipalName property, while the objects returned by Get-ActiveSyncDeviceStatistics don't. To preserve the UPN in the output of the second script, you can do something like this:
$csv | ForEach {
$upn = $_.UserPrincipalName
Get-ActiveSyncDeviceStatistics -Identity:$upn
} | select DeviceFriendlyName,#{n='UserPrincipalName';e={$upn}} |out-gridview

How to use the "-notcontains" conditional parameter when querying a BlockedSendersAndDomains list in PowerShell?

I am trying to make a list of all mailboxes who DO NOT have "conostco.com" domain on their BlockedSendersAndDomains list.
by using
$test= Get-MailboxJunkemailconfiguration -Identity * | fl Displayname, BlockedSendersAndDomains
I can get a list of all the names and the Blocked domains/email addresses associated to those names but for my purpose I want to get a list of all of the names of the mailboxes that DO NOT contain the domain "conostco.com". Is there such way to do it?
Based on the sample data you have given I am "assuming" BlockSendersAndDomains is an array.
So maybe you could do something like this then
$test= Get-MailboxJunkemailconfiguration -Identity * | % { $domains = $_.BlockedSendersAndDomains.GetEnumerator() | ? {$_ -notmatch 'conostco.com'}; $name = $_.displayname ; new-object PSObject -Property #{name=$displayname;domains=$domains} }
Again, there is no way for me to test, so see if that gives you a $test object collection which you can then re-use or just display, if you like.
Get-MailboxJunkEmailConfiguration -Identity * |
Where-Object {$_.BlockedSendersAndDomains -notlike '*conostco.com*' }

In PowerShell, how can I combine the results of two commands that have a 1-to-1 relashionship?

This particular example is Get-User and Get-Mailbox (Exchange 2010). Get-User returns some of the columns I need, and Get-Mailbox some others. I am having difficulty figuring out how I can combine the results of the two into a single table with the results from both.
Get-User -Filter "..." | Get-Mailbox -Filter "..."
How do I take the results of a command similar to the above and turn it into results similar to below?
FirstName LastName Alias CustomAttribute1
--------- -------- ------ ----------------
Bob Smith bsmith Example
Johnny NoMail
Adam Blye ablye Has a Mailbox
Note that FirstName and LastName are not returned by Get-Mailbox, and conversely Alias and CustomAttributes are not returned from Get-User. Not every user has a mailbox, so sometimes a portion of the columns would be null. But I'm having a devil of a time figuring out the best way to return a combined table like this.
Get the users, save each user in a variable, get the mailbox for each user and then create a new object with properties from both variables
Get-User -Filter ... | Foreach-Object{
$user = $_
$mbx = Get-Mailbox $user
New-Object -TypeName PSObject -Property #{
FirstName = $user.FirstName
LastName = $user.LastName
Alias = $mbx.Alias
CustomAttribute1 = $mbx.CustomAttribute1
}
}
I make a custom object, which may be overkill, but it's the simplest way I've found.
Here's some sample code to play with. Let me know if it generates any trouble or additional questions:
$outputCollection = #()
$users = Get-User -Filter "..."
$mailboxes = Get-Mailbox -Filter "..."
$users | Foreach-Object {
#Associate objects
$userObject = $_
$mailboxObject = $mailboxes | Where-Object {$_.Name -eq $userObject.Name}
#Make a combined object
$outputObject = "" | Select Name, UserAttribute, MailboxAttribute
$outputObject.Name = $userObject.Name
$outputObject.UserAttribute = $userObject.UserAttribute
$outputObject.MailboxAttribute = $mailboxObject.MailboxAttribute
#Add the object to the collection
$outputCollection += $outputObject
}
$outputCollection
Another option that should work is called calculated properties:
Get-User -Filter "..." | Select Name, UserAttribute, #{Name="OtherAttribute"; Expression={(Get-Mailbox $_.Name).MailboxAttribute}}
...note that this will run a new Get-Mailbox command for each entry, potentially increasing execution time
Thank you guys. I spent a hell of a lot of time trying to figure out my own issue and your code helped me get it right. I needed to find all the calendars were the default account was set to none. Below is what I needed up using.
Get-Mailbox | ForEach-Object{
$user = $_
$calPerms = Get-MailboxFolderPermission $user":\calendar" -User Default | Where-Object {$_.AccessRights -eq "none"}
New-Object -TypeName PSObject -Property #{
Name = $user
Permissions = $calPerms.AccessRights
Users = $calPerms.user
}
}
One liner to get FirstName, LastName, Alias and CustomAttribute1:
Get-User | Select Firstname, Lastname, #{Name="Alias"; Expression={(Get-Mailbox $_.Name).Alias}}, #{Name="CustomAttribute1"; Expression={(Get-Mailbox $_.Name).CustomAttribute1}}