Tuesday, December 9, 2014

New Exchange patches

UPDATE:
the Exchange 2010 Rollup8 has a bug in it so Microsoft removed the download link and will replace this rollup. If you happen to be fast and already installed KB2986475, Microsoft recomend to uninstall it and wait for the updatged rollup.Exchange Server 2013 Cumulative Update 7 (CU7) is released.
A version 2 of Exchange 2010 SP3 UR8 is now released, download here.
 
Exchange 2013 Cumulative Update 7.
Download link and KB2986485
Exchange Server 2010 Service Pack 3, Update Rollup 8.
Download link and KB2986475
Exchange Server 2007 Service Pack 3, Update Rollup 15.
Download link and KB2996150
Notice that there is Active directory schema updates that must be applied before installing Exchange 2013 CU7.

Sunday, November 30, 2014

Exchange cmdlet Extension Agents

Cmdlet extension agents are components within Exchange 2013 that are invoked when Exchange cmdlet’s run. Agens can do additional action when Exchange cmdlet are run such as modify,add functionality or validate input parameters.

Several agents exists out of the box when installing Exchange 2013. Run Get-CmdletExtensionAgent to see. note that they can be disabled/enabled and have a priority.

image

The one agent we can manipulate with ease is the “Scripting Agent”. It runs Exchange cmdlets located in an XML file, $exbin\CmdletExtensionAgents\ScriptingAgentConfig.xml. This file does not exists by default but there is a sample file in the same directory which contains examples.

The most common scenario I would think of is to run some cmdlet after a cmdlet is run. for example. when you create a mailbox you can also run some cmdlet to set some additional parameters on the mailbox. My example here is to enable SingleItemRecovery and also change de default permission on calendar to LimitedDetails for everyone to see the subject of calendar objects.

   1: <?xml version="1.0" encoding="utf-8" ?>



   2: <Configuration version="1.0">



   3:     <Feature Name="MailboxProvisioning" Cmdlets="Enable-Mailbox">



   4:         <ApiCall Name="OnComplete">



   5:             if($succeeded) {



   6:                 $ErrorActionPreference = "SilentlyContinue"



   7:                 $MaxTime = 60



   8:                  for ($LoopVar = 0;$LoopVar -lt $MaxTime;$LoopVar++) {



   9:                     if($provisioningHandler.UserSpecifiedParameters["Identity"] -ne $null) {



  10:                     $user = Get-user $provisioningHandler.UserSpecifiedParameters["Identity"] 



  11:                     $mbx = Get-Mailbox $user.DistinguishedName



  12:                     If (-not($mbx)) {



  13:                         Start-Sleep 1



  14:                         continue # with the for loop



  15:                     } 



  16:                     else



  17:                     {



  18:                         # Enable SingleItemRecovery



  19:                         Set-Mailbox $mbx -SingleItemRecoveryEnabled $true



  20:                         WriteToLog (' enabled singleitemrecovery on ' + [string]$mbx.alias)



  21:                         # set sharing permissoin on calendar folder



  22:                         $CalendarName = (Get-MailboxFolderStatistics -Identity $mbx.alias -FolderScope Calendar | Select-Object -First 1).Name



  23:                         $folderID = $MBX.alias + ':\' + $CalendarName



  24:                         Set-MailboxFolderPermission -Identity $folderID -User 'Default' -AccessRights 'LimitedDetails'



  25:                         WriteToLog (' set sharing permission on calenderfolder on ' + [string]$mbx.alias)



  26:                         break # out of for loop



  27:                     }



  28:                     }



  29:                 }



  30:                 $ErrorActionPreference = "Continue"



  31:             }



  32:         </ApiCall>



  33:     </Feature>



  34:     <Feature Name="MailboxProvisioning" Cmdlets="New-Mailbox">



  35:         <ApiCall Name="OnComplete">



  36:             if($succeeded) {



  37:                 $ErrorActionPreference = "SilentlyContinue"



  38:                 $MaxTime = 60



  39:                  for ($LoopVar = 0;$LoopVar -lt $MaxTime;$LoopVar++) {



  40:                     if($provisioningHandler.UserSpecifiedParameters["Name"] -ne $null) {



  41:                     $user = Get-user $provisioningHandler.UserSpecifiedParameters["Name"] 



  42:                     $mbx = Get-Mailbox $user.DistinguishedName



  43:                     If (-not($mbx)) {



  44:                         Start-Sleep 1



  45:                         continue # with the for loop



  46:                     } 



  47:                     else



  48:                     {



  49:                         # Enable SingleItemRecovery



  50:                         Set-Mailbox $mbx -SingleItemRecoveryEnabled $true



  51:                         WriteToLog (' enabled singleitemrecovery on ' + [string]$mbx.alias)



  52:                         # set sharing permissoin on calendar folder



  53:                         $CalendarName = (Get-MailboxFolderStatistics -Identity $mbx.alias -FolderScope Calendar | Select-Object -First 1).Name



  54:                         $folderID = $MBX.alias + ':\' + $CalendarName



  55:                         Set-MailboxFolderPermission -Identity $folderID -User 'Default' -AccessRights 'LimitedDetails'



  56:                         WriteToLog (' set sharing permission on calenderfolder on ' + [string]$mbx.alias)



  57:                         break # out of for loop



  58:                     }



  59:                     }



  60:                 }



  61:                 $ErrorActionPreference = "Continue"



  62:             }



  63:         </ApiCall>



  64:     </Feature>



  65:  



  66:     <Common>



  67:         <!-- common functions -->



  68:  



  69:         function WriteToLog {param ([string]$text)



  70:             $t = Get-Date -Format yyyyMM



  71:             $LogFile = 'C:\temp\scriptingAgent_' + $t + '.log'



  72:  



  73:             # $text = text to be written to logfile



  74:             $t = Get-Date -Format yyyyMMdd:HHmmss



  75:             $text = '[' + $t + '] ' + $text



  76:             $text >> $LogFile



  77:         } #end function LogToFile



  78:     </Common>



  79:  



  80: </Configuration>




the XML elements to notice here is Feature, ApiCall and Common. Feature hold the Cmdlet attribute , here you put in the Exchange cmdlet you want to do something with. ApiCall you enter what you want to do, I use OnComplete which will trigger after the cmdlet in feature element.

Both Feature and ApiCall can be in the XML file multiple times.


You can see in my example here (line 3 and 4) that the *Scripting Agent” will run a script block after Enable-mailbox is completed. I start by doing a trick to allow the Active Directory replication have a chance to finish before we actually do something. line 19 to 25 is where the stuff I actually want to happen after Enable-Mailbox.


Line 34,35 is when you run New-Mailbox. I could have have the New-Mailbox and Enable-Mailbox together but separated them because in they use different anchor to the mailbox (line 10 and 41).  
The common section in the XML file contains a small powershell function to write some information to a text file.



Other things I hear customer do is to apply some policies to mailboxes and disable things such as pop/imap.

So now that you have a XML file to work with you can simply add your own logic when some Exchange cmdlet is run and not only to when provisioning mailboxes, it could be for DL’s or whatever your imagination can come up with.



Of course you must enable “Scripting Agent” with

Enable-CmdletExtensionAgent “Scripting Agent” and also copy your XML file to every Exchange server in your environment.

Thursday, August 21, 2014

Exchange Health Manager bug

You hopefully know that Exchange Health Manager monitor the Exchange server by sending Probes. The result is picked up by Monitors which decide if a Responder needs to do something about the problem.

The other day I found that a HealthSet on the server was UnHealthy. This was found by running this commands.

Get-HealthReport -Server ex1 | where {$_.AlertValue -eq 'UnHealthy'} | ft –AutoSize

Result showed that “OutlookMapiHttp” HealthSet was to blame.
You can trigger a probe to execute at any time, first we need to know what the probe name is.

Get-MonitoringItemIdentity -Server ex1 -Identity OutlookMapiHttp | ft Identity, ItemType, Name

Result show the probe name for the OutlookMapiHttp HealthSet, “OutlookMapiHttpCtpProbe”.

Since we are dealing with outlook connectivity problem here we should use the Test-OutlookConnectivity cmdlet to trigger the probe to run.

Test-OutlookConnectivity -RunFromServerId ex1 -ProbeIdentity OutlookMapiHttpCtpProbe

Another way of trigger the probe would be
Invoke-MonitoringProbe -Server ex1 -Identity OutlookMapiHttp\OutlookMapiHttpCtpProbe

Both cmdlets took a about 90 seconds before they come back with a result saying “Failed to find proberesult”
Could this be a performance issue? This server showed no peformance related problem, it is actually a oversized box.
I fired up event viewer and looked in different eventlogs under Microsoft\Exchange\ManagedAvailability and Microsoft\Exchange\ActiveMonitoring. Events here show probe definitions and firing, monitors reading probe results and what responders do and the result of responders as well. The best way of reading this info is to switch from General to Details and filter on Errors.

I could find snippet of text “The remote server returned an error (404). Not Found and a reference to a Health Mailbox.
This was strange. monitoring mailboxes is created on demand when the Health Manager service do its thing, so I trigger a restart of it but no difference. waited several hours and did a reboot but no difference even when waiting until the next day.
Discussed this with en engineer at Microsoft and he eventually suggested to change the time zone on the server from the current GMT+1 to a time zone used in America. Did that and nothing happened. In desperation I rebooted the server again and bang, now the “OutlookMapiHttp” healthset showed Healthy.
I played around with time zone and restart of Exchange Health Management service and could make the problem come and go as I changed time zone.

I haven’t tried all time zones but it looks like if you’re using GMT+something this bug will surface.
f you don’t want to change time zone on server you can create on monitoring overide.

Add-ServerMonitoringOverride -Identity OutlookMapiHttp\OutlookMapiHttpCtpMonitor -ItemType monitor -PropertyName Enabled -PropertyValue 0 -Server ex1 -ApplyVersion 15.0.913.22

In a few minutes you would see your healthset go healthy. together with the OutlookMapiHttp healthset there is also another healthset that also shows unhealthy “OutlookMapiHttp.Proxy” and is subjct to same bug with time zone. to make an override for it use.

Add-ServerMonitoringOverride -Identity OutlookMapiHttp.Proxy\OutlookMapiHttpProxyTestMonitor\MSExchangeMapiFrontEndAppPool -ItemType monitor -PropertyName Enabled -PropertyValue 0 -Server ex1 -ApplyVersion 15.0.913.22

We can only hope that this is fixed in the next CU of Exchange 2013.

Thursday, August 14, 2014

Outlook update

Microsoft published an update for outlook 2013 on August 12. It was suppose to fix several things.
Sadly it also introduced a bug where you could not get access to Exchange archive in some circumstances.
Well so it happens that Microsoft has now reacted and pulled the update for further investigation. If you have already installed this patch and encounter problem you could easily uninstall it.

Read KB2881011 for more info.

So another update that introduces problem. It feels like Microsoft don’t test updates that much anymore My guess is that the “Cloud/Mobile first” mantra Microsoft advertise makes the internal processes at Microsoft spin a little to fast and then quality is sacrificed. This is something we have seen the last year and I can only hope it gets better.

Monday, July 28, 2014

Using Windows 8.1 mail app without a Microsoft account

Running Windows 8.1 you have a choice of either using Microsoft account/local account or an Active Directory account if the computer is joined to an Active Directory domain.
Having the computer joined to an AD domain is the common scenario in the corporate world and you then most of the time use the Active Directory account to logon to the computer. To do email and calendaring there is big chance you’re using Outlook but what if you want to run the built in mail app in windows 8?  When starting mail app you’re then prompted to change the computer settings to logon/sign-in with a Microsoft account.
image
This will of course not go very well when computer is joined to an AD domain so what to do?
When using a domain joined account you might see this wizard instead if the Switch to a Microsoft account.
image

Happy you enter your corporate email account and password but the wizard comes back with bad password and prompt you to enter the information correctly. It seems that it only works for hotmail/LiveID/Microsoft accounts and not for a regular Exchange account. So what to do?

I found a group policy setting “Administrative Templates\Windows Components\App Runtime\Allow Microsoft account to be optional”.
If you enable this policy , mail app won’t prompt you to change computer settings to use Microsoft account but instead simply prompt for corporate account and password for the email account you want to use. This policy can be set either on user or computer and as a local policy. Description for the policy implies that other windows store app might behave similar as mail app do and allow user to enter the corporate creds instead of the Microsoft account.
Mail app uses the computer policy to configure this setting.

Time to edit a group policy perhaps ?