Tuesday, May 31, 2016

What Domain Controllers are in My Site

Hi folks,

Below is a quick script to retrieve domain controllers that are located in the same site as a computer on which your computer or server is located.

This is required for scenarios when you are trying to understand which DCs can be used for LDAP/GC queries by your computer or server.

So basically what it does it loads value of the AD site name where computer is located and feeds it to the $ADSite variable. Then it queries domain controllers by using $ADSite as a variable in order to retrieve domain controllers located in the same AD site:

$ADSite = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite().Name
Get-ADDomainController -Filter {Site -eq "$ADSite"}

I hope you can find it helpful.

Enjoy!

Saturday, May 28, 2016

Resolving Transport Service Pile Up related to DNS Issues

Hi folks,

Just wanted to share with you about my recent adventure. This applies to Exchange server versions 2010, 2013 and 2016. I have noticed pile up of the messages in the queues.There were thousands and thousands of them. Queues were in the Retry state with the following error:

The error was like the one below:

last error 4.4.0 DNS query failed. the error was:DNS query failed with error Error Retry

It was interesting as I had absolutely healthy DNS. Suspending and retrying queues didn't do its magic. So I went to the Event Viewer to find the following errors in the Application Log for Transport service (error 205 was followed by error 16025):



Investigation lead me to this TechNet blog post and this forum thread. The rest of the blog posts were similar to the former one. However the latter was the magic silver bullet to solve my problem.

I have checked my advanced IPv4 address configuration to discover the following:


After checking the "Register this connection's address in DNS" and restarting Microsoft Exchange Transport service on the affected server functionality of transport server. the above error disappeared and transport queues were returned into Ready and Active states with the fully restored mail flow.


Therefore, dear friends, my recommendation would be first checking DNS settings and should it not be the case then move to tweaking your transport service related DNS settings as advised by MS and other bloggers.

By the way, if anyone is curious what 00000000-0000-0000-0000-000000000000 as a NIC GUID means, it means that Exchange Transport Service is using all DNS adapters for DNS lookups.

And of course my special thanks to the author of the last comment in the forum thread. Sometimes problem can be too small and too hidden to spot it straight away and this makes the greatest fun.

Enjoy!

Friday, May 27, 2016

Great Script for Managing NTFS Permissions

Hi folks,

I would love to share with you about one of my recent findings, namely PowerShell module for managing NTFS file and folder permissions. Its is available on the TechNet script gallery.You can download NTFSSecurity Module from this linkHere you can read about some basics about how to manage NTFS permissions. Actually there is one more arcticle and you can find its link at the download link.

After module is downloaded (in form of zip file) you will need to deploy it on your Windows server or client box (I played with the former thought, so I leave client to you).

To install NTFSSecurity Module on your Windows 2012 server you will need to unzip files and copy all of them to %Windir%\System32\WindowsPowerShell\v1.0\Modules. If you are as lazy as I am below is the code to do it automatically (of course you may have a different folder from where you are copying your module files:

New-Item "C:\Windows\System32\WindowsPowerShell\v1.0\Modules\NTFSSecurity" -Type Directory
Copy-Item D:\\Scripts\NTFSSecurity\* "C:\Windows\System32\WindowsPowerShell\v1.0\Modules\NTFSSecurity"

After which you can
Import-Module NTFSSecurity

Below are some Sample Commands that I played with:

View NTFS permission:
Get-Item C:\Folder |Get-NTFSAccess

Add Full Access to one of the well-known Windows SIDs:
New-Item G:\Folder -Type Directory
Add-NTFSAccess -Path C:\Folder -Account 'NT AUTHORITY\NETWORK SERVICE' -AccessRights FullControl -AppliesTo ThisFolderSubfoldersAndFiles

Add full access to a domain user named john.smith:
Add-NTFSAccess -Path C:\Folder -Account 'contoso\john.smith' -AccessRights FullControl -AppliesTo ThisFolderSubfoldersAndFiles

Isn't it cool? As I love saying PowerShell is indeed Power Shell!

Enjoy


Thursday, May 26, 2016

Scripts for Starting and Resuming Maitenance Mode on Exchange 2013 and 2016 servers Mailbox Servers

Hi folks,

All of us are facing tasks when we need to put our Exchange server box into maintenance mode. Usually this is done when we are installing updates or need to restart the servers (in majority of cases these two walk hand by hand). In Exchange 2010 there were 2 built-in scripts for this purpose StartDagServerMaintenance.ps1 and StopDagServerMaintenance.ps1. What each of these does can be read from their names.

However both Exchange 2013 and 2016 are different kind of animal compared to Exchange 2010 and in order to place them on maintenance you will need to disable more than just DAG and Windows cluster related settings. You will also need to drain transport queue and redirect all messages to other mailbox server (yes, mailbox servers are now responsible for transport). And when server is back up and running after maintenance you will need to revert it back from maintenance. It involves a lot of  commands and some of them can be missed or omitted. You can read more about it here.

Fortunately there is a solution for Exchange techies, especially those who are as lazy as I am. There are 2 scripts that were created for start and stop of Exchange server maintenance and they are available for download at below links:
Start Exchange 2013/16 box maintenance
Stop Exchange 2013/16 maintenance

I used them in my lab where I wanted to upgrade my Exchange 2016 Preview boxes to Exchange 2016 CU1.

First I placed both of them into Exchange scripts folder that is located at the installation path and renamed files to exclude version number.


Please note that if you have restricted PowerShell execution policy in your environment you may need to temporarily disable it by running

Set-PowerShellExecutionPolicy Unrestricted

After this you can run your script as follows:

cd $exscripts
.\Start-ExchangeServerMaintenanceMode.ps1 -Server Server1.domain.com -TargetServerFQDN Server2.domain.com

Script will magically put offline all the components which should be disabled and inactivated.



After it has been executed run the following command to ensure that all the components are inactive or offline:

Get-ServerComponentState -Identity Server1.domain.com



After I saw that all the critical components were inactive I have started upgrade of my Exchange 2016 Preview installation to CU1. Of course you know the command:

Setup.exe /m:Upgrade /IAcceptExchangeServerLicenseTerms



After successful upgrade I have recovered server from the maintenance mode by running the following code:

cd $exscripts
.\Stop-ExchangeServerMaintenanceMode.ps1 -Server Server1


After server has been returned back to functionality I have checked components by running Get-ServerComponentState command again (you can also run Test-Servicehealth cmdlet, however it reports of the state only of the back end components, totally ignoring frond end ones).



Finally you need to ensure that all DBs are activated by the DB activation preference. This can be achieved by running the following code wile in the scripts folder:

.\RedistributeActiveDatabases.ps1 -DagName DAG01 -BalanceDbsByActivationPreference -Confirm:$false



Enjoy

Wednesday, May 25, 2016

Exchange Management Shell and PowerShell 5.0

Hi folks,

Recently I have installed Exchange 2016 on my brand new Windows 2012 R2 box . When launching Exchange Management shell (aka PowerShell, aka EMS) I was greeted by error as below:


When trying to launch remote PowerShell session to Exchange I was successful. EAC was also working fine. Therefore it was something local on my server which would prevent me launching EMS locally.

During investigation I discovered this blog post for which I'm extremely thankful to its author.

I have executed $PSVersionTable.PSVersion to discover that PowerShell version that was installed on my server was 5.0.



This was result of having Windows Management Framework update being installed on my server.  According to this TechNet article Windows Management Framework 5.0 which includes PowerShell 5.0 is not supported with Exchange 2013/16. And apparently this is something I have discovered among updates installed on my server.



Uninstall of this update is needed to restore EMS functionality. I have discovered this script from the TechNet gallery to perform WMF uninstall automatically. Basically it is a PowerShell module which needs to be imported into the  PowerShell session. After this you will need to run Uninstall-OSCHotfix cmdlet which will removed WMF 5.0 from your server.

The code will be something like this:

Import-Module D:\Scripts\UninstallHotFixPowerShell\UninstallHotFix.psm1
Uninstall-OSCHotfix -HotFixID KB3134758

After the above commands have been executed you will need to restart your server. After this you can run the following command to confirm that PowerShell version installed on your server is 4:

$PSVersionTable.PSVersion

The try to launch EMS and voila it works:




Enjoy

Exchange Management Shell and Proxy

HI folks,

Just wanted to share with you another adventure which I have recently had with Exchange 2016. When launching Exchange Management Shell (aka EMS) on the newly installed server. I have got the following error:

New-PSSession : [server01.contoso.com] Connecting to remote server server01.contoso.com failed with the following error message : The WinRM client sent a request to an HTTP server and got a response saying the requested
HTTP URL was not available. This is usually returned by a HTTP server that does not support the WS-Managementprotocol. For more information, see the about_Remote_Troubleshooting Help topic.
At line:1 char:1

Internet is full of articles related to this particular error and I'm sure they are valid for a lot of scenarios. However, in my case it was due to misconfigured unauthenticated proxy which you use for CRL retrieving for Exchange certificates.

To make EMS working again all you need to do is to exclude FQDN suffix of your Exchange servers from being proxied. This can be achieved by using netsh utility. Below it the code sample:

netsh winhttp set proxy "proxy01.contoso.com:80" bypass-list="<local>;*.contoso.com;

Enjoy!

Exchange Management Troubleshooter and Exchange 2013/16

Hi folks,

I have been recently working on troubleshooting of Exchange Management Shell (EMS) on a newly installed Exchange 2016 server. My investigations led me to this KB article from Microsoft Support site. It was suggesting to use Exchange Management Troubleshooter (EMTShooter.ps1) to troubleshoot EMS on my server. It is indeed a great tool as it checks all the configuration bits on which EMS relies and in some cases can fix them automatically. You can read more about EMTShooter here and download it from here.

However when attempting to run it on my Exchange 2016 box I got the following error:



This was pointing that HKLM:\Software\Microsoft\ExchangeServer\v14\Setup key was missing. It is needed in order to read information about where Exchange binaries have been installed. However this key is absent on Exchange 2013/16 servers and information about installation path is rather located at HKLM:\Software\Microsoft\ExchangeServer\v15\Setup key.

Therefore in order to make EMTShooter.ps1 you will need to edit it either in notepad and locate there the following line:

$global:exinstall = (get-itemproperty HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\Setup).MsiInstallPath

There you will need to replace 4 with 5 in order to get it looking as follows:

$global:exinstall = (get-itemproperty HKLM:\SOFTWARE\Microsoft\ExchangeServer\v15\Setup).MsiInstallPath

This does the magic and EMTShooter,ps1 can now be executed against Exchange 2013/16 servers.



Enjoy!

Monday, May 23, 2016

CU12 Upgrade and Faulty Services

Hi folks,

I have recently encountered the problem when trying to upgrade my Exchange 2013 CU9 server to CU12. Right after executing installation program I got the following error:


Some google-ing let me to this thread.

The solution suggested at one of the posts by configuring startup type of automatic to Winmgmt, Remote Registry, WWW Publishing Service and IISAdmin did its magic.

Below is the code for configuring them:

Get-Service -name winmgmt, remoteregistry, w3svc, iisadmin | set-service -startuptype
automatic

Get-Service -name winmgmt, remoteregistry, w3svc, iisadmin | Start-Service

In my case I also had to restart servers after configuring the services.

Rerunning of Exchange 2013 CU12 upgrade succeeded.



Enjoy!

Managing Page File Using Powershell

Hi folks,

I have been planning deployment of more than one Exchange servers at a time, so in order to make work more effective and potentially save some time I was looking into automation of some, if not all, of the tasks.

One of them was to configure virtual memory on Windows 2012 R2 OS. You can read more on effective planning of paging file for Exchange 2013 and 2016 in this article.

During my investigations on this I found this article which provides a great code for a simple configuring configuration of RAM. All you need is to save it as Set-PageFile.ps1 file.

Let's imagine that we want to set our page file size to 16 GB+10 MB. You will need to run the following code (don't forget to navigate to the folder where it is stored):

 .\Set-PageFile.ps1 -InitialSize 16394 -MaximumSize 16394 -DriveLetter "C:"

After configuring the file you will need to restart your system and page file settings will become effective (similarly to the prompt which comes when you configure settings from GUI). After restart you can run this command to see if script execution was successful:

Get-CimInstance Win32_PageFileSetting | fl  *



Note parameters InitialSize and Maximum Size. They should be of the values you have run in the script.

Just in case if the link above gets broken or if you are too lazy you can upload the script from to this link.

However, I can't express how I am thankful to the article writer on this.

Enjoy!

Wednesday, May 4, 2016

Some More Adventures With Faulty Exchange Installs

Hi folks,

Just wanted to share with you my recent experience with installation of Exchange 2013 server. It failed at the point of installing component called Mailbox role:Mailbox services. The most frustrating moment was that it failed at the point of more than 90% of progress.

After consulting the setup log I have discovered the following:

[03/21/2016 12:45:55.0913] [2] [ERROR] Service 'MSExchangeSubmission' failed to reach status 'Running' on this server.
[03/21/2016 12:45:55.0913] [2] [ERROR] Service 'MSExchangeSubmission' failed to reach status 'Running' on this server.
[03/21/2016 12:45:55.0928] [2] Ending processing start-SetupService
[03/21/2016 12:45:55.0928] [1] The following 1 error(s) occurred during task execution:
[03/21/2016 12:45:55.0928] [1] 0.  ErrorRecord: Service 'MSExchangeSubmission' failed to reach status 'Running' on this server.
[03/21/2016 12:45:55.0928] [1] 0.  ErrorRecord: Microsoft.Exchange.Configuration.Tasks.ServiceDidNotReachStatusException: Service 'MSExchangeSubmission' failed to reach status 'Running' on this server.
   at Microsoft.Exchange.Configuration.Tasks.Task.ThrowError(Exception exception, ErrorCategory errorCategory, Object target, String helpUrl)
   at Microsoft.Exchange.Configuration.Tasks.Task.WriteError(Exception exception, ErrorCategory category, Object target)
   at Microsoft.Exchange.Management.Tasks.ManageSetupService.WaitForServiceStatus(ServiceController serviceController, ServiceControllerStatus status, Unlimited`1 maximumWaitTime, Boolean ignoreFailures, Boolean sendWatsonReportForHungService)
   at Microsoft.Exchange.Management.Tasks.ManageSetupService.StartService(ServiceController serviceController, Boolean ignoreServiceStartTimeout, Boolean failIfServiceNotInstalled, Unlimited`1 maximumWaitTime, String[] serviceParameters)
   at Microsoft.Exchange.Management.Tasks.ManageSetupService.StartService(String serviceName, Boolean ignoreServiceStartTimeout, Boolean failIfServiceNotInstalled, Unlimited`1 maximumWaitTime, String[] serviceParameters)
   at Microsoft.Exchange.Management.Tasks.StartSetupService.InternalProcessRecord()
   at Microsoft.Exchange.Configuration.Tasks.Task.<ProcessRecord>b__b()
   at Microsoft.Exchange.Configuration.Tasks.Task.InvokeRetryableFunc(String funcName, Action func, Boolean terminatePipelineIfFailed)
[03/21/2016 12:45:55.0928] [1] [ERROR] The following error was generated when "$error.Clear(); 
start-SetupService -ServiceName MSExchangeSubmission

" was run: "Microsoft.Exchange.Configuration.Tasks.ServiceDidNotReachStatusException: Service 'MSExchangeSubmission' failed to reach status 'Running' on this server.
   at Microsoft.Exchange.Configuration.Tasks.Task.ThrowError(Exception exception, ErrorCategory errorCategory, Object target, String helpUrl)
   at Microsoft.Exchange.Configuration.Tasks.Task.WriteError(Exception exception, ErrorCategory category, Object target)
   at Microsoft.Exchange.Management.Tasks.ManageSetupService.WaitForServiceStatus(ServiceController serviceController, ServiceControllerStatus status, Unlimited`1 maximumWaitTime, Boolean ignoreFailures, Boolean sendWatsonReportForHungService)
   at Microsoft.Exchange.Management.Tasks.ManageSetupService.StartService(ServiceController serviceController, Boolean ignoreServiceStartTimeout, Boolean failIfServiceNotInstalled, Unlimited`1 maximumWaitTime, String[] serviceParameters)
   at Microsoft.Exchange.Management.Tasks.ManageSetupService.StartService(String serviceName, Boolean ignoreServiceStartTimeout, Boolean failIfServiceNotInstalled, Unlimited`1 maximumWaitTime, String[] serviceParameters)
   at Microsoft.Exchange.Management.Tasks.StartSetupService.InternalProcessRecord()
   at Microsoft.Exchange.Configuration.Tasks.Task.<ProcessRecord>b__b()
   at Microsoft.Exchange.Configuration.Tasks.Task.InvokeRetryableFunc(String funcName, Action func, Boolean terminatePipelineIfFailed)".
[03/21/2016 12:45:55.0928] [1] [ERROR] Service 'MSExchangeSubmission' failed to reach status 'Running' on this server.
[03/21/2016 12:45:55.0928] [1] [ERROR-REFERENCE] Id=MailboxServiceControlLast___23a36fed7b6947e0906f388b5a90135c Component=EXCHANGE14:\Current\Release\Shared\Datacenter\Setup
[03/21/2016 12:45:55.0928] [1] Setup is stopping now because of one or more critical errors.
[03/21/2016 12:45:55.0928] [1] Finished executing component tasks.
[03/21/2016 12:45:55.0944] [1] Ending processing Install-MailboxRole
[03/21/2016 12:45:55.0959] [0] CurrentResult console.ProcessRunInternal:198: 1
[03/21/2016 12:45:55.0959] [0] CurrentResult launcherbase.maincore:90: 1
[03/21/2016 12:45:55.0959] [0] CurrentResult console.startmain:52: 1
[03/21/2016 12:45:55.0959] [0] CurrentResult SetupLauncherHelper.loadassembly:452: 1
[03/21/2016 12:45:55.0959] [0] The Exchange Server setup operation didn't complete.  More details can be found in ExchangeSetup.log located in the <SystemDrive>:\ExchangeSetupLogs folder.
[03/21/2016 12:45:55.0959] [0] CurrentResult main.run:235: 1
[03/21/2016 12:45:55.0959] [0] CurrentResult setupbase.maincore:396: 1
[03/21/2016 12:45:55.0959] [0] End of Setup

From all I saw ins the log installation program failed to start MSExchangeSubmission service and there were too many failed attempts that it simply gave up and stopped with error as above.

Quite interestingly services for other roles were installed and successfully started. I could tell it by looking into the Service console. As the first step I decided to rerun installation of Exchange 2013 by using the exactly the same command as I did during the first installation step.

In my case it was like the below:

setup.exe /mode:install /roles:Mailbox,ClientAccess /IAcceptExchangeServerLicenseTerms /InstallWindowsComponents /TargetDir:"C:\Program Files\Microsoft\Exchange Server\V15" /DoNotStartTransports

Installation program discovered Exchange components that were already installed and and kicked off from the point where it failed (as you can see it below):



So in the cases like that I would suggest to rerun Exchange installation program as the first step before you go on for further troubleshooting.

And it proves my theory that Exchange 2013/16 are simply Exchange 2010 roles placed together on one box and even though they are turned now into a single installation block, modular structure is still there beyond the veil. In a sense this situation was similar to the one I wrote about in this blog post.

I hope you find it is helpful for you if you face similar situation.

Enjoy!

Quick Retrieval of Remote IP Ranges on Receive Connectors

Hi folks,

As you well know that you can you can control list of hosts that can send to an Exchange server by maintaining RemoteIpRanges attribute of the receive connector. You can add and remove IP addresses to/from this attribute and I have already spoke about it in some of my previous posts.

Sometimes the number of IP addresses in the RemoteIpRanges can be too long so that when you type Get-ReceiveConnector |fl RemoteIpRanges some of the IP addresses are not displayed.

Below is a short code that allows us to see all the IP addresses no matter how long is the list of them:

Get-ReceiveConnector ConnectorName |select -ExpandProperty RemoteIpRanges |select Expression |sort Expression

I hope this will be helpful to you.

Enjoy!

Monday, May 2, 2016

Getting Rid of The Annoying Certificate Warnings During Exchange Deployment

Hi folks,

As you all well know when installing Exchange 2010/2013 CAS role or 2016 Mailbox role into the AD site which already hosts Exchange servers and users you may hear your users complaining that they see certificate warning in their Outlook client. This is the a well know issue and the reason for this is that AutoDiscoverServiceInternalUri on the server contains the hostname of the server rather than FQDN of AutoDiscover service that is configured as a CN or SAN of a certificate. This is usually quickly resolved by configuring AutoDiscover and assigning to a server the appropriate certificate to IIS service on the CAS server.

I have recently read this post on TechNet blog. According to it not only AutoDiscover settings can contribute to this. As you know when Outlook talks to Autodiscover SCP it receives settings of Outlook endpoint along with all the virtual directories that will be in use by the client. Among them are also virtual directories for OAB and EWS. Should Internal and External URL to be set to the default value (which is server hostname) and not to the URL that is included into the certificate, the same annoying certificate warning will be displayed to your user community,

In the same post MS is suggesting by isolating Exchange servers into a separate AD site so that end users don't see new Exchange server and return it back to the production site after all the configuration is over. As you well know in order to define a new AD site you will need to configure a separate IP subnet, create a new AD site object and assign new subnet object to the site. It is a very good method if you don't have any constrains and both AD and Exchange are managed by the same group of people. However, when teams are different this may be troubleshome. Also don't forget that you may need additional range for IP addresses which will also involve networking team with all the joys related to their configuration and you will also need at least one global catalog for your deployment site. The latter can be easily achieved by visualization especially if you are using Windows 2012 as your DC OS, which really befriends AD with visualization.

If for some reason you can't afford configuration of a separate AD site you will need to immediately after installation of Exchange binaries configure Autodiscover along with all the virtual directories used by Outlook. Below is the code that you may use for this purpose. Please note that you will need to replace names of the AD sites as well as URLs with the one that are relevant for your environment.

Also you need to ensure that you have a file with certificate available in the path you have specified in the code for certificate configuration. This will ensure smooth ruining of script.

The sample code is as follows:

$Server = $(Get-WmiObject Win32_Computersystem).name

Set-ClientAccessServer -Identity $Server -AutoDiscoverSiteScope Site1, Site2 -AutoDiscoverServiceInternalUri https://autodiscover.contoso.com/Autodiscover/Autodiscover.xml

Set-OABVirtualDirectory -Identity "$Server\OAB (Default Web Site)" -InternalUrl "https://mail.contoso.com/OAB" -ExternalUrl "https://mail.contoso.com/OAB" -RequireSSL:$true

Set-WebServicesVirtualDirectory -Identity "$Server\EWS (Default Web Site)" -InternalUrl "https://mail.contoso.com/ews/exchange.asmx" -ExternalUrl "https://mail.contoso.com/ews/exchange.asmx"

Import-ExchangeCertificate -FileData ([Byte[]]$(Get-Content -Path D:\Certs\CAS-cert.pfx -Encoding byte -ReadCount 0)) -Password:(Get-Credential).password

Enable-ExchangeCertificate -Thumbprint 1234567890123456789012345678901234567890 -Services IIS,IMAP,POP,SMTP

Enjoy!