How can I filter mailboxes that have never been logged on in Exchange Management Shell? - powershell

I need to run a Get-Mailbox | Get-MailboxStatistics command across a large number of mailboxes but the majority have never been used as it is a new install. As a result, I have to sit through hundreds of lines of
WARNING: There is no data to return for the specified mailbox '<mailbox DN>' because it has not been logged on to.
It would seem that I need to use a server-side filter of some kind but I haven't been able to find anything appropriate.
What can I do here?

There is no server side filtering in Get-MailboxStatistics and I can't repro it. Can you try this:
Get-Mailbox | Get-MailboxStatistics -warningAction silentlyContinue

This is the standard PS behavior for warnings. You can find Shay's parameter in the help for common_parameters get-help about_common_parameters. Alternately, you can set $WarningPreference = silentlycontinue. There are no statistics to return as the mailboxes have not yet been initialized, hence the warning.

Related

Passing previous Powershell command properties into a piped command

Can someone show how to pass a property from one Powershell command into the next piped command (in order to pull properties from both levels of the request)?
I need to get archive mailbox sizes for users in Exchange Online. An example of this is here:
Get-EXOMailbox | get-MailboxStatistics -archive | select displayname,totalitemsize
When you run this, obviously you are grabbing properties from the second command. I need to also grab the identity property tied to Get-EXOMAilbox, the first command (which shows the user's active mailbox and is useful for subsequent actions.
Thanks!
As Doug Maurer suggests, you might want to take advantage of the -PipelineVariable common parameter:
Get-EXOMailbox -PipelineVariable mailbox |Get-MailboxStatistics -Archive |Select #{Name='DisplayName';Expression={ $mailbox.DisplayName }},TotalItemSize

Is it possible to speedup Get-Mailboxstatistics for exchange online?

I need to run Get-MailboxStatistics for 4000 users, I'm thinking there is a way to speedup Get-MailboxStatistics.
I have read in a forum how to use Get-MailboxStatistics -Server, but I think it cannot be used for Exchange Online. As we don't know the servers where the mailboxes are.
Can I use the below cmdlet:
$MailboxStat = Invoke-Command -ScriptBlock {
Get-MailboxStatistics $mailbox.UserPrincipalName |
Select-Object TotalItemSize,DisplayName
}
I just need TotalItemSize and DisplayName for each mailbox user. I don't know whether this will really speedup.
Perhaps you can Export directly from portal https://portal.office.com/adminportal/home#/reportsUsage/MailboxUsage
Regards

How to check mailbox size without exchange module?

I need to find a way to check mailbox size and items count under PowerShell, but without using exchange snapin/module.
Normally this command would look like this:
Get-MailboxStatistics "XXX" | ft TotalItemSize, ItemCount
My goal is to checked those things without exchange specific commands. I don't have much knowledge about ADSI, but maybe this is the key to solve this.
Does anyone have any idea?

Get Memberships Of User

I have a very simple question but for some reason I can't seem to get my head around it.
I need a line of code that could be ran as a user from a client and lists all the "memeber of" groups from the AD (ONLY FOR THIS CURRENT USER). similar to
Get-ADGroupMember -identity "domain admins" -Recursive | foreach{ get-aduser $_} | select SamAccountName,objectclass,name
I would like the result to be listed.
I either need a way to import the AD module on a client computer or another way to contact the DC and get the users current "memeber of" groups.
/Niklas
I found the best way for my needs but CB.'s answer worked as well!
[ADSISEARCHER]"samaccountname=$($env:USERNAME)").Findone().Properties.memberof -replace '^CN=([^,]+).+$','$1'
I can then keep using this output in my code
you can use dos command line:
net user /domain %username%
The easiest way to do this would be with
Get-ADPrincipalGroupMembership -identity "Username"
Now this also means that you would have to have the active directory module loaded which you can find more information on its use on Technet Get-ADPrincipalGroupMember
If you simply want to produce a list, make a call to the command prompt as I find this works well, although it does truncate group names:
net user %username% /DOMAIN
If you want to programmatically get them and easily do something with that data, you'll want to rely on the Active Directory cmdlets.
To determine if you have these readily available in Powershell, you'll need to run the following command:
Get-Module –ListAvailable
If you don't see ActiveDirectory in the list you will need to first download and install the Windows Management Framework and import the module yourself:
Import-Module ActiveDirectory
Once that's done I believe this command should do the trick:
(Get-ADUser userName –Properties MemberOf | Select-Object MemberOf).MemberOf
Hopefully that gets you started. I'm fairly certain that there's more than one way to accomplish this with Powershell. Take a look at the Microsoft TechNet documentation to see if you can find something that better suits your needs.
Personally I have only ever needed to query AD group memberships ad-hoc for diagnostic purposes and have always relied on Get-ADUser or the command line call, depending on the target audience of the resulting data.

How can I effectively conserve resources using the PowerShell pipeline?

I have several PowerShell scripts that I use to manage a medium sized Microsoft Exchange organization (~10,000 mailboxes). Several of the scripts process all of the organization's mailboxes in some way. One common problem I run into while running these scripts is resource exhaustion. These scripts end up using gigabytes of RAM.
My research suggests that using the pipeline avoids memory consumption because the results aren't loaded into an array prior to processing. However, under certain conditions, Get-Mailbox still seems to load the entire list of results into memory before it attempts to pass those results to the next command in the pipeline.
For instance, I assumed the following example code would start listing the mobile devices associated with each mailbox as soon as the the command is executed:
EXAMPLE 1
function GetMailboxDevices
{
process
{
Write-Host $_.Alias -ForegroundColor Green
Get-MobileDevice -Mailbox $_
}
}
Get-Mailbox -ResultSize Unlimited | GetMailboxDevices
However, this code does not appear to process the results in real time while the Get-Mailbox cmdlet is running. Instead, Get-Mailbox appears to take a few minutes to run and then passes all of the results to the second command in the pipeline at once. The PowerShell session's RAM usage climbs to 1.5 GB or higher during this process.
Nevertheless, I can work around the issue using code similar to the following:
EXAMPLE 2
function GetMailboxAliases
{
process
{
Write-Host $_.Alias -ForegroundColor Green
$_.Alias
}
}
$aliases = Get-Mailbox -ResultSize Unlimited | GetMailboxAliases
foreach ($alias in $aliases)
{
Get-MobileDevice -Mailbox $alias
}
In the second example, Get-Mailbox does pass each result down the pipeline in real time as opposed to all at once (Write-Host confirms this) and the RAM usage does not increase significantly. Of course, this code is not as elegant as I have to collect the aliases into an array and then process the array with a foreach statement.
The pipeline seems to be effective if I do something simple in the function (such as simply returning the alias of each mailbox), but the behavior changes as soon as I introduce another Exchange cmdlet into the function (such as Get-MobileDevices).
My question is this: why doesn't the code in example 1 leverage the pipeline efficiently but example 2 does? What steps can be taken to ensure the pipeline is leveraged efficiently?
I'am not using Exchange so mush, but in my scripts I would do this :
function GetMailboxDevices ($mb)
{
process
{
Write-Host $_.Alias -ForegroundColor Green
Get-MobileDevice -Mailbox $mb
}
}
Get-Mailbox -ResultSize Unlimited | Foreach-object { GetMailboxDevices $_}
or
Get-Mailbox -ResultSize Unlimited | % { GetMailboxDevices $_}
When you are running a script that returns a lot of objects, loading them to a variable is a great way to help memory usage. This is why version 2 performs better.
Also, running this script remotely from another server or workstation could also make code execution easier and make resource usage easier to troubleshoot.
You can try this to check your impressions:
Measure-Command { script1.ps1 }
Measure-command { script2.ps1 }