• Twice login screen when proxying Exchange 2003 Legacy URLs using Exchange 2010 OWA through FBA on TMG

     

     

    A good trick I got when I was doing one of the TQAs around. Here is the details:

    Situation:

    Coexistence between Exchange 2003 and 2010 OWA and the proxying is working just fine internally. When try to 2003 user try to access the published URLs (using 2010 FBA), he’s getting another FBA page for Exchange 2003.

     

    Solution:

    Remove the Legacy publishing from the OWA publishing rules (paths and accepted domain names). Create a new dedicated publishing rule for legacy that has the legacy URLs and the domain names and point it to Exchange 2003 FE directly.

     

    Works like  a charm! Try it and feedback!

     

    If you like the post, don’t be shy and hit the rating button up there Winking smile

     

    Mohammed Saad

  • Exchange 2010 Cross-Forest Migration Step by Step Guide – Part III

    In this part of Cross-Forest Migration Guide we will solve the second challenge but before that let’s take a look again on the current environment:

    Diagram

     

    Second Challenge: Move Mailbox Error:

    As explained in Part II, we will use ADMT first to migrate SID History, Password and other AD attributes then we will use Prepare-MoveRequest, the idea of these steps is to get healthy Mail Enabled User (MEU) that will be used later to move the mailbox from the source forest to the target forest, after finishing Part II now we have the healthy MEU and we can check the LDAP properties for the mandatory attributes required for the move to succeed.

     

    The following snapshot shows the LDAP attributes:

    Yahya05

     

    Now this is the time to run New-MoveRequest to migrate the mailbox from the source forest to the target forest.

    The following snapshot shows the result of running New-MoveRequest:

    clip_image006

    The error is: Cannot find a recipient that has mailbox GUID

     

    The error is clearly saying that there is no MEU with the mandatory attribute msexchmailboxguid, however when we check the MEU LDAP property:

    clip_image008

    The mailbox GUID is there (of course it’s there because Prepare-MoveRequest migrated this attribute, check Part II), so what’s the problem?!

     

    We have MEU with the required msexchmailboxguid and each time we try to migrate the mailbox we will get the same error: Cannot find a recipient that has the mailbox GUID.

     

    The problem here that when the remote forest implies a child name relationship, Exchange 2010 will think that this is a child domain and then the strange error will be returned. In our case the source forest name is egypt.tailspin.com and the target forest name is tailspin.com so Exchange will think that the target is child domain from the source forest and it will fail.

     

    So what’s the solution?

    We have two painful options:

    1. Export all mailboxes as PST files from the source forest and then import it in the target forest: this option is based on big bang approach where there is no co-existence. This option might be considered in small companies where we can disconnect the source forest, export the PSTs and import it to the target forest in reasonable downtime.

    2. Co-Existence: when co-existence is required in enterprise companies with thousands of users the only option will be creating Intermediate Forest.

     

    Intermediate Forest:

    As you might guess this will be our option as co-existence is required, in this option we will do the migration on two steps.

    First we will need to create a new Active Directory Forest with a different name in our scenario we will use nwtraders.com. This forest will contain Exchange 2010 server we can use single server with HUB/CAS/MBX installed on the same server, as this forest will be intermediate and will not serve any users you may decide that high availability is not required.

     

    Now the migration will be done on two steps as following:

    1. Move the mailbox of the user (batch of users) from the source forest egypt.tailspin.com to the intermediate forest nwtraders.com.

    2. Move the mailbox of the user (batch of users) from the intermediate forest nwtraders.com to the target forest tailspin.com.

     

    After implementing the intermediate forest it’s very important to complete the following tasks before starting the migration:

    1. Apply SSL certificate on the intermediate forest that can is trusted and can be validated from the target forest. If Exchange 2010 server in the target forest can’t validate the certificate moving mailbox will fail.

    2. Enable the MRS Proxy service: this service responsible of moving the mailboxes from/to Exchange 2010, as the intermediate Exchange server will be 2010 then moving mailboxes will not work without enabling the MRS Proxy service.

     

    The following section contains the detailed steps required to prepare the intermediate forest:

    1. Install SSL Certificate

    This certificate must be trusted and validated from the CAS servers in the target forest. The certificate could be generated from internal Certification Authority trusted by the CAS servers in Corp forest.

    The steps to request to install the certificate as follow (on Intermediate Forest Exchange Server):

    a. Request certificate:

    I. Open Exchange Management Shell:

    II. $data = New-ExchangeCertificate -GenerateRequest –domainname mail.nwtraders.com,autodiscover.nwtraders.com,servername.nwtraders.com -FriendlyName Int-CAS

    II. Set-Content -path "C:\CertRequest.req" -Value $Data

    b. Import the Certificate:

    I. Import-ExchangeCertificate -PrivateKeyExportable:$true -FileData ([Byte[]]$(Get-Content -Path C:\cert.cer -Encoding Byte -ReadCount 0)) | Enable-ExchangeCertificate -Services IIS

     

    2. Enable MRSProxy Service

    This step should be completed before moving the mailboxes from the Intermediate forest to the target forest.

    a. On the Client Access server in the Intermediate Forest (nwtraders.com), open the following file with a text editor such as Notepad:

    C:\program files\microsoft\Exchange\V14\ClientAccess\ExchWeb\EWS\web.config

    b. Locate the following section in the Web.config file:

    <!-- Mailbox Replication Proxy Service configuration -->

    <MRSProxyConfiguration
    IsEnabled="false"
    MaxMRSConnections="100"
    DataImportTimeout="00:01:00" />

    c. Change the value of IsEnabled to "true".

    d. Save and close the Web.config file.

     

    In this part we addressed the second challenge and now we are ready to start the migration, in the next part we will start by configuring co-existence between the three forests.

     

    Exchange 2010 Cross-Forest Migration Step by Step Guide – Part I

    Exchange 2010 Cross-Forest Migration Step by Step Guide – Part II

    Exchange 2010 Cross-Forest Migration Step by Step Guide – Part III

  • Exchange 2010 Cross-Forest Migration Step by Step Guide – Part II

    In Part I of this guide I’ve explained the process of cross-forest migration and the differences between using ADMT first or using Prepare-MoveReuqest.Ps1 script first, I’ve also explained the migration scenario and the current environment.

    Starting from this part we will talk about migration challenges and the best way to address these challenges.

     

    A quick reminder of the current environment:

    Diagram

     

    First Challenge: ADMT First Then Prepare-MoveRequest.Ps1:

    As explained in Part I, we need to migrate user accounts and mailboxes from the source forest to the target forest. However in the target forest (tailspin.com) we already have user accounts created manually for users in the source forest (egypt.tailspin.com), so each user in egypt.tailspin.com has two user accounts:

    • Primary Account: AD User in the Egypt forest used for Windows logon, email and everything.
    • Secondary Account: AD user account created in Tailspin.com forest used for other applications hosted in tailspin, this user used to grant permissions and create profiles on Terminal Service servers.

     

    So the main target is we need to use the existing users in the target forest (tailspin.com), the consequences of this decision as follow:

    1. We can’t use the script first; the script in this scenario will create a new disabled Mail Enabled User (MEU), and will ignore the existing user account.
    2. We will have to run ADMT first to synchronize the password, migrate SID history, and other AD attributes from the source forest to the target forest.
    3. We need to provide prepare-moverequest.ps1 with attribute that links the user in the target forest with the user in the source forest, so when the script runs it will merge all the properties from the source account to the target account and will not create a new user.

     

    Before going to the detailed steps, let’s see the history and the relation between ADMT and Prepare-MoveRequest.Ps1:

    • ADMT and Exchange Attributes: By default ADMT doesn’t migrate Exchange attributes including “mail”, “proxyAddresses”, anything started by msexch. The reason behind that because when ADMT transfers Exchange attributes (e.g. homeMDB, homeMTA, showInAddressBook, msExch*) that will make the target user looks like a legacy mailbox in the target domain. This leaves the target account in an invalid state (e.g. homeMDB still points to the old forest) which is unexpected for the PrepareMoveRequest.ps1 script. To prevent this, Exchange attributes are excluded from ADMT.
    • In Exchange RTM, running ADMT first and then running the PrepareMoveRequest script: When a user is created via ADMT, the PrepareMoveRequest script doesn't work since there are no proxyAddresses for the script to match the source forest user with the target forest user (the script is looking for some attributes in the target account and try to match it with the source account).

    The recommended approach was to copy at least 1 proxy address using ADMT. Even after doing that and using the -UseLocalObject parameter, the script will only copy the 3 mandatory parameters (msExchMailboxGUID, msExchArchiveGUID, msExchArchiveName). This is not very useful as the other mandatory attributes are not copied.

    • In SP1, a new switch has been added –OverwriteLocalObject which mainly designed when running ADMT first scenario. ADMT can copy the SIDhistory, password, and proxyAddresses, and the PrepareMoveRequest script can attach the source account with the target account and sync the other email attributes. In this case, it will copy attributes from source to target, so it's the opposite of UseLocalObject.

     

    PrepareMoverRequest.ps1:

    The PrepareMoveRequest.ps1 script can identify and match existing accounts in the target forest based on their SMTP address (proxyAddresses attribute).

     

    The script will only use the existing target accounts if all the following are true:

    • The target account has a value in proxyAddresses which matches one of the proxyAddresses of the source account.
    • The target account is a mail enabled user (healthy MEU that can be retrieves with Get-MailUser command, which means it must have mail attributes like 'mail', 'ExternalEmailAddress', etc).
    • You need to specify the -UseLocalObject parameter in the script. (and –OverwriteLocalObject)

     

    If all these are true, the script will copy further attributes needed (especially msExchMailboxGUID) to the target account so that the move request can process the accounts.

    If one of the above items is missing, the script will duplicate by creating a new disabled Mail Enabled User (MEU), and no error will be returned, using the script in verbose mode will let you see the details.

     

    Based on that the steps to solve this challenge should be:

    1. Select the user or patch of users to be migrated.

    2. Delete any Mail Contact for the users in the target forest.

    3. Use ADMT to migrate the user account (merge) from source forest to target forest, this is required to get SID History and sync the password.

    Once ADMT migration is completed we should have normal user accounts with SIDHistory as the following snapshot:

    clip_image004

     

    4. Make the user (or patch of users) Mail Enabled User (MEU) (by running Enable-MailUser), setting ExternalEmailAddress matches the same email address of the user in the source forest (this will be the anchor to associate the user in the target forest with the user in the source forest).

    The following snapshot shows how to do it for bulk users using (Import-CSV)

    clip_image006

     

    We have a very simple csv file that contains two fields as the following snapshot:

    clip_image008

     

    Now we should have a healthy MEU ready for Prepare-MoveRequest, the following snapshot shows the LDAP properties of this user account:

    clip_image010

    Check the proxyAddresses, mail, and mailNickname.

     

    5. Use Prepare-MoveRequest.Ps1 with –uselocalobject and –overwritelocalobject, so the script will use the existing user account and overwrite the attributes in the target account by the attributes in the source account and most importantly migrate all the required attributes, so the MEU is ready to move the mailbox.

    Again we can do it for bulk users by using (Import-CSV), the following snapshot shows the command in verbose mode:

    clip_image012

    Check the first two lines, local account has been found and the anchor (proxyAddresses) has been used to identify it, then Merge will be done, last line indicates that the process is successfully completed.

    Now we have MEU ready to move the mailbox.

     

    In this part we solved the first challenge, in the next part we will continue with the second challenge before moving to the technical steps of the migration.

     

    Exchange 2010 Cross-Forest Migration Step by Step Guide – Part I

    Exchange 2010 Cross-Forest Migration Step by Step Guide – Part II

    Exchange 2010 Cross-Forest Migration Step by Step Guide – Part III

  • Linking ListViewWebParts in Sandbox environments

    Problem Statement

    You have a requirement to display two list view web parts of two SharePoint lists. These two lists are linked together using a multi-valued lookup field in one of them. So for example you have a list called Companies and another called Branches and in the list of Companies you have a multi-valued lookup field to the list of branches. Please note that the field is in the Companies list not the branches list and it is done so as per the requirement to be able to browse all branches of a specific company by simply opening the company item.

    Possible Solutions and Challenges

    So the first thing you would thing so what this shouldn’t be that hard right. SharePoint has out of the box a web part connection feature out of the box. So you create a page, add two list view web parts to it and configure them so that the Companies web part would provide the row value to the Branches web part. The branches web part accepts the lookup value as a filter parameter linked to the name of the branch. Well this will not work as you see the lookup parameter is multivalued and also it is not text parameter so it passes a value such as “1#Branch1;2#Branch2;” this value will not match any Branch name and hence the filter will remove all values.

    The second attempt I thought about was to create a custom web part to do this; and then it hit me; this is a sandbox solution so I cannot actually instantiate a ListViewWebPart from my custom web part so this means I will re-write all ListViewWebPart logic using ASP.NET controls Sad smile.

    The third thing I tried was to create a Silverlight web part (so this adds good looks also) and then add that web part to the page. But this is a sandbox environment and it has the client object model and the data services disabled and I cannot enable them.

    The solution

    So what I ended up doing is that I added the two web parts to the page and then I edited this page using SharePoint designer. So in SharePoint designer I created a new custom parameter in the Branches web part. Then I created a web part connection so that the Companies web part would pass the row value to the Branches web part. The branches web part would then link the lookup field value to the custom parameter. Finally I created a conditional formatting rule on the Branches web part so that it hides the row using an advanced condition that would look like this.

    not(contains($BranchLookup,@Title))

  • NullReferenceException when trying to get the AdapterReceiveCompleteTime property

    So you are implementing a custom BizTalk tracking solution using the BAM APIs. In this solution you need to track when the message arrives at the receive port exactly and even before the receive pipeline starts to execute. so simple right you just end up doing something like this.

    image

    BUT BAM (not the BizTalk BAM but something blowing up) a NullReferenceException is thrown. Strange!!! and also the strangest part is that you will find that on some environments it works and on others it throws this exception.

    Well the  issue here is related to the tracking setting for the receive port. If you enable tracking of message bodies on the receive port somehow this property is removed from the message context.

    image