Thursday, July 31, 2014

Who Shutdown Your Exchange Servers

Hi folks,

Let me share with you a small script that will help to identify when and by whom Exchange servers have been restarted. Since it queries Event Log it can be used for all the other servers, no matter what role they are running.

What the script does checking System log of your Windows box for event 1074 and then you can output details that you need to CSV file.

In my case I'm running this script against Exchange servers which are the part of AD domain (which excludes Edge Transport servers). You can run it on Edge servers locally and therefore script text will slightly change (with no need to create variable that has all Exchange servers.

Therefore my text looks like this:

$ExServers=Get-ExchangeServer | Where-Object {$_.ServerRole -ne "Edge"}

$ExServers | foreach {Get-EventLog -ComputerName $_.Name -LogName system |Where-Object {$_.EventID -eq "1074"}} |Select EventID,MachineName,Message,TimeGenerated,TimeWritten,UserName |Export-Csv D:\Software\Event-1074.csv

Enjoy, hope it helps you as it did help me.

Wednesday, July 30, 2014

Dealing with Failing Exchange 2010 Multi-Role Server Installation

Hi folks,

I would love to share about one more adventure I recently had with one of my clients' messaging platforms. I needed to install additional CAS/HUB servers in order to support hybrid deployment with Office 365 and further migration into the cloud.

What can be simpler that that. I have got 3 VMs running Windows 2008 R2 on which I have installed all the prereqs as listed here.

However, when running step of installing and configuring multi-role server my installation would stumble and fail at the point of installing Exchange management tools. with the error as below:

 Exchange Management Tools                                 FAILED
     The following error was generated when "$error.Clear();  Set-WERRegistryMarkers; " was run: "Provisioning layer initialization failed: '"Scripting Agent initialization failed: "File is not found: 'c:\Program Files\Microsoft\Exchange Server\V14\Bin\CmdletExtensionAgents\ScriptingAgentConfig.xml'.""'".

The investigation lead me that the cause of the problem is Cmdlet Extension Agents which requires ScriptingAgentConfig.xml to be present on  a server. And since it's a brand new server of course this file is not there.

As a result some of Exchange files are installed on the affected server, however server roles are not configured and no changes in Active Directory are done.

To resolve this problem first you will need to run on one of the Exchange 2010 servers in your organization the following command:

Disable-CmdletExtensionAgent -Identity "Scripting Agent"

This will temporarily disable you from running modified or extended Exchange 2010 cmdlets, but it will allow you to successfully complete Exchange 2010 installation.

After disabling Scripting Agent you can re-run Exchange 2010 installation. 

Optionally, you can uninstall failed Exchange 2010 installation as did because I prefer nice and clean installations. In my case I had to run installation couple times as one of uninstallations failed with the error like this one (which is result of a lame installation):

This uninstallation simply removes the files installed earlier.

After that you can run Exchange installation again using your favorite installation method. Just in case details about Exchange installation can be found here for 2013 and here for 2010.

In my case I ran /m:Install /r:CA,HT /InstallWindowsComponents to install Exchange 2010 CAS/HUB server with Windows prereqs and installation went successfully.

After the installation is over you will need to rename file named ScriptingAgentConfig.xml.sample which is installed into C:\Program Files\Microsoft\Exchange Server\V14\Bin\CmdletExtensionAgents. Otherwise Exchange tools will fail starting pointing to the similar error as installation.

You simply right-click the file and remove sample from its name, so it becomes XML file.

Finally,  after the installation of all my multi-role servers was over I have enabled Scripting agent back by running

Enable-CmdletExtensionAgent -Identity "Scripting Agent"

I hope this will be of a great use to you.

Tuesday, July 29, 2014

Slipstreaming Rollup Updates Into Exchange 2010 Installation

Hi folks,

If you are working on a large deployment of Exchange 2010 servers in addition to the latest service pack (SP) you will also need to have latest Rollup Update (RU) installed. Please note that Service Pack installations are the separate builds and there's no need to integrate them into Exchange installation files. So for example to install SP3 you simply need to extract files and run installation running setup.exe (for GUI) or (for unattended).

Back to RU now. Slipstreaming process is fairly easy. All you need to do is to place MSP file for the latest RU into the Update subfolder of your Exchange 2010 installation folders.

After that you run installation command and wait for the end of installation.

And here you go! In my case I have installed Exchange 2010 SP3 with RU5 without any additional effort.

And when you check Exchange version using Exchange Management Console (for some reason in 2010 PowerShell doesn't reveal RU version information) you are getting 14.03.0181.006 which corresponds to RU5 for SP3 (as it is my scenario). This may differ in yours.

Alternatively, you can find it in Windows Updates applet of Control Panel by running see Installed Updates.

Please note that you will need to keep this file structure available to you for any installs, uninstalls or updates of your Exchange build on a server you installed it at.

Finally, in Exchange 2013 the servicing model has been changed and you now have Cumulative Updates (CU) published every quarter and SP published every year. Every CU and SP is now a separate build, so they can be installed using Setup /m:Install on the new servers and Setup /m:Upgrade on the new servers.


Friday, July 11, 2014

Reporting Mount Points for Mailbox Servers

Hi Folks,

Recently I had one more adventure.

I extremely love my customers, especially those who have a good standardization and conventions in their infrastructure. One customer of mine had pretty strict requirements for size of LUNs for database files and transaction logs.

However 2 things happened. Once their backup had got broken which as you know would result of transaction logs not being truncated and disk space usage grow presenting the threat of dismounting of database. This resulted into extending size of LUNs used by transaction logs and further discrepancy in disk size.

So my task was to determine which LUNs don't have standard size so that their size can be squeezed back to a standard one. LUNs were presented to mailbox servers as mount points.

In order to discover their size I decided that I generate a script that would report information about mount points and generate a nice CSV files that can be later processed by Microsoft Excel.

My greatest thanks to the author of  this article as I used it as basis for my script.

First I defined variables so that data is output into CSV in gigabytes instead of bytes. And after that I defined a variable for all mount points which then I have output into CSV file.

And I ended up with script that exports information about absolutely all mount points that I have across my client's Exchange estate:

$TotalGB = @{Name="Capacity(GB)";expression={[math]::round(($_.Capacity/ 1073741824),2)}}
$FreeGB = @{Name="FreeSpace(GB)";expression={[math]::round(($_.FreeSpace / 1073741824),2)}}
$FreePerc = @{Name="Free(%)";expression={[math]::round(((($_.FreeSpace / 1073741824)/($_.Capacity / 1073741824)) * 100),0)}}

$MPoints = Get-MailboxServer |foreach {Get-WmiObject -computer $_.Name win32_volume | Where-object {$_.DriveLetter -eq $null}} 
$Mpoints |Select SystemName,Name, Label, $TotalGB, $FreeGB, $FreePerc |Export-Csv D:\Scripts\Mount_Points_All.csv

I have also done some tweak to make output of a particular mount points I was interested in. I needed information of all mount points which are larger than 100 GB and smaller than 855 GB, so I ended up with the filter {$_.Capacity -gt  107374182400 -and $_.Capacity -lt  918049259520} which is calculated by converting GB into bytes, so the code looked like:

$MPoints |Where-object {$_.Capacity -gt  107374182400 -and $_.Capacity -lt  918049259520} | Select SystemName,Name, Label, $TotalGB, $FreeGB, $FreePerc| sort-object SystemName,Label | Export-Csv D:\Scripts\MountPoints_Oversized.csv

And of course you can come up with different other filters that will allow you to extract the exact information you may need.

In my case I have ended up with the nice Excel file as below:


Tuesday, July 1, 2014

Easy Checking Message Tracking Log Across All Servers

Hi Folks,

This is a quick tip on how to extract information from message tracking logs. Exchange has nice GUI tools like Message Tracking which used ECP, EAC and Tracking Log Explorer. However we can use them against a single server (even it's remote) at a time.

The following commands allow you to extract message tracking information from all Hub Transport servers at the same time. Let's imagine the following scenario: you have Hub Transport server role co-located with CAS on the servers. And also you are trying to find all emails that were sent to a user named John Smith with email address from a user Mary Jones with email address (of course nothing personal, these names are fictional here).

First I created variable called $Hubs which I populate with Hub Transport servers.

If you have separate Hub transport server roles you can use (and no Edge servers will be there simply because they are not present):


If you have Edge servers in your Exchange topology then the following command is for you

$Hubs=Get-ExchangeServer | Where-Object {$_.ServerRole -like "HubTransport"}

And finally in my scenario where I have Edge servers in topology and Hub Transport servers also has CAS role running, I have populated my $Hubs variable this way (since I don't need edge servers there because I was looking only for internal emails):

$Hubs=Get-ExchangeServer | Where-Object {$_.ServerRole -like "ClientAccess, HubTransport"}

Afterwards I have run Get-MessageTrackingLog command against each Hub Transport server in $Hubs variable with specifying

$Hubs |foreach {Get-MessageTrackingLog -server $_.Name -Sender -Recipients}

This command can be even better filtered by using -Start and -End  with dates and times specified (to search limited to certain dates) or any other parameter.You can check all the parameters for Get-MessageTrackingLog command here .

And finally report can be outputted as list (Format-List) to see every single detail for each SMTP transaction, though very hard to read or you can output it to CSV file using Export-CSV command. Something like:

$Hubs |foreach {Get-MessageTrackingLog -server $_.Name -Recipients} |select EventId,Source,Sender,@{N="Recipients";E={$_.Recipients}},MessageSubject,TimeStamp |Export-Csv D:\Software\Output.csv


Playing with RBAC and Roles

Hi folks,

Today let me share my experience with creating and managing role groups. RBAC is a very good security engine in Exchange 2010 and 2013 to manage administrative access by providing to administrative users only rights necessary for them to perform on the daily basis. In couple words a user is limited to a number of PowerShell commands he or she may execute or to certain sections in EMC or EAC he or she may access. I will not go into many details about this as you can read this article nicely provided in Technet.

In my case I was using standard roles created by Exchange 2010 by default with no customization which I was assigning to the newly created role groups.

Below commands are used to manage role groups and assignments.

First of all we create a role group (let's say for Level 1 engineers)

New-RoleGroup Level1

After this we assign role to a group. The following command allows to do it one-by-one

New-ManagementRoleAssignment -SecurityGroup Level1 -Role "Message Tracking"

We can check if rules were successfully assigned to this group:

Get-RoleGroup IPsoft-L1 |fl Roles

The above commands are quite simple and straightforward. Let me share one case when I needed to mimic one role group configuration between lab and production environment (which should be a normal case for any messaging environment and not only messaging).

For the sake of this article let's call this group Level3 as it will be serving admin needs of level 3 IT engineers to whom I don't want to assign Organization Management permissions.

First I have checked all roles assigned to the role group created in the lab:

Get-ManagementRoleAssignment -RoleAssignee Level3 |select Role,RoleAssigneeName

RoleAssigneeName corresponds to a user or a group to which a particular role is assigned. Of course as output of this command I will get the name of the same group assigned to it, but in the next step you will see how I used this to easily recreate this role in my production environment.

I used the same command, however instead of outputting it to screen I have exported results into a CSV file like below:

Get-ManagementRoleAssignment -RoleAssignee Level3 |select Role,RoleAssigneeName |Export-Csv D:\Software\Roles-i3.csv

I have ended up with the output like below:

As you can see I have 2 columns named after attributes I have exported Role,RoleAssigneeName . I will use them in the next command as parameters for -SecurityGroup and -Role.

As you can guess, I had imported username into pipeline and executed ManagementRoleAssignment against each of them with the parameters mentioned above.

Import-Csv .\Roles-i3.csv |foreach {New-ManagementRoleAssignment -SecurityGroup $_.RoleAssigneeName -Role $_.Role}

This simple command is used to add a users into a role group one-by-one:

Add-RoleGroupMember Level3 -Member "Farhad Mahmudov"

If we go back to my previous example of transferring role group between test lab and the production environment, I will show you some magic that I have done in my environment to import mailboxes from lab to production (provided your AD environment in the target environment is not populated as it was in my case)

First, I have extracted group members in my lab with the necessary details and exported detailes necessary for further mailboxes provisioning to CSV file:

Get-RoleGroupMember Level3 |Get-User |select Name,DisplayName,SamAccountName,UserPrincipalName | export-csv D:\Software\Level3.csv

I have transferred CSV file into my production environment and there provisioned mailboxes (please ensure that there are no trailing spaces after name or display name, otherwise you will have some grief of cleaning this out of CSV file). Please note that here I was using standard password for eevery admin which they were required to reset afterwards for security reasons.

$Password = Read-Host "Enter Users Password" -AsSecureString

Import-Csv C:\Scripts\Level3.csv |foreach {New-Mailbox -Name $_.Name -SamAccountName $_.SamAccountName -UserPrincipalName $_.UserPrincipalName -DisplayName $_.DisplayName -Password $Password}

Then I ran this code to simply check if users and mailboxes are created:

Import-Csv .\Level3.csv |foreach {Get-User $_.Name}

As you can guess mailboxes creation was successful. Finally, after that I ran Add-RoleGroupRoleMember command against each user of imported CSV file to add them to this group as members:

Import-Csv .\Level3.csv |foreach {Add-RoleGroupMember Level3 -Member $_.Name}

I hope this will be very beneficial in your daily messaging management.