15 December 2016

SCOM - The Ehlo options for the client proxy target did not match

The full error is this one:

Alert: Exchange Health Set
Source: sr-XXXXX - HubTransport
Path: sr-XXXXX.domain.lan;sr-XXXXX.domain.lan
Last modified by: System
Last modified time: 12/15/2016 9:43:40 AM Alert description: The Ehlo options for the client proxy target did not match while setting up proxy for user  on inbound session 08D41FF9C251F8DD. The critical non-matching options were <maxSize>. The non-critical non-matching options were <NONE>. Client proxying will continue.
Probe Exception: ''
Failure Context: ''
Execution Context: ''
Probe Result Name: 'Transport/SmtpProxyEhloOptionsDoNotMatchContinueProxying'
Probe Result Type: 'Failed'
Monitor Total Value: '0'
Monitor Total Sample Count: '1'
Monitor Total Failed Count: '1'
Monitor Poisoned Count: '0'
Monitor First Alert Observed Time: '15-12-2016 08:43:37'

The error itself doesn't tell you al lot at first glance.
But if you look at "client proxy target" it shows you in the direction of the receive connector on the server the error originated from.

So what's happening here?
Let's say the MaxMessageSize for the organisation is set to 50MB.
An email arrives at the Client Frontend receive connector which has a size of  50MB.
If the MaxMessageSize is set at 50MB it gets passed on to the Client Proxy receive connector which usually has a MaxMessageSize setting of 50MB as well.
Then it will be passed on to the Outbound Frontend Proxy receive connector which has a setting of 50MB as well.

Every time the message gets proxied/passed on to the next receive connector some header info gets added to the message making it a little bit bigger.
So in other words your receive connector needs to accept a bigger MaxMessageSize for every step along the way.

How do we do this?

First check your Current settings:
get-ReceiveConnector *\* | fl   identity,role*,maxm*size,bind*

Then check the settings for the individual receive connector on all the servers:
Get-ReceiveConnector "*\client proxy servername" | fl identity,role*,maxm*size,bind*
Get-ReceiveConnector "*\client frontend servername" | fl identity,role*,maxm*size,bind*
Get-ReceiveConnector "*\outbound proxy frontend servername" | fl identity,role*,maxm*size,bind*
Get-ReceiveConnector "*\client frontend servername" | fl identity,role*,maxm*size,bind*

After that set the MaxMessageSize for the Client Frontend connector on each server:
Set-ReceiveConnector   "servername\client frontend servername" -MaxMessageSize 50MB

Then set the MaxMessageSize for the Client Proxy connector on each server, and add 1MB:

Set-ReceiveConnector   "servername\client proxy servername" -MaxMessageSize 51MB

Then set the MaxMessageSize for the Outbound Proxy Frontend connector on each server, and add 1MB:
Set-ReceiveConnector   "servername\outbound proxy frontend servername" -MaxMessageSize 52MB

Now you can check your settings with the same commandlet as you started with:
Get-ReceiveConnector "*\client proxy servername" | fl identity,role*,maxm*size,bind*
Get-ReceiveConnector "*\client frontend servername" | fl identity,role*,maxm*size,bind*
Get-ReceiveConnector "*\outbound proxy frontend servername" | fl identity,role*,maxm*size,bind*
Get-ReceiveConnector "*\client frontend servername" | fl identity,role*,maxm*size,bind*

Then restart the MSExchangeTransport Service on each server to activate the settings:
Get-Service   -ComputerName servername -Name MSExchangeTransport | Restart-Service

13 December 2016

Remote PowerShell session - the request needs to be sent to a different machine

Well this is a nice one as well….NOT. I keep losing hair like this.
After trying to setup a remote PowerShell session the following error occurs.

The WinRM service cannot process the request because the request needs to be sent to a different machine.
Use the redirect information to send the request to a new machine.  Redirect location reported: https://mail.mydomain.com/powershell.
To automatically connect to the redirected URI, verify "MaximumConnectionRedirectionCount" property of session preference variable
"PSSessionOption" and use "AllowRedirection" parameter on the cmdlet.
+ CategoryInfo          : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [], PSRemotingTransportRedirectException
+ FullyQualifiedErrorId : PSSessionOpenFailed

Let me tell you what is not the cause so you can skip checking all those things:
  • An URL redirect in IIS
  • Reinstall of WinRM
  • adding “–AllowRedirect” after your connection command let
  • "MaximumConnectionRedirectionCount" property setting
  • Misconfigured certificate
  • PowerShell version
  • Invalid credentials
The list could go on and on, but the solution is quite simple as it is not logic at the same time.
The error doesn't say a lot about the actual cause.
So remember when was the last CU you installed? Bingo, after every CU your IIS settings can get garbled and that’s exactly what happened here.
Changes are your authentication settings in IIS on the PowerShell virtual directory for the frontend website are gone/missing/set incorrectly.
In my case they were gone, no authentication option was set. After setting it al back the way it should be (see this post, you need to make note of this stuff for a working Exchange environment in cases like this) I could create a remote PowerShell session instantly.

After renewing Exchange certificates IMAP stops working

The strangest things happen as an Exchange admin.
Recently i renewed the certificates for our Exchange servers, and while everything went fine the next day we got several calls that a few IMAP mailboxes stopped working.

No this is particularly strange because it's an IMAP mailbox that uses plain text logon on port 143, the default imap port so it doesn't even use a certificate.
After ripping my hairs out, calling everybody who came to close a #$%^ and a &!@#*& i came across this post by Jetze Mellema.

Strangely enough it worked, well at least for 2 of the 3 mailboxes.
The day after we were getting calls that there was still one mailbox that couldn't connect.

Same error in the IMAP protocol log:

2016-12-13T09:11:57.785Z,000000000000003F,8,x.x.x.151:143,x.x.x.202:54194,imapmailbox,63,43,55,login,imapmailbox@domain.com *****,"R=""2yc2 NO LOGIN failed.\r\n* BYE Connection is closed. 14"";Msg=Proxy:servername.domain.lan:1993:SSL;ErrMsg=ProxyNotAuthenticated"

The error message suggests that there is something going on with authentication or a firewall issue possibly blocking a port or using a certificate that is expired or has wrong name in it.

But no, to solve this we moved the mailbox to another mailbox database.
After the move we created an Outlook profile with the correct credentials and were able to login immediately. 

Now if you're reading this and you know why this happend please let me know, because i was baffled and totally don't understand any logic behind this stuff.

29 November 2016

Renew Exchange 2013 Certificates from Internal CA

This comes back once a year, well for me anyway.
So to never forget I thought why not make a post for myself and all of you out there.

But Paul Cunningham from Exchangeserverpro did a far better job even before i got started, so here goes:

Step 1
 Step 2
 Step 3
 Step 4

PowerShell tips

This cmdlet will return all exchange specific cmdlets

Get-command -name get-service –synopsis


Get-Help is another one which comes handy. Say, while you were playing with Exchange management shell, you saw a new cmdlet and don’t know what that means.

For example, you don’t know what Get-Message means. To know more, type

Get-Help Get-Message

Get-Message is a cmdlet to retrieve messages from the message queue in Exchange 2007 and 2010

An example is,

Get-Message -Filter {FromAddress -like “*@ratishnair.com”}

This cmdlet will retrieve all messages from the domain “ratishnair.com”
The tilde character (~) represents the shortcut to root directory. For example,

Dir ~

Use it as a shortcut:

Cp FileName “~\My Documents”

We see the $_ sign in a lot of cmdlets. This is known as a Special Variable.

The $_ represents the objects being passed from one cmdlet to another cmdlet in the pipeline. The $_ variable is automatically initiated by the shell and is bound to the current pipeline object. You can access the properties of the object assigned to the $_ variable as you would any other object.

The following example shows how you can view the Name property of each mailbox object
that is passed through the pipeline:

Get-Mailbox | ForEach { $_.Name }

If you need another example, this one lists all running services on an Exchange server

Get-Service | where {$_.Status -eq “Running”}

Lets take a look at another one. This one returns the name of the smallest database:

(Get-MailboxDatabase | foreach { get-childitem $_.edbFilePath | select-object name,length} | sort -property length )[0]

-FILTER and –LIKE commands are often used together. This will filter the information in Double quotes and look for data matching info in Single quotes

Again, easy when explained with an example:

Get-Mailbox –RESULTSIZE UNLIMITED -FILTER “Displayname –Like ‘Nair, Ratish'”

So, this cmdlet is going to get mailbox information where the result will be unlimited and will filter information to ensure only the one with Displayname ‘Nair, Ratish’ is returned.

You can access the event log from the Exchange Management Shell. To retrieve the whole event log, run:

Get-EventLog Application | Format-List

To retrieve all Exchange-related events, run:

Get-EventLog Application | Where { $_.Source -Ilike “*Exchange*” }

Any cmdlet that accepts a size value lets you specify whether the integer value is in kilobytes (KB), megabytes (MB), gigabytes (GB), or terabytes (TB). For example:

Set-Mailbox “Meera Nair” -ProhibitSendQuota 200MB

You can import CSV files and treat them as objects by using the Import-Csv cmdlet. Each row in a CSV file becomes an element in an array, and each column becomes a property. You can assign the CSV file to a variable or you can pipe its contents directly to another cmdlet. In the following example, there are three columns in the CSV file, Name, Alias and EmailAddress, with several rows that the For Each cmdlet will cycle through. The data in each row is used to create a new mail contact.

Import-Csv | ForEach { New-MailContact -Name $_.Name -Alias $_.Alias -ExternalEmailAddress $_.EmailAddress -OrganizationalUnit Users }

The Exchange Management Shell can log all the Exchange-related commands that modify objects in some way. Exchange-related command activity is logged to the PowerShell event log. To enable Exchange-related command logging, run the following command:

Set-ItemProperty HKLM:\SOFTWARE\Microsoft\PowerShell\1\PowerShellSnapIns\Microsoft.Exchange.Management.PowerShell.Admin -Name LogpipelineExecutionDetails -value 1

This one is one of my favourites – Set-Alias

Say you want to have an Alias for Get-StorageGroup, just type

Set-Alias GetSg Get-StorageGroup
From now, Get-StorageGroup cmdlet will have an alias Get-Sg

For all the current aliases, type:

This one is not exactly a powershell cmdlet tip. This works in command prompt too. CTRL+C will hard-break command in the Exchange Management Shell. If a command is taking too long to run or you want to cancel an operation quickly, press CTRL+C to stop execution.

When some or a group of users complain that they cannot access their mailbox, check the mounted status of all mailbox databases? Type:

Get-MailboxDatabase -Status | Format-Table Name, Server, Mounted

This one checks the permissions an Active Directory user account has on a specific mailbox? Use:

Get-Mailbox <Mailbox to Check> | Get-MailboxPermission -User <Active Directory User>

This one returns the list of all devices synchronized with a user’s mailbox:

A variety of information is returned including device name, operating system, and last sync time.

This one returns the list of the backup status of all mailbox databases in your organization? Type:

Get-MailboxDatabase -Status | Format-Table Name, Server, *Backup*
How about just the mailboxes on a specific server? Type:

Get-MailboxDatabase -Server <Server Name> -Status | Format-Table Name, *Backup*

This one gets a list of all users who are Unified Messaging-enabled type, use:

Get-UmMailbox | ForEach { If($_.UmEnabled -Eq $True){$_.Name}}

This one will help you control the properties of e-mail messages sent to a specific domain using the RemoteDomain cmdlet.

Create a new remote domain by using the New-RemoteDomain cmdlet. Type:

New-RemoteDomain -Name “ratishnair.com Configuration” -DomainName ratishnair.com
Then modify the properties that you want for this remote domain by using the Set-RemoteDomain cmdlet:

Set-RemoteDomain ” ratishnair.com Configuration” -AutoReplyEnabled $True -AutoForwardEnabled $True

Control which features are available to Outlook Web Access users by using the Set-OwaVirtualDirectory cmdlet. Type:

Set-OwaVirtualDirectory “OWA (Default Web Site)” -ContactsEnabled $True -ChangePasswordEnabled $True

This one will disable Outlook web access for the user sunder@msexchangeguru.com

Set-CASMailbox sunder@msexchangeguru.com-OWAEnabled:$False

Move-Mailbox of all users from server EXCH1 to server EXCH2 as follows:

Get-Mailbox -Server EXCH1 | Move-Mailbox -TargetDatabase EXCH2

The .count parameter is a good one. This helps to count the output (number of mailboxes) in a cmdlet like the one shown below:

<Get-Mailbox –Server EXCH1 –Resultsize unlimited>.count


UPDATE from Jeffery Hicks (Windows PowerShell MVP)

Good list, although I might suggest a few revisions to make them even more PowerShell like and take advantage of the pipeline.

This command (point 4):

Get-Mailbox | ForEach { $_.Name }

works and generates a nice list which is great if you wanted to save it to a text file:

Get-Mailbox | ForEach { $_.Name } | out-file Mailboxes.txt.

But to get just that property all you need is

Select-Object: Get-MailBox | Select Name

I would also suggest that this (Point 16):

Get-UmMailbox | ForEach { If($_.UmEnabled -Eq $True){$_.Name}} is more complicated than it needs to be. This is more efficient.

Get-Mailbox | where {$_.UMEnabled} | Select Name

IIS redirect using URL Rewrite

In the following example we will redirect HTTP to HTTPs using URL Rewrite. You will need the following items completed in order for this to work correctly.
– SSL Certificate for site installed in IIS.
– Site properly installed and configured for SSL (site set up and binding in IIS configured).
– URL Rewrite 2.0 is installed on the sever.

GUI Version

– Select the website you wish to configure
– In the “Features View” panel, double click URL Rewrite

You will notice there are currently no rules configured for this site. Click “Add Rules…” in the Actions menu to the right of the “Features View” panel

Use the default “Blank rule” and press “OK”.

When editing a rule there are the “Name” field and 4 configuration pull down boxes.
– Enter “Redirect to HTTPS” in the name field.
– Next we will configure the first configuration pull down box called “Match URL”, on the right side of “Match URL” press the down arrow to expand the box.

Within the “Match URL” configuration box we will set the following settings:
Requested URL: Matches the Pattern
Using: Regular Expressions
Pattern: (.*)

We can now edit the next configuration pull down box which is “Conditions”, Press “Add…” to add a new condition to the configuration.

We will configure the condition with the following settings:
Condition Input: {HTTPS}
Check if input string: Matches the Pattern
Pattern: ^OFF$
Press “OK”

You should see your condition in the list of conditions.

For this setting we do not need to configure the “Server Variables” pull down box. Continue onto the “Action” configuration box and pull down the box by selecting the arrow on the right. We will configure the following settings for the “Action” configuration:
Action Type: Redirect
Redirect URL: https://{HTTP_HOST}/{R:1}
Redirect Type: See Other (303)

Press “Apply” then press “Back to Rules”

You should now see the rule configured on the main screen of the URL Rewrite module.

Test your site, it should now redirect from HTTP to HTTPS.
If we exam the web.config file we can see where the rule was entered. If we entered the rule directly into the web.config file it would show up in the GUI.

Web.Config Rule
You can also edit the web.config file of the site directly and you will be able to see the rule in the GUI. You will need to enter the following within the <system.webServer> </system.webServer> elements.
<rule name="Redirect to HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions><add input="{HTTPS}" pattern="^OFF$" />
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="SeeOther" />
When implementing this solution you need to make sure to use relative paths for all references on your page because there is a possibility you will get a warning asking you if you want to display secure and insecure items. For example, if you have a logo on your page and the URL to this logo is http://domain/images/logo.jpg, do not use the whole path because including the http:// will hard code this image to use http and not https. Instead use /images/logo.jpg.

Replace the Redirect URL https://{HTTP_HOST}/{R:1} with https://{HTTP_HOST}{REQUEST_URI}

PSGallery and NuGet on WIndows 10 build 1607 (Anniversary Edition)(OneGet)

Since the Windows 10 anniversary edition things have change a little for NuGet. (OneGet)
The new way to add a repository is this:
PS C:\> Get-PackageSource

 Name                             ProviderName     IsTrusted  Location
----                             ------------     ---------  --------
PSGallery                        PowerShellGet    False      https://www.powershellgallery.com/api/v2/

 PS C:\> Set-PackageSource -Name PSGallery -Trusted

 Name                             ProviderName     IsTrusted  Location
----                             ------------     ---------  --------
PSGallery                        PowerShellGet    True       https://www.powershellgallery.com/api/v2/

 PS C:\> Get-PackageProvider -Name Chocolatey

 The provider 'chocolatey v2.8.5.130' is not installed.
chocolatey may be manually downloaded from https://oneget.org/ChocolateyPrototype- and installed.
Would you like PackageManagement to automatically download and install 'chocolatey' now?
[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"): Y

 Name                     Version          DynamicOptions
----                     -------          --------------
Chocolatey             SkipDependencies, ContinueOnFailure, ExcludeVersion, ForceX86, PackageSaveMode, FilterOnTag, Contains, AllowPrereleaseVersions, ConfigFile, SkipValidate

 PS C:\> Set-PackageSource -Name Chocolatey -Trusted

 Name                             ProviderName     IsTrusted  Location
----                             ------------     ---------  --------
chocolatey                       Chocolatey       True       http://chocolatey.org/api/v2/

 PS C:\> Get-PackageSource

 Name                             ProviderName     IsTrusted  Location
----                             ------------     ---------  --------
PSGallery                        PowerShellGet    True       https://www.powershellgallery.com/api/v2/
chocolatey                       Chocolatey       True       http://chocolatey.org/api/v2/

 PS C:\> Find-Package -Name Firefox

 The provider 'nuget v2.8.5.208' is not installed.
nuget may be manually downloaded from https://oneget.org/Microsoft.PackageManagement.NuGetProvider- and installed.
Would you like PackageManagement to automatically download and install 'nuget' now?
[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"): Y

 Name                           Version          Source           Summary
----                           -------          ------           -------
Firefox                        50.0.1           chocolatey       Bringing together all kinds of awesomeness to make browsing better for you

 PS C:\> Find-Package -Name Adobe

 Name                           Version          Source           Summary
----                           -------          ------           -------
adobereader                    2015.007.20033   chocolatey       Adobe Reader - View and interact with PDF files
AdobeAIR                    chocolatey       Adobe AIR runtime is necessary for AIR based applications.
adobeshockwaveplayer        chocolatey       Displays Web content that has been created by Adobe Director
adobereader-update             15.017.20053.1   chocolatey       Adobe Reader - View and interact with PDF files
adobe-creative-cloud           1.0              chocolatey       Adobe Creative Cloud Client Installer for installing creative cloud subscription applications
simnetsa-adobereader-fr        11.0.7           chocolatey       Le logiciel Adobe Reader est la norme internationale libre, permettant de visualiser, imprimer et commenter des documents PDF
BR.AdobeReaderFR               11.0.09          chocolatey       BR.AdobeReaderFR

 PS C:\>

25 November 2016

How to Configure Windows 2012 R2 ADCS With Static DCOM Port

To configure the Active Directory Domain Services (AD CS) certification authority (CA) service (CertSvc) to listen on a static DCOM port

1. Log on with an account that has local administrator permission on the CA 
2. Open the Component Services snap-In (dcomcnfg.exe).

3. In the left pane of the Component Services snap-In, expand Component Services, Computers, My Computer, and then DCOM Config.
4. In the right pane, select CertSrv Request.

5. On the Action menu, click Properties.

6. On the Endpoints tab, click Add.

7. Select Use static endpoint, enter an unused TCP port number, 50000, and then click OK twice.

8. Close the Component Services snap-In. 
9. Restart the certification authority service. 
net stop certsvc 
net start certsvc

ADCS Server 2012 R2 Auto Enrollment with hardening - RPC Server Unavailable

On a Windows 2012 R2 server with the ADCS role installed you get an error "RPC server unavailable" after trying to request a certificate from a published template.

The first thing to look for is access rights.

In all the posts on the internet I came across mentioned to check whether the Authenticated users group had acces on several objects. The idea is in the right direction but not quite the solution yet.

In Windows Server 2012 R2 in combination with a hardening policy you need to use the Domain Users group as well.

So check for the Authenticated Users group and add the Domain Users group in the following places:The local server group: Certificate DCOM Access

The properties of the CA server itself, Authenticated Users, Domain Computers, Domain Controllers and Domain Users should be present.

On the CA server itself the Certsrv directory in C;\Windows\System32\ should have Read and Execute rights for Authenticated users and Domain Users.

In Active Directory\Builtin locate the "Users" group and check for Authenticated Users and Domain Users

Check the DCOM Access Limit of “My Computer” of the DC:
1- On the server, run dcomcnfg.exe.

2- On the Component Services console, navigate to Component Services\Computers\My Computer.

3- Right-click My Computer, select Properties, verify that Enable Distributed COM on this computer is selected in the Default Properties tab. 

4- Click the COM Security tab, Click Edit Limits in the Access Permission section and ensure that Everyone and Certificate Service DCOM Access has Local Access and Remote Access permissions.

5- Click Edit Limits in the Launch and Activation Permission section and ensure that Certificate Service DCOM Access group has Local Activation and Remote Activation permissions.

6- Click OK.

This should be enough to get those certificates rolling again.

07 October 2016

FIXED - ANOMALY: use of REX.w is meaningless (default operand size is 64) - FIXED


There is a fix for this published by Trendmicro:



Came across this strange error after reinstalling my pc.

Same goes for PowerShell.

The command itself doesn't matter, the error appears at every command or applet.

Removed TrendMicro Maximum Security 2017, rebooted and the error was gone.
Installed TrendMicro Maximum Security 2017 again and there is was again.


Then removed the TrendMicro Password manager and the TrendMicro troubleshooting tool.

Reboot, still there.
Now i can't just remove TrendMicro Maximum Security 2017 well because....
It has some thing to do with TrendMicro Maximum Security 2017 itself.

I will see if i can contact the support team and try to get this fixed or at least under the attention of TrendMicro.

To be continued.

29 September 2016

Top 30 Quick reminders for SysOps

Came across this over at gfi.com/blog, this is just here for my own quick sneak and peek.
But if you have more quick wins, tips or oneliners let me know and i'll add them.


  1. netsh int ip reset all will reset your NIC back to DHCP quickly, blanking out all static settings.
  2. net use will show you all open SMB connections on your machine.
  3. If you need to grab a quick network capture, but aren’t allowed to install Wireshark or another similar tool, open an admin command prompt and run netsh trace start capture=yes tracefile=c:\capture.etl to create a file you can open in Wireshark or Netmon later. Use netsh trace stop to end the capture.
  4. If you just need to know what is happening, but not capture a trace, use netstat as a poor man’s packet analyzer. netstat –ano 1 | findstr X will update once a second and highlight whatever you replace X with, like :443 or SYN_SENT or the destination ip.addr you are trying to confirm your machine is attempting to communicate with.
  5. netstat –e can give you a quick diagnosis of layer 2. Watch out for high or increasing numbers of errors.
  6. Grab the TCPING utility from http://www.elifulkerson.com/projects/tcping.php and use it to monitor not just when a server reboots, but when a service is back up. Try tcping –t –b 2 addr 3389 when you reboot a Windows server. It will start to use your default beep sound when the service starts responding to SYN requests, so you know you can RDP back into the box after a reboot.
  7. Use netstat –r to dump your IP routing table so you can see if everything goes to the default gateway, or somewhere unexpected.
  8. Download BIND for Windows from https://www.isc.org/downloads/# and use the Windows ports of DIG and HOST to do DNS queries.
  9. And if you like DIG and HOST, grab the whois port from https://technet.microsoft.com/en-us/sysinternals/bb897435 to do command line lookups of domain names and IP networks.

Active Directory

  1. netdom query fsmo will list all the Flexible Single Master Operations members in your domain, so you can find the PDC emulator, schema master, etc.
  2. repadmin /replsummary will give you a quick status on AD replication. It will also let you know if you cannot reach a domain controller from the machine on which you run the command.
  3. repadmin /syncall will trigger an AD replication so you don’t have to wait.
  4. net accounts will list the domain security policy.
  5. gpresult /v will dump all the Group Policy Object settings affecting you and the machine you’re on.
  6. whoami and whoami /groups will confirm your AD account and group memberships.
  7. set l will let you know what domain controller authenticated you, or if you are running with cached credentials.


  1. Use the Windows+Arrow Keys to move windows around, including both half- and quarter-monitor views.
  2. Windows+Tab to bring up a quick preview of all running applications.
  3. Windows+X brings up the Quick Access Menu.
  4. Windows+P brings up projection options for when you connect to a second monitor or projector.
  5. Windows+number will launch whatever app is in that numeric position, from left to right, on your taskbar.
  6. CTRL+SHIFT+P launches an “In Private” session of Internet Explorer.
  7. Use the Problem Steps Recorder to automatically capture screenshots of a process or procedure. It’s great for documentation and training too. Windows+R, PSR, Enter!
  8. Run powercfg –h off to turn off hibernation, and buy back several GB of disk space by dropping the hiberfil.sys file that is just taking up space on your hard drive.
  9. Look up most error codes at the command prompt by downloading the Microsoft ERR tool and saving it in your path.
  10. All the Sysinternals command-line tools can be executed from the web using \\live.sysinternals.com\tools\toolname*. Check out http://live.sysinternals.com/ for all the tools that are there.


  1. If you are not sure of a command, run get-command *something* to get a list of appropriate commands.
  2. Use get-help command to get help on a command. –full gives you everything, -examples just lists some examples, and –online brings up the online help.
  3. PowerShell v4 and later has copy and paste already turned on, and can use the highlight, CTRL-C, CTRL-V just like any other Windows app.
  4. There are 155 aliases in PowerShell v5, making cmdlets from DOS and Linux available to you in PowerShell. Run alias to see all the ones that are built-in, and use the alias command to create your own.

28 September 2016

Onedrive - This feature has been disabled by your administrator

How anoying, now how to get to your Onedrive?

Update - 31-10-2016 - Found another registry key to enable Onedrive if disabled by group policy.

Copy the text below and paste in a new text file, save the file as a ".reg".

Windows Registry Editor Version 5.00














Then double click the reg file and close Onedrive, then reopen Onedrive and sign in from an Office application.

27 September 2016

Skype for Business client addressbook not downloading - Force Addressbook download - Why would you?

Skype for Business client addressbook not downloading - Force Addressbook download - Why would you?

This is one of those things that happens to all of us.
The Lync or Skype for Business addressbook won't download to the local computer.

I wrote about this once before for Lync 2010 here.

After upgrading to Office 2016 you get the new collaboration/communication client as well: Skype for Business. And with that comes a version change, and i don't mean in what you see at the client i mean on the file system level.

The previous path to the Lync client profile was:
C:\Users\Username\AppData\Local\Microsoft\Office\14.0\Lync\sip_username@domain.com for Lync 2010.
C:\Users\Username\AppData\Local\Microsoft\Office\15.0\Lync\sip_username@domain.com for Lync 2013.
But now it's:
C:\Users\Username\AppData\Local\Microsoft\Office\16.0\Lync\sip_username@domain.com for Skype for Business 2016.

So you have to update you registry path accordingly.
So instead of looking for:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Office\14.0\Lync\GalDownloadInitialDelay for Lync 2010.
Or HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Office\15.0\Lync\GalDownloadInitialDelay for Lync 2013.

Go to HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Office\16.0\Lync\GalDownloadInitialDelay for the new Skype for Business 2015 client.

Make sure the value for GalDownloadInitialDelay is set at 1 for instant GAL retrieval.


Why bother with local copies of files when you can search at the source?
The one place where the GAL originates from: The Skype for Business server it self.

On the frontend server open an elevated Skype for Business Management PowerShell:
To get the current Addresbook policy:
PS C:\> Get-CsClientPolicy | select identity, addressbook*

 Identity               AddressBookAvailability
Global                 WebSearchOnlyWebSearchAndFileDownload
To set the Addressbookavailability to "WebsearchOnly":
Set-CsClientPolicy -Name Global -AddressBookAvailability "WebSearchOnly"
To see more about ClientPolicies go here.

23 September 2016

Backup local user contacts from Lync 2013 and Skype for Business 2015 with Powershell

After migrating from Lync 2010 to Skype for Business 2015 the moment came to move all the users to the new registrar pool and all the local user contacts went missing.

To avoid this from happening to you, here's what you can do.

Copy the text below into a new text file and name it "Skype4BusinessUserContactsBackup.ps1"
$fileName = (Get-Date -Format ddMMyyyy) + "-SkypeUsersContactsBackup.zip"
$Path = "\\Domain.lan\Some\path\to\some\where"
# Set limit for older than days
$limit = (Get-Date).AddDays(-365)
# Delete files older than the $limit.
Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force
#(Join-Path $Path $filename)
Export-CsUserData -PoolFqdn Yourpoolname -FileName (Join-Path $Path $filename)
Short description of what this all does:
$filename, set a filename in current date and time format and add SkypeUsersContactsBackup.zip.
File name looks like this: 23092016-SkypeUsersContactsBackup.zip.
$path, specify a path where the file will be saved.
$limit, how many days before we start deleting the backup zip files.
At the end the export from the pool will be written in the destination made from $path and $filename.

Then create a scheduled task with these action settings:

Program/script: Powershell.exe -command ". 'path to your script\scriptname.ps1'"
Set it to run at a monthly schedule or more as you desire.
The file in my environment is about 16MB for roughly 1600 users.

Now when the time comes to restore some contacts for a user, several or all users, you'll need this GUI script from Anthony Caragol.
Download from here:
It still works on Skype for Business.

12 September 2016

Migrate from Office Web Apps 2013 to Office Online Server 2016 for Skype for Business 2015

Sharing PowerPoint's in Skype for Business 2015 was done with Office Web Apps 2013.

Now we have Office Online Server 2016 to do this.

A few things before starting the migration:

The installation ISO can be found on the Volume License Servicing Center
Find "Office Professional Plus 2016" click "Download" select your language bit version and click "Continue", "Office Online Server x64" is listed under the Office 2016 Pro suite.
There is a serial listed, but i couldn't find where to enter it. (if you know let me know)

- .NET Framework 4.5.2
- Visual C++ Redistributable for Visual Studio 2015 (14.0.23026)

Run "Get-OfficeWebAppsFarm | FL internalurl,externalurl,certificatename" copy the output to a notepad file, you'll need this later.

Remove the Office web App Server from Skype for business, and the association within all the Skype for Business pools and publish the topology.

Uninstall "Microsoft Office Web Apps Server 2013"

Install Windows Identity Foundation 3.5 (Add Roles and Features > Features)

Install the Update for Universal C Runtime in Windows KB (https://support.microsoft.com/en-gb/kb/2999226)

Install the required features from an elevated PowerShell session:

Install-WindowsFeature Web-Server, Web-Mgmt-Tools, Web-Mgmt-Console, Web-WebServer, Web-Common-Http, Web-Default-Doc, Web-Static-Content, Web-Performance, Web-Stat-Compression, Web-Dyn-Compression, Web-Security, Web-Filtering, Web-Windows-Auth, Web-App-Dev, Web-Net-Ext45, Web-Asp-Net45, Web-ISAPI-Ext, Web-ISAPI-Filter, Web-Includes, InkandHandwritingServices, Windows-Identity-Foundation

Mount the ISO and run "Setup.exe", next, next, finish, you know the drill.

In an elevated PowerShell run:
New-OfficeWebAppsFarm -InternalURL "https://oos.domain.lan" -ExternalURL "https://oos.domain.com" -CertificateName "OOS_Cert"

To be on the safe side you could reboot the server, but in this case i didn't.

Go to the Skype for Business Topology Builder with elevated privileges.
Create a new "Office Web Apps Server" in Skype for Business.

Enter the FQDN of the Office Online Server and click OK.

Right click each pool you would like to associate with the OOS Server, and select Edit Properties. Associate the Office Online Server with the Skype for Business pool:

Publish the topology.
A few minutes after the Topology is published, be on the lookout for event IDs 41032 & 41034 on the Skype for Business Front End Server. These confirm that the discovery of the Office Online Server has been successful.

To manually check if the Office Online Server website is running check:

Https://localhost/hosting/discovery or Https://servername/hosting/discovery

Source 1

23 August 2016

Fastest way to create and fill (multiple) relay allowed receive connectors, and remove multiple ip addresses

UPDATE 15-09-2016

Bulk remove

After adding all the old ip addresses at once, now was the time to remove some old ip addresses from servers that we're decommissioned.

Turn's out the script below can be edited at 1 character and it does the complete opposite.
Instead of adding it removes. Look at the line number 72:
Notice the "+" sign? Change this to "-" and it removes the IP addres.
The script shows its progress at the console, but it shows "Adding" instead of "Removing".
So when cleaning up the code to represent the correct Write-Host info I ended up with this:
function get_RecConnector{

  $RecConns = Get-ReceiveConnector | Select -ExpandProperty Identity
 $Count = 0;
 Write-Host "Bulk Add of Remote IP Addresses for Exchange Receive Connectors" -ForegroundColor Green
 Write-Host "Version 0.1" -ForegroundColor Green
 Write-Host "www.telnetport25.com" -ForegroundColor Green
 Write-Host ""
 Write-Host "Detected Receive Connectors: " -ForegroundColor Cyan
 Write-Host ""
 foreach($Connector in $RecConns){
  Write-Host $Count "." $Connector -ForegroundColor White
  $Count ++
 Write-Host ""
 $Choice = Read-Host "Please select the Receive Connector that you wish to work with."
 Write-Host ""
 import_RemoteIPRanges $RecConns[$Choice]

 function import_RemoteIPRanges{

 $FileName = Select-FileDialog "Open IP Range Text File..."
 $IPs = Get-Content $FileName
  foreach($IP in $IPs){
   Write-Host "Adding IP Address :" $IP " to "$ConnectorID -ForegroundColor Cyan
        $Rcnn = Get-ReceiveConnector "$ConnectorID"
        $Rcnn.RemoteIPRanges += $IP
        Set-ReceiveConnector "$ConnectorID" -RemoteIPRanges $Rcnn.RemoteIPRanges


Write-Host ""
Write-Host "Script Completed." -ForegroundColor Yellow

The script uses a text file in the same way as the "Add" script, simply paste your IP addresses in a new Remove.txt file and point to it when the script runs.

Bulk Add

Had to create 6 new receive connectors on separate servers, with the email relay allowed ip addresses from an old Exchange 2010 connector.

So first export the old: (See this previous post of mine)
Get-ReceiveConnector "sr-XXXXX\smtp relay" | fl remoteipranges | 
out-file "d:\temp\smtp relay sr-XXXX.txt"

Then edit this file so that every ip address is on a single line without spaces, like so:

Now create the new send connectors, and note that on a multi role Exchange server you can't choose "Hubtransport" as connector type. If you do you'll get an error stating that there's already a connector with those exact same settings.

New-ReceiveConnector -Name "SMTP-Relay-SR-XXXXX" -Server sr-XXXXX -Usage Custom 
-Bindings -RemoteIPRanges -MaxMessageSize 30MB -TransportRole 
frontendtransport -Enabled $False
Notice the "RemoteIPRanges" value, it has to have a value so remember to edit that out after importing the old ip address range from the old connector.
Also note the "-Enabled $False" value, if the security settings are in place and the ip address import went successful and the DNS entry for the connector is in place then enable it.

Then download the "BulkImportRemoteIPonRecConn.ps1" script from Andy Grogan to import the IP addresses. The script still works on Exchange 2013, not sure on 2016.

Then run the script:

[PS] C:\_Scripts\_TEST\BulkImportRemoteIpReceiveConnector>
Bulk Import of Remote IP Addresses for Exchange Receive Connectors
Version 0.1

 Detected Receive Connectors:

 0 . Servername\Client Servername
1 . Servername\Client Servername
2 . Servername\Default Servername
3 . Servername\Default Servername
4 . Servername\Default Servername
5 . Servername\Client Proxy Servername
6 . Servername\Default Frontend Servername
7 . Servername\Outbound Proxy Frontend Servername
8 . Servername\Client Frontend Servername
9 . Servername\XXXXX_inbound
10 . Servername\Default Servername
11 . Servername\Client Proxy Servername
12 . Servername\Client Frontend Servername
13 . Servername\XXXXX_inbound
14 . Servername\Default Servername
15 . Servername\Client Proxy Servername
16 . Servername\Default Frontend Servername
17 . Servername\Client Frontend Servername
18 . Servername\XXXXX_inbound
19 . Servername\Default Servername
20 . Servername\Client Proxy Servername
21 . Servername\Default Frontend Servername
22 . Servername\Outbound Proxy Frontend Servername
23 . Servername\Client Frontend Servername
24 . Servername\XXXXX_inbound
25 . Servername\Default Servername
26 . Servername\Client Proxy Servername
27 . Servername\Default Frontend Servername
28 . Servername\Outbound Proxy Frontend Servername
29 . Servername\Client Frontend Servername
30 . Servername\XXXXX_inbound
31 . Servername\Default Servername
32 . Servername\Client Proxy Servername
33 . Servername\Default Frontend Servername
34 . Servername\Outbound Proxy Frontend Servername
35 . Servername\Client Frontend Servername
36 . Servername\XXXXX_inbound
37 . Servername\Outbound Proxy Frontend Servername
38 . Servername\Default Frontend Servername
39 . Servername\Outbound Proxy Frontend Servername
40 . Servername\SMTP relay
41 . Servername\SMTP relay
42 . Servername\SMTP-Relay-Servername
43 . Servername\SMTP-Relay-Servername
44 . Servername\SMTP-Relay-Servername
45 . Servername\SMTP-Relay-Servername
46 . Servername\SMTP-Relay-Servername
47 . Servername\SMTP-Relay-Servername

 Please select the Receive Connector that you wish to work with.: 47

 Adding IP Address :  to  Servername\SMTP-Relay-Servername
Adding IP Address :  to  Servername\SMTP-Relay-Servername
Adding IP Address :  to  Servername\SMTP-Relay-Servername
Adding IP Address :  to  Servername\SMTP-Relay-Servername
Adding IP Address :  to  Servername\SMTP-Relay-Servername
Adding IP Address :  to  Servername\SMTP-Relay-Servername
Adding IP Address :  to  Servername\SMTP-Relay-Servername
Adding IP Address :  to  Servername\SMTP-Relay-Servername
Adding IP Address :  to  Servername\SMTP-Relay-Servername
Adding IP Address :  to  Servername\SMTP-Relay-Servername
Adding IP Address :  to  Servername\SMTP-Relay-Servername
Adding IP Address :  to  Servername\SMTP-Relay-Servername
Adding IP Address :  to  Servername\SMTP-Relay-Servername
Adding IP Address :  to  Servername\SMTP-Relay-Servername

Adding IP Address :  to  Servername\SMTP-Relay-Servername
Script Completed.
[PS] C:\_Scripts\_TEST\BulkImportRemoteIpReceiveConnector>

After the script completes set the security so Anonymous user access is granted. You have to do this at two places, one in PowerShell:
Get-ReceiveConnector "Servername\smtp-relay-Servername" | 
Add-ADPermission -User 'NT AUTHORITY\Anonymous Logon' 
-ExtendedRights MS-Exch-SMTP-Accept-Any-Recipient
And one in the EAC on (all) the newly created receive connectors

Your connectors are done.