Tuesday, June 28, 2016

Adding Multiple Computer Objects to AD Group

Hi folks,

Just wanted to share with you about an adventure that I had when trying to add multiple computer objects for my server into an AD group. Let us imagine that we have set up naming convention where names for computer objects are well organized.

Add-ADGroupMember is the one to be used when you're adding your server objects into AD group and you can read about it here.  A command to add a single server object to a group is quite straightfoward:

Add-ADGroupMember -Identity SvcAccPSOGroup -Members SQL01

And it seems to be straightforward when you're trying to add more than 1 server, like below:

Add-ADGroupMember -Identity SvcAccPSOGroup -Members SQL01,SQL02

However, when I tried it I got an error. Therefore I decided to run my server objects one-by-one. To avoid typing command for each server objects I queried AD for all of them and fed to the $Mem variable. Please note that I'm using well defined naming convention and therefore it's simple for me to do so. After this I'm running the Add-ADGroupMember command against every server in the $Mem variable. The final code is as below:

 $Mem = Get-ADComputer -Filter {Name -like "MYSERVER00*"}
 $Mem |foreach {Add-ADGroupMember -Identity "MY Group Name" -Members $_.DistinguishedName}

And finally you can confirm group membership by executing the following command:

 Get-ADGroupMember -Identity "MY Group Name"

Now let's consider yet another scenario. Imagine you have mailbox (or CAS) servers in your Exchange platform that share part of common name while the other part varies depending on the AD site. Below code can be run from Exchange management shell with the AD PowerShell module loaded. First we retrieve Exchange servers of a certain role (Mailbox in my example) and feed them into a variable just as above, and this is where Exchange Management shell is in play. The we will add them to the group where they should be added.

The code will be as below:

$MbxMem = Get-MailboxServer EXCH* |foreach {Get-ADComputer -Identity $
 $MbxMem |foreach {Add-ADGroupMember -Identity "MY Group Name" -Members $_.DistinguishedName}

I hope you'll find it helpful.


Quickly Retrieving Local User Accounts

Hi folks,

Just wanted to share with you a quick way to retrieve local users (whether admin or non-admin) which exist on your computer or server. I found this article which explains how to do this. Out of the methods I used WMI method and for the parameters that I was outputting were Caption, Domain (the latter should be enough), as in my report I was trying to show the computer name where I was running the code.

So my code became as below:

Get-WmiObject -Class Win32_UserAccount -Filter  "LocalAccount='True'" | Select PSComputername, Name, Status, Disabled, AccountType, Lockout, PasswordRequired, PasswordChangeable, Caption, Domain 

I hope you find it helpful.


Friday, June 17, 2016

Temporary Server Error and HOSTS file

Hi folks,

Just wanted to share with you about yet another adventure I faced. When some of the application servers that were configured to use my Exchange 2013 servers farm behind the load balancer attempted to send email via them they were prensented with the following error:

451 4.7.0 Temporary server error. Please try again later. PRX5 Downstream

As I was talking to my older brother Google when investigating this issue all the articles including this one from Dell were pointing to the known bug with the Exchange 2013. Recommendations were to update receive connectors to listen on the primary IP address of the NIC and also update HOSTS file to include IP addresses of Exchange server there.

I personally haven't got to that point because I was more lucky. When I edited HOSTS file I found there weird IP addresses (outside of my IP address range) and Exchange servers' hostnames next to them. I removed all incorrect records from the HOSTS file and rebooted the server after which my applications were able to use SMTP on Exchange to send messages.

Therefore my advise if you have this error first check your HOSTS file for strange records before you try any further troubleshooting.


Tuesday, June 14, 2016

Add All Exchange 2016 Servers from the Site to DAG

Hi folks,

Just wanted to share with you with a script on how to quickly add new Exchange 2016 servers into DAG. Let's imagine scenario when you have introduced Exchange 2016 CU1 servers into an AD site which currently contains Exchange 2010 and 2013 servers. Let's also imagine that we have a proper and consistent naming convention (believe me, folks, it makes life sooooo easy). And of course let's assume that we have a good network infrastructure and fast AD replication.

If all of the above is truth and you are lazy to type command for each server or click Next button million of times then the below code is exactly for you. I made this script interactive so that you will need to type the name of your DAG (perhaps you have more than one AD site where you introduce Exchange servers with a different DAG in it). By this you won't need to edit this script every time when you move from site to site. Then you feed all your Exchange 2016 servers with the version "Version 15.1 (Build 396.30)" into the variable and then add them one by one. To allow AD replication occur (you know sometimes Microsoft Clustering solution are a bit temperamental and sensitive to the AD) I added 20 min for replication after each servers are added. This will allow you to kick of the script and have some time for drinking tea or reading TechNet :).

The code will look something like below:

$DAG = Read-Host "Type your DAG Name. For example: DAG01"
$ExchBox = Get-ExchangeServer $DAGSrv* | Where-Object {$_.AdminDisplayVersion -like "Version 15.1 (Build 396.30)"}
   $ExchBox |foreach {
                                      Start-Sleep -Seconds 600
                                       Add-DatabaseAvailabilityGroupServer -Identity $DAG -MailboxServer $_.Name
                                       Start-Sleep -Seconds 600}


Quickly Updating Domain Based Exlusions

Hi folks,

As you well know that in Exchange 2013/16 you can now configure some new conditions about which you can read here. Among them are RecipientDomainIs and SenderDomainIs which allow you to control transport rules based on the SMTP domain of a sender and a recipient of an email. Both of these attributes are multi-value attributes and are quite easy to manipulate from EAC.

Now imagine you have transport rule which manipulates email which are perform a certiain action when email is sent to one of the domains in the list. Let's say you need the same manipulation to be done also when email is sent to people from contoso.com domain. When using PowerShell by adding and removing domains while when you type something like:
Set-TransportRule "My Transport Rule" -RecipientDomainIs contoso.com

will overwrite all the current values.

Therefore something like the code below should do a magic for you.

$RecDom = (Get-TransportRule "My Transport Rule").RecipientDomainIs
$RecDom += "contoso.com"
Set-TransportRule "My Transport Rule" -RecipientDomainIs $RecDom

All you need to do is to feed the current list of SMTP domains into a variable (let's call it $RecDom). After which we update variable with a new domain (contoso.com in our case). And finally we will update RecipientDomainIs value with the updated variable. This will preserve the current list of SMTP domains as well as add the desired domain to the list.

The similar kind of manipulation can be done with the SenderDomainIs parameter as well.


Wednesday, June 8, 2016

Quickly Add a Signle Email Address to a Recipient

Hi folks,

Just wanted to share with you a quick way to add email addresses to Exchange recipients by using PowerShell. This is in case you are as lazy as I am and don't want to access recipient from the GUI tool like EAC.

The sample code is as follows for mailbox.

Set-Mailbox jsmith -EmailAddresses @{Add=’john.w.smith@contoso.com’}

The same can be applied for all kinds of recipients like contacts, distribution groups and so on.


DAG and ReFS

Hi folks,

When you are working on planning/deploying Exchange 2016 there's now a new good practice which MS published in the Exchange 2016 Preferred Arcitecture about file system used by database volumes. Now database volumes should be formatted with ReFS.

In this article 2 important considerations are added. Firstly, we will need to disable integrity streams bit on the database volume. This should be done during volume configuration and format. Don't miss it, otherwise you will have to re-do all your storage and even mailbox databases in DAG. In Windows 2012 R2 it can be done by the followig sample command (of course disk numbers and volume can vary in your environment):

Get-Partition –Disknumber 5 –PartitionNumber 2 | Format-Volume -FileSystem REFS -NewFileSystemLabel Volume3 -SetIntegrityStreams $false

Secondly, you will need to configure your DAG to user ReFS by as the file system. We need this to ensure that spare volume when used by AutoReseed is formatted by ReFS, rather than NTFS.

By default, file system for DAG is configured to be NTFS:

To confiure your DAG with ReFS as file system you will need to run the follwing command:

Set-DatabaseAvailabilityGroup NameOfYourDAG -FileSystem ReFS

I hope it will be extremely helpful for your DAG planning and deployment.


Friday, June 3, 2016

Quickly Retrieving Local Admins Group Members

Hi folks:

Just wanted to share with you the PowerShell code that can be used to retrieve members of the local admins group on your Windows server or client machine. I found it at this link and found it extremely useful.

The code to retrieve it can be

Get-WmiObject win32_groupuser |Where-Object { $_.GroupComponent -match ‘administrators’ } | ForEach-Object {[wmi]$_.PartComponent }

This provides detailed report as below (which even includes SID for each admin user):

Finally you can always adjust section { $_.GroupComponent -match ‘administrators’ } to any other group name in order to retrieve appropriate members.


Wednesday, June 1, 2016

Add Path to Exchange Scripts to Path Variable

Hi folks,

As you know when Exchange 2010 and later is installed on your Windows server it comes with a bunch of scripts that are used for configuration and maintenance of Exchange Server. They are usually stored in C:\Program Files\Microsoft\Exchange Server\v15\Scripts (for Exchange 2013/2016) or in C:\Program Files\Microsoft\Exchange Server\v14\Scripts (for Exchange 2010). I have slightly covered this subject in this blog post.

In order to run them you will navigate to the above folder or you can access them via $exscripts variable from Exchange Management Shell.

To simplify access to scripts you can add the folder where scripts are located to the system variable named Path. As you well know it is usually done by accessing System Variables section in the advanced properties of the system.

To make this process faster it can be achieved by executing the below script. Firstly, it's worthy to mention that directories in Path variable are stored in the Path value of the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment registry key.

The script extracts list of folders in the Path value and stores it in the $oldpath variable. Then it creates new variable $newPath which consists of all directories from the $oldPath and folder where Exchange scripts are stored. After this Path value in the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ is updated with all the directories stored in the $newPath variable.

The code will look like below.

$oldPath=(Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH).Path

$newPath=$oldPath+’;C:\Program Files\Microsoft\Exchange Server\v15\Scripts’

Set-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH –Value $newPath

Please note that I have tested this script with elevate privileges. And I recommend you running it under the same. After script execution you will need to restart the system and it will do the magic.

After restart just start your EMS and type first couple letters of any of Exchange scripts (for example RedistributeActiveDatabases.ps1) and hit Tab button. EMS should resolved it as below: