When removing a Public Folder Database, the error is displayed: “The public folder database specified contains folder replicas. Before deleting the public folder database, remove the folders or move the replicas to another public folder database. “

Scenario:  You are trying to remove the last Public Folder Database in your Exchange 2010 Organization, but you are receiving this error when running:  Remove-PublicFolderDatabase EXPF1

The public folder database specified contains folder replicas. Before deleting the public folder database, remove the   folders    or move the replicas to another public folder database.

Solution:  Run the following commands to deleted the PF Folders and then try to remove the public folder database again:

Public Folders:

Get-PublicFolder -Server Ex2010Srv1 “” -Recurse -ResultSize:Unlimited | Remove-PublicFolder -Server Ex2010Srv1 -Recurse -ErrorAction:SilentlyContinue

System Public Folders:

Get-PublicFolder -Server Ex2010Srv1 “Non_Ipm_Subtree” -Recurse -ResultSize:Unlimited | Remove-PublicFolder -Server Ex2010Srv1 -Recurse -ErrorAction:SilentlyContinue

“Couldn’t Load Mailboxes” error when opening an eDiscovery search preview

Scenario:  When an eDiscovery search is finished and you click to preview the results, you receive a “Couldn’t load mailboxes” error message and no results are displayed.

Resolution:  Remove the space out of the Search Name.  For example, if your search was labeled “Search for Steve”, remove the spaces so it looks like “SearchForSteve”

 

Steve

Message Tracking Aging in Exchange 2013

Scenario: You have a message that was delivered into Exchange 2013 within the last 30 days, but you cannot locate any Message Tracking log entries for that message.  Clearly the message was delivered into the mailbox as the message header contains the Exchange 2013 server hops.

When we run the following in Exchange 2013, it outputs the following defaults:

get-transportservice Ex2013Srv1 | FL MessageTrackingLogMax*

MessageTrackingLogMaxAge:           30 Days
MessageTrackingLogMaxDirectorySize: 1000 MB
MessageTrackingLogMaxFileSize:      10MB

Looking deeper into the Message Tracking Logging in the actual File Directory where the messages are stored (C:Program FilesMicrosoftExchange ServerV15TransportRolesLogsMessageTracking), I see 30 days worth of logs and what appears to be well over 1000 MB in log files combined.

Here’s whats happening.

The Message Tracking Log Directory contains different message tracking log files, all prefixed with the type of Tracking Log it is.

MSGTRK - Logs associated with the Transport Service
MSGTRKMA - Logs associated with the approvals and rejections
MSGTRKMD - Logs associated with messages delivered to Mailboxes
MSGTRKMS - Logs associated with messages sent from mailboxes

The 30 day max directory age OR the 1000 MB max directory size applies to the different message tracking log types separately.  For example, I have 30 days worth of MSGTRKMS logs as there is less activity for sending messages from the transport service on the server and the combined MSGTRKMS logs are under 1000 MB in combined size.  But I only have  20 days worth of MSGTRKMD logs as the combined log files size has met the 1000 MB limit.  Circular logging kicks in and older log files that meets the max age or max size criteria are then replaced with newer message tracking logs.

In our scenario,  the messages have aged off based on the size of the cumulative message tracking types and/or the date of when the files were created.

 

 

Disable Cache Mode for Additional Mailboxes that are added to your mail profile.

Scenario:  You want to only cache your primary mailbox in your mail profile, but you do not want to cache the additional mailboxes that were added to your mail profile.

Resolution:  Uncheck Download shared folders under your cache settings:

  1. Within Outlook 2013/2010, click on the File tab, click Account Settings in the Account Settings list.
  2. In the Account Settings dialog box, click the E-mail tab and then double-click your Microsoft Exchange Server account.
  3. In the Change Account dialog box, click More Settings.
  4. In the Microsoft Exchange dialog box, click the Advanced tab.
  5. Click to clear the Download shared folders check box. (The screen shot for this step is listed below).

    The screen shot for this step.

  6. Click OK two times.
  7. Click Next, click Finish, and then click Close.
  8. Restart Outlook.

Delete Calendar entries by Start date and End Date

Scenario:  When exporting a Calendar to a PST via New-MailboxExportRequest, there no good content filters to export via Start Date and End Date for exporting calendar entries to a date range.  The Created/Modified/Received dates which are saved into Indexing may not produce the correct result if those items are queried.  Instead follow these steps:

1. Export the entire calendar and import it into another mailbox.

2. On the new mailbox, give your account that you are running Exchange Powershell from FULL permissions to the mailbox you created (or the mailbox with the calendar you want to edit).

3. Run the following script.  Change that which is in blue:

*Note: You can only do up to 2 year increments.  You can also comment out (#) the delete lines to double check your work.

Import-Module -Name "C:Program FilesMicrosoftExchange ServerV15BinMicrosoft.Exchange.WebServices.dll"
$mailboxname = "TEST222@domain.com"
$service = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.Exchangeversion]::exchange2013)
$service.Url = new-object System.Uri("https://Ex2013Svr1.domain.com/EWS/Exchange.asmx")
$folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar,$MailboxName) 
$Calendar = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)    
#Define Date to Query 
#running 2 Year Increment
$StartDate = "1/1/2006"
$EndDate = "12/31/2007"
$CalendarView = New-Object Microsoft.Exchange.WebServices.Data.CalendarView($StartDate,$EndDate,100000)    
$fiItems = $service.FindAppointments($Calendar.Id,$CalendarView)    
foreach($Item in $fiItems.Items){      
 "Start    : " + $Item.Start  
        #"ENd    : " + $Item.END
        "Subject     : " + $Item.Subject  
 $Item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete)
    }    
#running 1 Year Increment
$StartDate = "1/1/2008"
$EndDate = "12/31/2008"
$CalendarView = New-Object Microsoft.Exchange.WebServices.Data.CalendarView($StartDate,$EndDate,100000)    
$fiItems = $service.FindAppointments($Calendar.Id,$CalendarView)    
foreach($Item in $fiItems.Items){      
 "Start    : " + $Item.Start  
        #"ENd    : " + $Item.END
        "Subject     : " + $Item.Subject  
 $Item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete)

Installing updates manually once approved via Configuration Manager and checking the install status for each server remotely

Scenario:  You use Microsoft System Center 2012 Configuration Manager to receive updates for Windows.  Once your updates are approved for installation, you can use the following script to perform a manual install. Once the manual install is kicked off from a remote machine, you can use additional PowerShell commands to determine the statuses for each update.

Here is a copy of the script we are using that is located on each one of our servers.  Reference to the script found here.

InstallUpdates.PS1

$MissingUpdates = Get-WmiObject -Class CCM_SoftwareUpdate -Filter ComplianceState=0 -Namespace rootCCMClientSDK 

$MissingUpdatesReformatted = @($MissingUpdates | ForEach-Object {if($_.ComplianceState -eq 0){[WMI]$_.__PATH}}) 

$InstallReturn = Invoke-WmiMethod -Class CCM_SoftwareUpdatesManager -Name InstallUpdates -ArgumentList (,$MissingUpdatesReformatted) -Namespace rootccmclientsdk 

$objCurrentPSProcess = [System.Diagnostics.Process]::GetCurrentProcess();

Stop-Process -Id $objCurrentPSProcess.ID;

 

To kick this script off remotely on your servers, you can use a similar PowerShell command such as:

Invoke-Command { powershell.exe -executionpolicy unrestricted C:updatesInstallUpdates.ps1} -ComputerName Win2012Svr1

OR, to run against multiple servers at once… Lets Loop It!

$Servers = Get-ExchangeServer Win2012Svr*

$Servers | %{Invoke-Command { powershell.exe -executionpolicy unrestricted C:updatesInstallUpdates.ps1} -ComputerName $_}

Instead of using Software Center to check the status of your updates via an RDP session to multiple servers,  lets use PowerShell again to invoke a command that will return the EvaluationState for each update:

Invoke-Command -computername Win2012Svr1 -scriptblock {Get-WmiObject -Class CCM_SoftwareUpdate -Namespace rootCCMC
lientSDK | Group EvaluationState}

OR against multiple servers, Lets loop it again!

$Servers = Get-ExchangeServer Win2012Svr*

$Servers  | %{Invoke-Command -computername $_ -scriptblock {Get-WmiObject -Class CCM_SoftwareUpdate -Namespace rootCCMClientSDK | Group EvaluationState}}

Below is what we determined each status represents.  Obviously there are some numerical codes missing, but these are the normal status codes we occasionally see:

0 = Not Started
5 = Downloading
6 = Waiting to Install
7 = Installing
8 = Requires Restart
13 = Failed

To restart the computers remotely, you can issue the following PowerShell Commands:

Restart-Computer Win2012Svr1 -force

or multiple servers:

$Servers = Get-ExchangeServer Win2012Svr*

$Servers  | Restart-computer -force

Happy updating!

 

 

 

 

 

 

Compare 2 powershell variable arrays and show values that do not match.

Scenario:  When performing a migration, we noticed a discrepancy in the  count of users that are in a distribution group compared to the count of users that have move requests (the move requests  were originally generated from that distribution group).  We have to determine which mailboxes are missing.

Resolution: Here is a quick way of comparing those 2 lists:

1. Pull the Distribution Group Members into a Variable:

$1 = Get-DistributionGroupMember Migration_710 | Select Alias

2. Pull the Move Requests that were batch into a second Variable:

$2 = Get-MoveRequest -batchname Migration_710 | Select Alias

3. Export both of those Aliases into a CSV file:

$1 | export-csv C:1.csv

$2 | export-csv C:2.csv

4. Import those csv back into new variables :

$file1 = Import-csv C:1.csv

$file2 = Import-csv C:2.csv

5. Compare the lists by running the following command.  The output should be the missing objects.

compare-object $file1 $file2

Search a mailbox for a specific email without using OWA or Outlook.

Scenario:  A user is missing a message in their mailbox claiming it ‘disappeared’.  The possibilities are:

  1.  The message was accidentally deleted.
  2. The message was accidentally moved into another folder.
  3.  The message exists in the mailbox folder, except the items in that folder are not sorted correctly. Note:Sorting by the Received date will make all emails in that folder in chronological order

Solutions:

You could request permission from the user who owns the mailbox to allow you to have full access permission and search their mailbox via OWA — but this can be a little time consuming.  Instead  perform a ‘search-mailbox’ against the mailbox to locate the missing message:

Get a count of all messages that match the subject line:

Search-Mailbox jdoe1 -SearchQuery Subject:”Attention: Please Read this Email” -EstimateResultOnly

Create a copy of the messages that match the subject line:

Search-Mailbox jdoe1 -SearchQuery Subject:”Attention: Please Read this Email” -targetmailbox ExAdmin1  -searchdumpster

OR for a search with additional properties to be queried:

Search-Mailbox jdoe1 -SearchQuery {Subject:”Attention: Please Read this Email” AND from:”President@Domain.com”  AND Sent:”7/10/2015″} -Targetmailbox ExAdmin1 -searchDumpster

Note: it may request you to name a target folder so it can create that folder in the ExAdmin1 mailbox.  The search results will be then copied to that target folder in the folder hierarchy for where the messages are stored. For example, if there are messages in the inbox and deleted items of the mailbox being searched against, you will have the search results copied to the inbox and deleted items folder under the targetfolder that was created.

Commands to Create Mount Points from Unallocated Hard Drives

Scenario: You added new Hard Drives into your Windows Servers and you wish to  quickly partition these disks to be used as mount points. You can use the commands below to script it.

Commands:  We will be using DiskPart in order to accomplish this.

1. Open DiskPart: 

From a command prompt or powershell, type in diskpart and press enter.  A new DiskPart window should open up.

2. Determine the Disk Numbers of the newly installed disks:

List Disk 

3. Use the Disk Number  and use the commands below.  We are going to use Disk Number 3 as the newly installed disk. You can copy all the commands below at once and paste the commands into the DiskPart command window.

Select Disk 3
Create Partition Primary
Select partition 1
format  quick fs=ntfs Label=”MountPoint1″
Assign Mount=C:MountPoint1

 

Message Tracking to find the first hop into Exchange 2013

Scenario: You have added new Exchange 2013 servers to your existing Exchange 2013 environment and you just configured your perimeter devices to route SMTP email to the new servers in addition to the old servers.  You want to gather a log of emails to review to make sure no issues are occurring, but you first need to trace down which emails are coming into the new Exchange 2013 servers so you can trace those emails down until they are delivered into the mailbox.

Determine the IP address or the DNS host name of your perimeter devices and run the command below.  We will use the IP 10.10.1.2 as the perimeter system delivering email into the new Exchange 2013 servers.

PowerShell:

Get-transportserver NewServerName | Get-messagetrackinglog -start “7/7/2015 9:00am” -eventID Receive | Where EventData -like “*10.10.1.2*”

Note: The event data will display the term “firstforesthop” and the proxied connection info (Info of the Perimeter Devices). The term ‘FirstForestHop’  wasn’t a good way for us to rely on a query as we have had a mix of Exchange 2010 and Exchange 2013.  When it entered into Exchange 2013, it would have ‘FirstForestHop’ listed in the event data even if it wasn’t really the first forest hop as it came in from Exchange 2010.  But it did have the Perimeter device info in which did provide successful queries.