Determine the true size of a mailbox by adding together the TotalItemSize and TotalDeletedItemSize values.

Scenario:  Determine the true size of a mailbox by adding together the TotalItemSize and TotalDeletedItemSize values together via a script and put the values into a table.  These values are properties of the Get-MailboxStatistics commandlet.

Note:  The TotalDeletedItemSize is not included in the TotalItemSize value for a mailbox.  Test it by deleting all of your mailbox content and comparing the values before and after.  Then perform a mailbox move and Exchange will show the total size of the mailbox which is a combination of the two.

Script:

#query for your mailboxes
$stat = get-mailboxdatabase DB* | Get-mailboxstatistics | Select DisplayName,TotalDeletedItemSize, TotalItemSize,ItemCount

#Define array variable
$final = @()

#Loop
$stat | %{

$TIS = $_.TotalItemSize.Value.ToMB() | Measure-object -sum

$TDIS = $_.TotalDeletedItemSize.Value.ToMB() | Measure-object -sum

$Total = $TIS.sum + $TDIS.sum


#Build the Array
 $ServerObj = New-Object PSObject
 $ServerObj | Add-Member NoteProperty -Name "DisplayName" -Value $_.DisplayName
 $ServerObj | Add-Member NoteProperty -Name "MbxSize(InMB)" -Value $total
 $Final += $ServerObj    
}

$Final

 

 

 

Collect and Email the Exchange 2013 Malware Protection Engine Update Information.

Scenario:  You want a report that will email you the Engine Update Information for all of your Exchange 2013 Servers that are using the native Malware Protection.

Script:

#Create Variables
$ExchangeServers = Get-ExchangeServer | Where AdminDisplayVersion -like "Version 15*"
$final = @()
$strCurrentTimeZone = (Get-WmiObject win32_timezone).StandardName
$TZ = [System.TimeZoneInfo]::FindSystemTimeZoneById($strCurrentTimeZone)

#Check for Malware Engine Updates. Loop and Invoke Commands.
$Exchangeservers | %{
$server = $_.name
$LC = Invoke-Command –Computername $_ -ScriptBlock {Add-PSSnapin microsoft.forefront.filtering.management.powershell;(Get-EngineUpdateInformation).LastChecked } -ErrorAction STOP
$LU = Invoke-Command –Computername $_ -ScriptBlock {Add-PSSnapin microsoft.forefront.filtering.management.powershell;(Get-EngineUpdateInformation).LastUpdated } -ErrorAction STOP
$EV = Invoke-Command –Computername $_ -ScriptBlock {Add-PSSnapin microsoft.forefront.filtering.management.powershell;(Get-EngineUpdateInformation).EngineVersion } -ErrorAction STOP

#Convert from UTC to Local Time Zone.
$LCLocal = [System.TimeZoneInfo]::ConvertTimeFromUtc($LC, $TZ)
$LULocal = [System.TimeZoneInfo]::ConvertTimeFromUtc($LU, $TZ)

#Build the Array
 $ServerObj = New-Object PSObject
 $ServerObj | Add-Member NoteProperty -Name "ServerName" -Value $server
 $ServerObj | Add-Member NoteProperty -Name "LastChecked" -Value $LCLocal
 $ServerObj | Add-Member NoteProperty -Name "LastUpdated" -value $LULocal
 $ServerObj | Add-Member NoteProperty -Name "EngineVersion" -value $EV
    $Final += $ServerObj    
}

$EngineUpdates = $final | Sort ServerName | Convertto-HTML

#Email
$body =""
$smtp = "mail.domain.com"
$to = "steve@domain.com"
$from = "EngineUpdateMonitor@domain.com"
$subject = "Engine Update Monitor" 
$body += "<b><Font color=#0404B4>Malware Engine Updates: </b></font><br><br>"
$body += "$EngineUpdates <br><br><br>"
send-MailMessage -SmtpServer $smtp -To $to -From $from -Subject $subject -Body $body -BodyAsHtml -Priority high

Content Index State is Unknown or Failed and has an error message of: “An internal error occurred for the database or its index.”

 Scenario:  Users cannot search in OWA or when in Outlook in Online mode. When you run the command below you notice that the Content Index State is Failed or Unknown.

get-mailboxdatabasecopystatus DB123 | FL Content*

ContentIndex:  Failed or Unknown
ContentIndexErrorMessage:  An internal error occurred for the database or its index.ContentIndexErrorCode:2

In the Application Event Log you see the following:

Event 1009, MSExchangeFastSearch:

The indexing of mailbox database DB123 encountered an unexpected exception. Error details: Microsoft.Exchange.Search.Core.Abstraction.OperationFailedException: The component operation has failed. —> Microsoft.Exchange.Search.Core.Abstraction.OperationFailedException: The component operation has failed. —> System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: Internal error while processing request

You have also verified that the Microsoft Exchange Search and Microsoft Exchange Search Host Controller services are started.

Solution: Follow these steps.

  1. Create an security group called ContentSubmitters.
  2. This security group will have no members, but you need to add Full Control in the security of the group to:
    • Administrators
    • Network Service
  3.  Now on the affected Exchange servers,  Restart the following services:
    • MSExchangeFastSearch  (Microsoft Exchange Search)
    • HostControllerService (Microsoft Exchange Search Host Controller)

 

 

Configure the Exchange Web.Config File for Lync via Powershell Script on Multiple Servers

Scenario:  During the OWA Integration of Exchange 2013 and Lync 2013 , one of the steps is to edit the web.config file on each Exchange Mailbox Server by adding a IMCertificateThumbprint and IMServerName.

The script below queries a list of Exchange servers, determines the certificate thumbprint needed, appends the required values to the web.config file, and then restarts the MSExchangeOWAAppPool and the MSExchangeUM* services.

$Servers= Get-ExchangeServer | Where AdminDisplayVersion -like "*15*"

$Servers | %{
$servername = $_.name 
Write-Host $servername

#Adding the UM Info into Web.Config
$UMThumb= (Get-ExchangeCertificate -server $servername | Where { $_.Services -like '*UMC*'}).ThumbPrint | Select -First 1

Write-Host "Configuring WebConfig for "$servername " with " $UMThumb

$WebConfigFile= "\$servernameC$Program FilesMicrosoftExchange ServerV15ClientAccessOwaweb.config"

Write-Host "Editing Web.Config in $WebConfigFile"

$wc= [XML](Get-Content $WebConfigFile)
$el= $wc.CreateElement("add")
$key= $wc.CreateAttribute( 'key')
$key.psbase.value = 'IMCertificateThumbprint'
$val= $wc.CreateAttribute('value')
$val.psbase.value= $UMThumb
$el.SetAttributeNode($key)
$el.SetAttributeNode($val)
$wc.configuration.appSettings.Appendchild( $el)
$el= $wc.CreateElement("add")
$key= $wc.CreateAttribute( 'key')
$key.psbase.value = 'IMServerName'
$val= $wc.CreateAttribute('value')
$val.psbase.value= 'LyncServerPool.Domain.Com'
$el.SetAttributeNode($key)
$el.SetAttributeNode($val)
$wc.configuration.appSettings.Appendchild( $el)
$wc.Save( $WebConfigFile)


#Restart the AppPool
$appPoolName = "MSExchangeOWAAppPool"
$appPool = get-wmiobject -computername $servername -namespace "rootMicrosoftIISv2" -class "IIsApplicationPool" -Authentication PacketPrivacy -Impersonation Impersonate | Where-Object {$_.Name -eq "W3SVC/APPPOOLS/$appPoolName"}
$appPool.Recycle()

#Restart the UM Services
Get-Service MSExchangeUM* -computername $servername | Restart-Service

}

 

Build a custom table in Powershell that includes mailbox count

Scenario:  You want to build a custom table to include the MailboxCount and other elements of the Get-ExchangeServer command.

$exchangeservers = Get-ExchangeServer | Where AdminDisplayVersion -like "*15*"

$final = @()

$Exchangeservers | %{

#Put the Server Name into a Variable
$server = $_.Name

#Grab the Mailbox Count Per server
$MBXCount = (Get-mailbox -server $_.Name).Count

#Version of Exchange
$AdminDisplayVersion = $_.AdminDisplayVersion

Write-Host "Checking $server"

#Grab the InstallPath
$ExchangeInstallPath = $null

$ExchangeInstallPath = Invoke-Command –Computername $server -ScriptBlock {$env:ExchangeInstallPath} -ErrorAction STOP

#Build the Array
 $ServerObj = New-Object PSObject
 $ServerObj | Add-Member NoteProperty -Name "ServerName" -Value $server
 $ServerObj | Add-Member NoteProperty -Name "InstallPath" -Value $ExchangeInstallPath
 $ServerObj | Add-Member NoteProperty -Name "MBXCount" -value $MBXCount
 $ServerObj | Add-Member NoteProperty -Name "Version" -value $AdminDisplayVersion
    $Final += $ServerObj    
}
$Final

 

 

Exchange Database Restore with CommVault

Here are the steps for performing the restore:

1. Create the Recovery Exchange Database in Exchange

2. Restore the Database from backup in CommVault

3. Restore the contents of the mailbox in the recovery database to a place holder mailbox in Exchange.

4. Create a PST of the of the mailbox content of the place holder mailbox in Exchange.

 

Create a Recovery Database in Exchange 2013:
The server MBX1 has a dedicated mount point for restoring databases in Exchange. The mountpoint is C:RecoveryDB on MBX1. Run the following powershell command:

New-MailboxDatabase -Recovery -Name RDB_DB01 -Server MBX1 -EdbFilePath “C:RecoveryDBRDBDB01.edb” -LogFolderPath “C:RecoveryDBRDB logs”

 

Restore to the Recovery Database in CommVault:

1. Ensure the database you want to restore is dismounted and marked for overwrite.

2. From the CommCell Console, navigate to Client Computers | <Exchange CommVault Client>. Right-click Exchange Database and then click All Tasks | Browse Backup Data.

3. Select your Browse option for when to Restore From. Select the date of the last known good backup of the data that needs to be restored.

4. In the left pane of the Client Browse window, navigate to Exchange Database | Microsoft Information Store | <Storage Group>. Select the database to be restored in the right pane and click Recover All Selected.

5. In the Restore Destination section, select the destination client that holds the Recovery Database; MBX1. In the Destination DB, select the new recovery database that was created; RDB_DB01. Click OK. You can monitor the restore in the Job Controller so you know when it is 100%.
Extract Content from Recovery Database:
1. Mount the Recovery Database so we can access the content by running the following in Exchange PowerShell:

Mount-database RDB_DB01

2. The following PowerShell command we can use to extract content of the mailboxes. The content can be extracted and placed into another mailbox. We will use a place holder mailbox called r_steve2010 and put all of the content into a recovery folder which will be created during the mailbox restore.

Exchange 2013 command:

New-MailboxRestoreRequest -SourceDatabase “RDB_DB01” -SourceStoreMailbox “<DisplayName of User on RDB Database>” -TargetMailbox “r_steve2010” -TargetRootFolder Recovery -AllowLegacyDNMismatch

Exchange 2010 Command:

Restore-Mailbox -Identity “R_Steve2010” -RecoveryDatabase “RDB_DB01” -RecoveryMailbox ‘steve2010’ -TargetFolder Recovery

3. From here we can either provide access the dummy account, or export the content from the dummy mailbox to a PST and give it to the customer. To export it to a pst, run the following Powershell Command:

New-MailboxExportRequest R_steve2010 –FilePath “\servernamesharenamefilename.pst” -acceptlargedataloss -baditemlimit 999
Now we have successfully restored and recovered content from a Commvault backup.

How to quickly gather IP Addresses for a list of Servers

Scenario: You want to quickly gather the IP addresses from a list of HostNames.  Gather your hostnames into a variable and run the following script:

#Gather into your Variable ( I am gathering a list of all Exchange 2010 servers) – You could also Import-CSV or other import types.

$Servers = Get-ExchangeServer ExSvr* | Where AdminDisplayversion -like *14* | Sort Name

#Loop It!  You can also write it out to a file as well by inserting Out-File with -append OR other export types.

$servers | %{
$IP = [System.Net.DNS]::GetHostAddresses($_.Name).IPAddressToString
$Name = $_.Name +":"+$IP
Write-Host $name
}

Rename Volume Labels by Powershell

To bulk rename Volume Labels for disks, use the following Powershell command:

get-ciminstance win32_Volume -filter “Label = ‘Old Label'” | set-ciminstance -Property @{Label =’New Label’}

If these volumes are mount points and you have to change the folder name as well, use the following Powershell command:

Rename-Item C:OldFolderName C:NewFolderName

Re-Activate inactive Server Component States for Exchange 2013

Scenario: After Exchange Patching/Upgrades (both failed and successful attempts) you may notice that the ​Server Component States become Inactive. For Example, even though the IMAP service is started, the server may be refusing the connection. To check to see the Server Component States state, run the following command:

get-servercomponentstate <servername>

To re-activate a Server Component State, run the following

set-servercomponentstate <servername> -component <component name> -State Active -Requester HealthAPI.

Note, other Requester’s you could try are:

Maintenance,  Sidelined, Functional, Deployment

Cert Work! Querying, Removing, Assigning Services to Exchange Servers via Powershell

Scenario:  You want to clean up Exchange Certificates on your Exchange Servers. The following steps are examples of querying and building your query to perform an action.

1. Check to see what Exchange Certs are on your server.

get-exchangecertificate -server  ExSvr1

2. Query a list of Certificates that have the subject mail.domain.com:

get-exchangecertificate – Server ExSvr1 | Where Subject -like CN=Mail.dom*

3.  Query a list of Certificates that have the subject mail.domain.com and have a Expiration less than a specific date:

Get-ExchangeCertificate -Server ExSvr1 | Where {($_.NotAfter -lt “3/22/2019”) -and ($_.Subject -like “CN=Mail.dom*”)} 

4.  Remove the list of Certificates that have the subject mail.domain.com and an expiration less than a specific date:

Get-ExchangeCertificate -Server ExSvr1 | Where {($_.NotAfter -lt “3/22/2019”) -and ($_.Subject -like “CN=Mail.dom*”)}  | Remove-Exchangecertificate -confirm:$false

 

Lets say you want to query all Ex2013 servers to find and remove the certs:

1. Gather your Servers into a Variable:

$Servers = Get-ExchangeServers | Where AdminDisplayVersion -like *15*

2. Use that variable in a loop to loop through the certs:

$Servers | %{

Write-Host $_.name;

Get-ExchangeCertificate -server $_.nameWhere {($_.NotAfter -lt “3/22/2019”) -and ($_.Subject -like “CN=M*”)}  | Remove-Exchangecertificate -confirm:$false

}

 

How to move/enable services on an Exchange Certificate:

1. Determine the Thumbprints of the Certificate you want to move Exchange Services to:

Get-exchangecertificate -server ExSrv1

2. Move/Enable services on an Exchange Certificate

Enable-ExchangeCertificate -thumbprint <thumpbrint> -server ExSrv1 -services IIS,SMTP,POP,IMAP

 

Now lets say you want to loop it:

1. Gather your servers into a variable:

$Servers = Get-ExchangeServers | Where AdminDisplayVersion -like *15*

2. Enable Services on all your servers certs with a Loop:

$Servers | %{ 

Write-Host $_.name;

Enable-ExchangeCertificate -thumbprint <thumpbrint> -server $_.name -services IIS,SMTP,POP,IMAP

}