PowerShell

Add Skype for Business Federation Partner/Domain

Hey again!

Have you been searching and looking around to find a way to automate or use PowerShell for adding federation partners to Skype for Business Online?

Then here’s a great example for you, feel free to use the script, edit and tweak it. If you do tweak and edit/improving it. Please go ahead and share it with the community and also link to my blog post.

In my case I’m using PowerShell version 5 together with Skype for Business module, which is a requirement for connecting to the cloud service(s).

The script in itself is pretty much straight forward, type in one or more domains and they get added into the alloweddomains list.
This can be handy if you’re not using open federation and have to add a couple of new domains every now and then..

 


<#
.SYNOPSIS
Filename: Add-CsFedDomain.psm1

Jonas Andersson
Jonas.Andersson@testlabs.se

THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE
ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS
WITH THE USER.

Version 1.0, September 25th, 2016

.DESCRIPTION
Used for adding new domain(s) for Skype for Business Online

.PREREQUISITES
Connect to Skype for Business Online using the PowerShell module

Revision History
--------------------------------------------------------------------------------
1.0     Initial release

.EXAMPLE
Add-CsFederationDomain -domainName domain1.com
Add-CsFederationDomain -domainName domain1.com,domain2.com,domain3.com

#>

function Add-CsFederationDomain (
[Parameter(Mandatory = $true)][array]$domainName
)
{
if ((Get-MsolDomain -ErrorAction 0) -eq $null)
{
Write-Host "Not connected to O365, use ConnectToO365-P*" -ForegroundColor Red
break
}

$tenant = Get-CsTenant
$domainName = $domainName.split(",")
$domainName = $domainName.split(";")
$domainName = $domainName.split(",")
$domainName = $domainName.Replace(" ","")

if ($domainName.Count -lt 2)
{
[string]$domainName = $domainName[0].ToString()
Write-Host "#########################################################################################" -ForegroundColor White
Write-Host "Domain: $domainName" -ForegroundColor DarkGreen

$x = Get-CsTenantFederationConfiguration –Tenant $tenant.TenantId
$domain = $x.AllowedDomains.AllowedDomain | ?{$_.Domain -eq $domainName}
if ($domain -eq $null)
{
$d1 = New-CsEdgeDomainPattern -Domain $domainName
$x.AllowedDomains.AllowedDomain.Add($d1)
Set-CsTenantFederationConfiguration -Tenant $tenant.tenantID  -AllowedDomains $x.AllowedDomains
Write-Host "Domain $domainName was added successfully" -ForegroundColor Green
}
else
{
Write-Host "ERROR: $domainName already in allowed list" -ForegroundColor Red
}
}

if ($domainName.Count -gt 1)
{
foreach ($newdomain in $domainName)
{
Write-Host "#########################################################################################" -ForegroundColor White
Write-Host "Domain: $newdomain" -ForegroundColor DarkGreen

$x = Get-CsTenantFederationConfiguration –Tenant $tenant.TenantId
$domain = $x.AllowedDomains.AllowedDomain | Where-Object {$_.Domain -eq $newdomain}
if ($domain -eq $null)
{
$d1 = New-CsEdgeDomainPattern -Domain $newdomain
$x.AllowedDomains.AllowedDomain.Add($d1)
Set-CsTenantFederationConfiguration -Tenant $tenant.tenantID -AllowedDomains $x.AllowedDomains
Write-Host "Domain $newdomain was added successfully" -ForegroundColor Green
}
else
{
Write-Host "ERROR: $newdomain already in allowed list" -ForegroundColor Red
}
}
}
}

Inspiration from this great blog post:

https://gotspeechguy.com/2012/06/21/setting-up-a-tenants-allowed-domains-for-federation/

Populate extensionAttribute with value using PowerShell

Implementing ADFS using the new feature within KB2919355 for Windows Server 2012 R2 called Alternative Login ID? (http://technet.microsoft.com/en-us/library/dn659436.aspx)

The configuration for Alternative Login ID is fairly simple, the extensionAttributes/CustomAttributes can be used and I want to share a script with you for populating values into the attributes.

Use the script as much as you want, make sure to test it before implementing into production.
All contents is provided “AS IS” with no warranties, and confers no rights. You assume all risk for your use.

 

# +=======================================================================
# | Blog: http://www.testlabs.se/blog
# | Twitter: @jonand82
# | =============================================
# | Filename: populate_extensionattribute15_v1.0.ps1
# |
# | CREATED BY: Jonas Andersson
# | FUNCTION: Populates users extensionAttribute15 with SamAccountName plus a value
# |
# | CHANGE LOG:
# | v1.0 - 2014-05-28, *Created*
# +=======================================================================

$users = Get-ADUser -Filter * -SearchScope Subtree -SearchBase "OU=Users,OU=Testlabs,DC=testlabs,DC=se" | Select-Object DistinguishedName, SamAccountName
$value = "@testlabs.se"
foreach ($i in $users)
{
$ext = ($i.SamAccountName) + $value
Write-Host "extensionAttribute15:", $ext

$id = $i.DistinguishedName
$user = Get-ADUser -Identity $id -Properties extensionAttribute1
Set-ADUser –Identity $user -Clear "extensionAttribute15"
Set-ADUser -Identity $user -Add @{extensionAttribute15 = $ext}
}
Update: Exchange 2013 script – automatic installation of prerequisites v2.1 *NEW*

Update: Exchange 2013 script – automatic installation of prerequisites v2.1 *NEW*

*Update*

*********************************************************************************************************************************************

Reuben Welsh came up with a great feature request regarding verifying the checksum of the files that’s being installed.
This has been implemented in the version 2.1 of the script.

*********************************************************************************************************************************************

For a year ago I was publishing a script that helped with installing prerequsites for Exchange 2013, this has now been updated so it also works for Exchange 2013 SP1 and Windows Server 2012 R2.
I hope this script helps someone for a smoother installation.
The script can be downloaded here: http://www.testlabs.se/blog/wp-content/uploads/2014/04/Install-Exchange2013PreReqs_v2.1.zip

*********************************************************************************************************************************************

Feel free to use this, make sure to test it in a test environment before using it inside production.
All contents is provided “AS IS” with no warranties, and confers no rights. You assume all risk for your use.

# +=======================================================================
 # | Blog: <a href="http://www.testlabs.se/blog">http://www.testlabs.se/blog</a>
 # | Twitter: @jonand82
 # | =============================================
 # | Filename: Install-Exchange2013PreReqs_v2.1.ps1
 # |
 # | CREATED BY: Jonas Andersson - Original written by: Pat Richard, Anderson Patricio and Bhargav Shukla
 # | FUNCTION: Installs and configures the prerequisites to install Exchange 2013 on..
 # | ..Windows Server 2008 R2, Windows Server 2012 or Windows Server 2012 R2 server
 # |
 # | CHANGE LOG:
 # | v1.0 - 2013-04-05, *Created*
 # | v2.0 - 2014-04-11, *Updated with functions*
 # | v2.1 - 2014-04-28, *Checksum implemented*
 # |
 # | <a href="http://www.ucblogs.net/blogs/exchange/archive/2009/12/12/Automated-prerequisite-installation-via-PowerShell-for-Exchange-Server-2010-on-Windows-Server-2008-R2.aspx">http://www.ucblogs.net/blogs/exchange/archive/2009/12/12/Automated-prerequisite-installation-via-PowerShell-for-Exchange-Server-2010-on-Windows-Server-2008-R2.aspx</a>
 # | <a href="http://msmvps.com/blogs/andersonpatricio/archive/2009/11/13/installing-exchange-server-2010-pre-requisites-on-windows-server-2008-r2.aspx">http://msmvps.com/blogs/andersonpatricio/archive/2009/11/13/installing-exchange-server-2010-pre-requisites-on-windows-server-2008-r2.aspx</a>
 # | <a href="http://www.bhargavs.com/index.php/powershell/2009/11/script-to-install-exchange-2010-pre-requisites-for-windows-server-2008-r2/">http://www.bhargavs.com/index.php/powershell/2009/11/script-to-install-exchange-2010-pre-requisites-for-windows-server-2008-r2/</a>
 # | <a href="http://www.tinyint.com/index.php/2011/09/14/get-an-md5-or-sha1-checksum-with-powershell/">http://www.tinyint.com/index.php/2011/09/14/get-an-md5-or-sha1-checksum-with-powershell/</a>
 # +=======================================================================

# Detect correct OS here and exit if no match
 if (-not((Get-WMIObject win32_OperatingSystem).OSArchitecture -eq '64-bit') -and (((Get-WMIObject win32_OperatingSystem).Version -eq "6.1.7601") -or ((Get-WMIObject win32_OperatingSystem).Version -eq "6.2.9200") -or ((Get-WMIObject win32_OperatingSystem).Version -eq "6.3.9600"))) {
 Write-Host "This script requires a 64bit version of Windows Server 2008 R2, Windows Server 2012 or Windows Server 2012 R2, which this is not." -ForegroundColor Red -BackgroundColor Black
 Exit
 }

function Get-Checksum
 {
 Param (
 [string]$File=$(throw("You must specify a filename to get the checksum of.")),
 [ValidateSet("sha1","md5")]
 [string]$Algorithm="sha1"
 )

$fs = new-object System.IO.FileStream $File, "Open"
 $algo = [type]"System.Security.Cryptography.$Algorithm"
 $crypto = $algo::Create()
 $hash = [BitConverter]::ToString($crypto.ComputeHash($fs)).Replace("-", "")
 $fs.Close()
 $hash
 }

function Disable-UAC() {

function UAC-status() {

$path = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System"
 $EnableLUA = ""
 $EnableLUA = Get-ItemProperty $path -Name EnableLUA

if ($EnableLUA.EnableLUA -eq "0") {
 [bool]$UACenabled = $false
 }

if ($EnableLUA.EnableLUA -eq "1") {
 [bool]$UACenabled = $true
 }

return $UACenabled
 }

[bool]$status = UAC-status

if ($status -ne $true) {
 Write-Host "UAC already disabled" -ForegroundColor Green
 return
 }

else {

Write-Host "Starting to disable UAC.."

Set-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System" -Name "EnableLUA" -Value 0
 Start-Sleep -Seconds 2

[bool]$status = UAC-status

if ($status -ne $false) {
 Write-Host "An error occurred, try again." -ForegroundColor Red
 return
 }

else {
 Write-Host "UAC Enabled:", $status
 Write-Host "...."
 Write-Host "UAC is now disabled" -ForegroundColor Green
 Write-Host "Registry key HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA has been changed." -ForegroundColor White
 }
 }
 }

function Disable-FW() {

function FW-status() {

$status = ""
 $status = netsh advfirewall show allprofiles state

if ($status | Select-String "ON") {
 [bool]$enabled = $true
 }

else {
 [bool]$enabled = $false
 }

return $enabled
 }

[bool]$fwstatus = FW-status

if ($fwstatus -eq $false) {
 Write-Host "Firewall is already disabled" -ForegroundColor Green
 return
 }

if ($fwstatus -eq $true) {

Write-Host "Starting to disable the firewall.."

$param = "advfirewall set allprofiles state off"
 $run = (Start-Process netsh -ArgumentList $param -Wait -PassThru).ExitCode
 if ($run -ne 0) { Write-Host "Failed!" -ForegroundColor Red }

[bool]$fwstatus = FW-status

if ($fwstatus -ne $false) {
 Write-Host "An error occurred, try again." -ForegroundColor Red
 return
 }

else {
 Write-Host "Firewall enabled:", $fwstatus
 Write-Host "...."
 Write-Host "Firewall is now disabled" -ForegroundColor Green
 }
 }
 }

function InstallFilterPack() {

function DownloadFilterPack1() {

#Download Microsoft Filter Pack
 Write-Host "Downloading Microsoft Filter Pack..." -nonewline
 $clnt = New-Object System.Net.WebClient
 $url = "<a href="http://download.microsoft.com/download/0/A/2/0A28BBFA-CBFA-4C03-A739-30CCA5E21659/FilterPack64bit.exe&quot;">http://download.microsoft.com/download/0/A/2/0A28BBFA-CBFA-4C03-A739-30CCA5E21659/FilterPack64bit.exe"</a>
 $clnt.DownloadFile($url,$file1)
 Write-Host "done!" -ForegroundColor Green
 }

function DownloadFilterPack2() {

#Download Microsoft Filter Pack SP1
 Write-Host "Downloading Microsoft Filter Pack SP1..." -nonewline
 $clnt = New-Object System.Net.WebClient
 $url = "<a href="http://download.microsoft.com/download/A/A/3/AA345161-18B8-45AE-8DC8-DA6387264CB9/filterpack2010sp1-kb2460041-x64-fullfile-en-us.exe&quot;">http://download.microsoft.com/download/A/A/3/AA345161-18B8-45AE-8DC8-DA6387264CB9/filterpack2010sp1-kb2460041-x64-fullfile-en-us.exe"</a>
 $clnt.DownloadFile($url,$file2)
 Write-Host "done!" -ForegroundColor Green
 }

function InstallFilterPack1() {

#Install Microsoft Filter Packs 1
 Write-Host "Installing Microsoft Filter Packs..."

$args = "/quiet /norestart"
 $setup1 = (Start-Process $file1 -ArgumentList $args -Wait -PassThru).ExitCode
 if ($setup1 -eq 0) {
 Write-Host "Successfully installed $file1" -ForegroundColor Green
 }

if ($setup1 -ne 0) {
 Write-Host "Failed!" -ForegroundColor Red
 }
 }

function InstallFilterPack2() {

$args = "/quiet /norestart"
 $setup2 = (Start-Process $file2 -ArgumentList $args -Wait -PassThru).ExitCode
 if ($setup2 -eq 0) {
 Write-Host "Successfully installed $file2" -ForegroundColor Green
 }

if ($setup2 -ne 0) {
 Write-Host "Failed!" -ForegroundColor Red
 }
 }

if (Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\{95140000-2000-0409-1000-0000000FF1CE}" -ErrorAction SilentlyContinue) {

Write-Host "FilterPack is already installed." -ForegroundColor Yellow
 return
 }

else {

trap {
 Write-Host "Problem downloading FilterPackx64.exe. Please visit: <a href="http://www.microsoft.com/en-us/download/details.aspx?id=26604">http://www.microsoft.com/en-us/download/details.aspx?id=26604</a> and <a href="http://www.microsoft.com/en-us/download/details.aspx?id=17062&quot;">http://www.microsoft.com/en-us/download/details.aspx?id=17062"</a>
 break
 }

#set a var for the folder you are looking for
 $folderPath = 'C:\Temp'

#Check if folder exists, if not, create it
 if (Test-Path $folderpath) {
 Write-Host "The folder $folderPath exists."
 }

else {
 Write-Host "The folder $folderPath does not exist, creating..." -NoNewline
 New-Item $folderpath -type directory | Out-Null
 Write-Host "done!" -ForegroundColor Green
 }

$file1 = $folderPath+"\FilterPack64bit.exe"
 $file1chksum = "9253B09EA9A2ADD0E773CD30FE4120F5732C4D98"

$file2 = $folderPath+"\filterpack2010sp1-kb2460041-x64-fullfile-en-us.exe"
 $file2chksum = "2C7B81D0C148E3E1894A9183FEE6A543EA5DC9B2"

# Check if file exists, if not, download it
 if (Test-Path $file1) {
 Write-Host "The file $file1 exists."

$chksum1 = Get-Checksum $file1
 if ($file1chksum.CompareTo($chksum1) -eq 0) {
 Write-Host "Checksum OK" -ForegroundColor 'Green'
 InstallFilterPack1
 }

else {
 Write-Host "Checksum Error, removing $file1" -ForegroundColor 'Red'
 Remove-Item $file1
 DownloadFilterPack1
 InstallFilterPack1
 }
 }

else {
 #Download Microsoft Filter Pack
 DownloadFilterPack1

#Install FilterPack 1
 InstallFilterPack1
 }

if (Test-Path $file2) {
 Write-Host "The file $file2 exists."

$chksum2 = Get-Checksum $file2
 if ($file2chksum.CompareTo($chksum2) -eq 0) {
 Write-Host "Checksum OK" -ForegroundColor 'Green'
 InstallFilterPack2
 }

else {
 Write-Host "Checksum Error, removing $file2" -ForegroundColor 'Red'
 Remove-Item $file2
 DownloadFilterPack2
 InstallFilterPack2
 }
 }

else {
 #Download Microsoft Filter Pack SP1
 DownloadFilterPack2

#Install Microsoft Filter Pack SP1
 InstallFilterPack2
 }
 }
 }

function InstallUMAPI() {

function InstallMicrosoftUMAPI() {

#Check/Install Media Foundation feature
 $mf = Get-WindowsFeature "Server-Media-Foundation" | select *

Start-Sleep 2

if ($mf.Installed -eq $False) {

Write-Host "Installing Media Foundation feature..."    -ForegroundColor Green
 Add-Windowsfeature Server-Media-Foundation

Write-Host ""
 Write-Host "Installing of Media Foundation feature completed." -ForegroundColor Green
 Write-Host ""
 Write-Host "Restart the server and restart the task" -ForegroundColor Red
 Write-Host "or else the UM API won't be installed" -ForegroundColor Red
 Write-Host ""
 return
 }

if ($mf.Installed -eq $True) {

#Install Microsoft UM API
 Write-Host "Installing Microsoft UM API..." -ForegroundColor Green

$args = "/quiet /norestart"
 $setup = (Start-Process $file -ArgumentList $args -Wait -PassThru).ExitCode
 if ($setup -eq 0) {
 Write-Host "Successfully installed $file" -ForegroundColor Green
 }

if ($setup -ne 0) {
 Write-Host "Failed!" -ForegroundColor Red
 }
 }
 }

function DownloadMicrosoftUMAPI() {

#Download Microsoft UM API
 Write-Host "Downloading Microsoft UM API..." -nonewline
 $clnt = New-Object System.Net.WebClient
 $url = "<a href="http://download.microsoft.com/download/2/C/4/2C47A5C1-A1F3-4843-B9FE-84C0032C61EC/UcmaRuntimeSetup.exe&quot;">http://download.microsoft.com/download/2/C/4/2C47A5C1-A1F3-4843-B9FE-84C0032C61EC/UcmaRuntimeSetup.exe"</a>
 $clnt.DownloadFile($url,$file)
 Write-Host "done!" -ForegroundColor Green
 }

#Checking for regkey
 if (Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\UCMA4" -ErrorAction SilentlyContinue) {

Write-Host "Unified Communications Managed API 4.0 Runtime is already installed." -ForegroundColor yellow
 return
 }

else {

trap {
 Write-Host "Problem downloading UM API. Please visit: <a href="http://www.microsoft.com/en-us/download/details.aspx?id=34992&quot;">http://www.microsoft.com/en-us/download/details.aspx?id=34992"</a>
 break
 }

#set a var for the folder you are looking for
 $folderPath = 'C:\Temp'

#Check if folder exists, if not, create it
 if (Test-Path $folderpath) {
 Write-Host "The folder $folderPath exists."
 }

else {
 Write-Host "The folder $folderPath does not exist, creating..." -NoNewline
 New-Item $folderpath -type directory | Out-Null
 Write-Host "done!" -ForegroundColor Green
 }

# Check if file exists, if not, download it
 $file = $folderPath+"\UcmaRuntimeSetup.exe"
 $filechksum = "5E4D536E916F9C97EE5A91A61952589825AEAA6C"
 if (Test-Path $file) {
 Write-Host "The file $file exists."

$chksum3 = Get-Checksum $file
 if ($filechksum.CompareTo($chksum3) -eq 0) {
 Write-Host "Checksum OK" -ForegroundColor 'Green'

#Install Microsoft UM API
 InstallMicrosoftUMAPI
 }

else {
 #Remove the file with wrong checksum
 Remove-Item $file

#Download Microsoft UM API
 DownloadMicrosoftUMAPI

#Install Microsoft UM API
 InstallMicrosoftUMAPI
 }
 }

else {
 #Download Microsoft UM API
 DownloadMicrosoftUMAPI

#Install Microsoft UM API
 InstallMicrosoftUMAPI
 }
 }
 }

Import-Module ServerManager
 $opt = "None"
 # Do {
 clear
 if ($opt -ne "None") {Write-Host "Last command: "$opt -foregroundcolor Yellow}
 Write-Host
 Write-Host Exchange Server 2013 SP1 - Prerequisites script
 Write-Host Please, select which role you are going to install..
 Write-Host
 Write-Host '1) Client Access Server'
 Write-Host '2) Mailbox'
 Write-Host '3) Typical (CAS/Mailbox)'
 Write-Host
 Write-Host '10) Install Microsoft Filter Pack 2.0'
 Write-Host '    Recommended if installing Mailbox Server roles' -foregroundcolor yellow
 Write-Host '    Automatically set for options 2 and 3' -foregroundcolor yellow
 Write-Host '11) Install Microsoft UM API' -foregroundcolor yellow
 Write-Host '    Automatically set for options 1, 2 and 3' -foregroundcolor yellow
 Write-Host '12) Disable UAC'
 Write-Host '13) Disable Firewall'
 Write-Host
 Write-Host '18) Restart the Server'
 Write-Host '19) End'
 Write-Host
 $opt = Read-Host "Select an option.. [1-19]? "

$Win2008feat = "Desktop-Experience", "NET-Framework", "NET-HTTP-Activation", "RPC-over-HTTP-proxy", "RSAT-Clustering", "RSAT-Web-Server", "WAS-Process-Model", "Web-Asp-Net", "Web-Basic-Auth", "Web-Client-Auth", "Web-Digest-Auth", "Web-Dir-Browsing", "Web-Dyn-Compression", "Web-Http-Errors", "Web-Http-Logging", "Web-Http-Redirect", "Web-Http-Tracing", "Web-ISAPI-Ext", "Web-ISAPI-Filter", "Web-Lgcy-Mgmt-Console", "Web-Metabase", "Web-Mgmt-Console", "Web-Mgmt-Service", "Web-Net-Ext", "Web-Request-Monitor", "Web-Server", "Web-Stat-Compression", "Web-Static-Content", "Web-Windows-Auth", "Web-WMI"
 $Win2012feat = "AS-HTTP-Activation", "Desktop-Experience", "NET-Framework-45-Features", "RPC-over-HTTP-proxy", "RSAT-Clustering", "RSAT-Clustering-CmdInterface", "RSAT-Clustering-Mgmt", "RSAT-Clustering-PowerShell", "Web-Mgmt-Console", "WAS-Process-Model", "Web-Asp-Net45", "Web-Basic-Auth", "Web-Client-Auth", "Web-Digest-Auth", "Web-Dir-Browsing", "Web-Dyn-Compression", "Web-Http-Errors", "Web-Http-Logging", "Web-Http-Redirect", "Web-Http-Tracing", "Web-ISAPI-Ext", "Web-ISAPI-Filter", "Web-Lgcy-Mgmt-Console", "Web-Metabase", "Web-Mgmt-Console", "Web-Mgmt-Service", "Web-Net-Ext45", "Web-Request-Monitor", "Web-Server", "Web-Stat-Compression", "Web-Static-Content", "Web-Windows-Auth", "Web-WMI", "Windows-Identity-Foundation"

switch ($opt) {
 1 {

# Windows Server 2008 R2 SP1
 if ((Get-WMIObject win32_OperatingSystem).Version -eq "6.1.7601") {

InstallUMAPI
 Import-Module ServerManager
 Add-WindowsFeature $Win2008feat -restart
 }

# Windows Server 2012 or Windows Server 2012 R2
 if (((Get-WMIObject win32_OperatingSystem).Version -eq "6.2.9200") -or ((Get-WMIObject win32_OperatingSystem).Version -eq "6.3.9600")) {

InstallUMAPI
 Install-WindowsFeature $Win2012feat -restart
 }
 }

2 {

# Windows Server 2008 R2 SP1
 if ((Get-WMIObject win32_OperatingSystem).Version -eq "6.1.7601") {

Import-Module ServerManager
 InstallUMAPI
 InstallFilterPack
 Add-WindowsFeature $Win2008feat -restart
 }

# Windows Server 2012 or Windows Server 2012 R2
 if (((Get-WMIObject win32_OperatingSystem).Version -eq "6.2.9200") -or ((Get-WMIObject win32_OperatingSystem).Version -eq "6.3.9600")) {

InstallUMAPI
 InstallFilterPack
 Install-WindowsFeature $Win2012feat -restart
 }
 }

3 {

# Windows Server 2008 R2
 if ((Get-WMIObject win32_OperatingSystem).Version -eq "6.1.7601") {

Import-Module ServerManager
 InstallFilterPack
 InstallUMAPI
 Add-WindowsFeature $Win2008feat -restart
 }

# Windows Server 2012 or Windows Server 2012 R2
 if (((Get-WMIObject win32_OperatingSystem).Version -eq "6.2.9200") -or ((Get-WMIObject win32_OperatingSystem).Version -eq "6.3.9600")) {

InstallUMAPI
 InstallFilterPack
 Install-WindowsFeature $Win2012feat -restart
 }
 }

10 {
 # future - auto detect Internet access
 Write-Host 'Can this server access the Internet?'
 $filtpack = Read-Host 'Please type (Y)es or (N)o...'
 switch ($filtpack)                {
 Y { InstallFilterPack }
 N {Write-warning 'Please download and install Microsoft Filter Pack from here: <a href="http://www.microsoft.com/en-us/download/details.aspx?id=26604">http://www.microsoft.com/en-us/download/details.aspx?id=26604</a> and <a href="http://www.microsoft.com/en-us/download/details.aspx?id=17062'}">http://www.microsoft.com/en-us/download/details.aspx?id=17062'}</a>
 }
 }

11 {
 # future - auto detect Internet access
 Write-Host 'Can this server access the Internet?'
 $umapi = Read-Host 'Please type (Y)es or (N)o...'
 switch ($umapi)                {
 Y { InstallUMAPI }
 N {Write-Warning 'Please download and install Microsoft UM API from here: <a href="http://www.microsoft.com/en-us/download/details.aspx?id=34992'}">http://www.microsoft.com/en-us/download/details.aspx?id=34992'}</a>
 }
 }

12 { Disable-UAC }
 13 { Disable-FW }
 18 { Restart-Computer }
 19 {
 Write-Host "Exiting..."
 Exit
 }
 default {Write-Host "You haven't selected any of the available options. "}
 }

Bulk import PST files – [updated] v1.1

Bulk import PST files – [updated] v1.1

Just wrote a basic script for importing PST files into mailboxes, that I want to share with the community.

It is designed to check for PST files in the specified folder. Based on the filenames (of the PST files) it then verifies that a mailbox can be found. This is done by using the filename and adding the @ character and the domain value into a string value. If there is a match, it returns a value of $True and the script continues with running the New-MailboxImportRequest cmdlet.

The script is written just as basic as it can, it provides much information about values and what’s going on.
The most recent updated script can be downloaded here

I hope this will help you to import the PST files into the mailboxes

Ps. Sorry for the word-wrap, see the script file instead of copy the script code below

Changelog
v1.1
– Updated the $name variable due to issues with filenames got trimmed away. Also added so that if errors exists, they will be sent to a errorlog. Thanks to Chris Steding!

# +=======================================================================
# | Blog: http://www.testlabs.se/blog
# | Twitter: @jonand82
# | =============================================
# | Filename: Import-PST v1.1.ps1
# |
# | CREATED BY: Jonas Andersson
# | FUNCTION: Imports PST files into mailboxes, matching on emailaddresses
# |
# | CHANGE LOG: 
# | v1.0 - 2013-09-18, *Created*
# | v1.1 - 2013-09-22, *Update of $name variable*
# |
# |    Required permissions (RBAC) Role: “Mailbox Import Export”, example: New-Managementroleassignment –Role “Mailbox Import Export” –User “Administrator”
# +=======================================================================

# Load snapin
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction 'SilentlyContinue'

# Variables
$error.clear()
$errorlog = "C:\temp\errorlog.txt"
$pstpath = "C:\temp"
$domain = "testlabs.se"
$servername = "tlex01"
$files = Get-ChildItem -Path $pstpath -Filter *.pst

Write-Host $files

if (($files -ne $null) -or ($files -eq "")) {

    foreach ($i in $files) {

        $name = $i.BaseName
        $id = $name + "@" + $domain
        $filename = $i.FullName
        $filename = $filename.Replace(":","$")
        $uncfilepath = "\\" + $servername + "\" + $filename

        Write-Host "#################################################################"
        Write-Host "Filename:" $i -ForegroundColor 'Cyan'
        Write-Host "UNC path:" $uncfilepath -ForegroundColor 'DarkCyan'
        Write-Host "Emailaddress:" $id -ForegroundColor 'DarkGreen'

        $MailboxExists = [bool](Get-Mailbox -Identity $id -ErrorAction SilentlyContinue)

        if ($MailboxExists -eq $false)
        {
            Write-Host "Found mailbox:" $MailboxExists -ForegroundColor 'Red'
            Write-Host "Make sure to match filename to mailaddress, without @domain" -ForegroundColor 'Red'

        }

        if ($MailboxExists -eq $true)
        {
            Write-Host "Found mailbox:" $MailboxExists -ForegroundColor 'Green'
            Write-Host "Importing $uncfilepath into mailbox: $id" -ForegroundColor 'White'

            New-MailboxImportRequest -Mailbox $id -FilePath $uncfilepath

        }

        Write-Host ""
    }

}

else
{
    Write-Host "No PST files found"
}

if ($error -ne $null)
{
    $error | Out-File -FilePath $errorlog -Append
    Write-Host "See $errorlog for errors" -ForegroundColor 'Red'
}
Migration Preparation script

Migration Preparation script

This script idea came up after being involved in a migration project.

Published: 2013-05-22
Updated: 2013-05-24
Version: 1.1

It’s purpose with this script is for getting Quest Migration Manager (QMM) being able to match objects between domains. In a scenario with one-way trust and not being able to use Quest Migration Manager AD or any other tool for providing the SIDHistory into the AD objects. Users, mailboxes and mail contacts are already created, where the contacts are used for having a global address list (GAL) object they can send emails to.

Using QMM you can match by Username, Mailaddress or SIDHistory. In my case the username differs and the SIDHistory is not available (not allowed being copied into the target AD).

I created four different functions within this script, one called “Export-SourceInformation”, which should be used in the source environment. It will export the information from the source regarding Name, DisplayName, PrimarySmtpAddress, RecipientTypeDetails and save it into a CSV file called “users.csv”.

Then bring the CSV file into the target environment. This CSV file should be used as a control file if you don’t want to run all users at the same time (run some tests before running all of them in one batch).
I would recommend a couple of smaller batches for testing the functions before deploying it in full scale.

There is a function called “Verify-TargetInformation”, which uses the CSV file called “users.csv” and retrieves the Name and PrimarySmtpAddress for each object in the CSV file.

Another function is called “Set-SourceAddress”, this part takes care of the target account.
It uses the file called “users.csv” and checks whether there are any contacts for these mailboxes, if there are the mail contact will be deleted and the mailbox forward settings will be removed together with making sure that the mailbox is showed in the GAL. But before any changes are done, the current configuration for both the mail contact and the mailbox object are being saved into a CSV file called “targetinformation.csv”.

Last but not least, the function called “Rollback-TargetInformation” is used for putting back the PrimarySmtpAddress to the value that it was prior to the change, this by using the CSV file “targetinformation.csv”. When the Directory Synchronization have successfully matched the mailboxes this function should be runned for having back the correct information.

You can use this for free, without any guarantee or warranty and at your own risk.
Feel free to post about it, just make sure to link my blog and blogpost.

Download the script

##################################################################################### 
# Filename: Migration-Preparation-testlabs.ps1  
# Description: 
# This PowerShell script exports information, configures objects and prepares for 
# Quest Migration Manager EX Directory Synchronization 
# 
# Usage: Import-Module Migration-Preparation-testlabs.ps1 
# Start with importing the module, then Starting function: Export-SourceInformation; 
# Set-SourceAddress; Rollback-TargetInformation; Verify-TargetInformation 
# 
# Version: 1.1
#
# Changelog:
# v1.1 - Introduced LegacyExchangeDN - X500 preparation
#
# Jonas Andersson, MCC 2011 & 2012 
# http://www.testlabs.se/blog 
# Twitter @jonand82 
#####################################################################################

Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction SilentlyContinue
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin -ErrorAction SilentlyContinue

## Exporting the SMTP information from Source mailboxes 
Function Export-SourceInformation(){ 

    $filename = "users.csv" 

    $users = Get-Mailbox -resultsize unlimited | Select Name,DisplayName,PrimarySmtpAddress,RecipientTypeDetails,LegacyExchangeDN
    $users | Export-CSV $filename -notype -Encoding Unicode 

}

## Changing Target mailboxes to Source PrimarySmtpAddress for QMM to match on it 
Function Set-SourceAddress(){ 

    $data = Import-CSV .\users.csv 
    $filename = "targetinformation.csv" 

    ## Saving Target Information into CSV file before changing 
    $MasterList = @() 
    Foreach($t in $data) 
    { 
        $str = $t.displayname 
        $MyObject = New-Object PSObject -Property @{ 

        Name = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").Name 
        DisplayName = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").DisplayName 
        PrimarySmtpAddress = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").PrimarySmtpAddress 
        RecipientTypeDetails = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").RecipientTypeDetails 
        Email = ((Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").EmailAddresses -Join ";") 
        DeliverToMailboxAndForward = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").DeliverToMailboxAndForward 
        ForwardingAddress = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").ForwardingAddress 
        ForwardingSmtpAddress = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").ForwardingSmtpAddress 
        HiddenFromAddressListsEnabled = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").HiddenFromAddressListsEnabled 
        LegacyExchangeDN = (Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'").LegacyExchangeDN
        ContactName = (Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'").Name 
        ContactDisplayName = (Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'").DisplayName 
        ContactPrimarySmtpAddress = (Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'").PrimarySmtpAddress 
        ContactEmail = ((Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'").EmailAddresses -Join ";") 
        ContactExternalEmailAddress = (Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'").ExternalEmailAddress 
        ContactHiddenFromAddressListsEnabled = (Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'").HiddenFromAddressListsEnabled

        } 

        $MasterList += $MyObject 
    } 

    $MasterList | Export-Csv $filename -NoTypeInformation -Encoding Unicode 
    Write-Host "Information is saved into the CSV file: $filename" -ForegroundColor White 

    Foreach($i in $data) 
    { 
        $str = $i.displayname 

        ## Removing mail contacts for Source users 
        $c = Get-MailContact -resultsize unlimited -Filter "DisplayName -like '*$str*'" 
        Write-Host $c -ForegroundColor Yellow 

        ## Multiple matching, no changes will be done 
        if ($c.count -ge 1) 
        { 
            Write-Host "ERROR: Multiple matching" 
            Write-Host "Matches: $c.count" 
            return 
        } 

        ## Unique contact found, removing it 
        if ($c.count -eq $null) 
        { 
            Write-Host "Unique matching: $c" 
            Write-Host "Removing the mail contact object for: $c" 

            Remove-MailContact -Identity $c -Confirm:$false 

        } 

        ## Starting the configuration for Target Mailboxes 
        $u = Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'" 

        Write-Host $u -ForegroundColor Yellow 

        ## Multiple matching, no changes made 
        if ($u.count -ge 1) 
        { 
            Write-Host "ERROR: Multiple matching" 
            Write-Host "Matches: $u.count" 
            return 
        } 

        ## Setting the Source PrimarySmtpAddress on the Target Mailboxes 
        if ($u.count -eq $null) 
        { 
            Write-Host "Unique matching: $u" 
            Write-Host "Setting Source SMTP as PrimaryAddress for matching using QMM" 
            Write-Host "Configuring the mailbox for showing up in GAL and remove the forwarding configuration"
            Write-Host "Adding the LegacyExchangeDN as X500 for Outlook auto-complete cache"
 

            $email = $i.PrimarySmtpAddress
            $x500 = $i.LegacyExchangeDN

            Set-Mailbox -Identity $u -ForwardingAddress $null -DeliverToMailboxAndForward:$false -HiddenFromAddressListsEnabled:$false -PrimarySmtpAddress $email -EmailAddressPolicyEnabled:$false 

            $ProxyAddresses = (Get-Mailbox -Identity $u).EmailAddresses
            $ProxyAddresses += [Microsoft.Exchange.Data.CustomProxyAddress]("X500:$x500")
            Set-Mailbox -Identity $u -EmailAddresses $ProxyAddresses
        } 

        else 
        { 
            Write-Host "No match" 
            return 
        } 

    } 

    Write-Host "" 
    Write-Host "#################################################################" -ForegroundColor White 
    Write-Host "# First run the Verify-TargetInformation..                        #" -ForegroundColor White 
    Write-Host "# Start the QMM Synchronization for matching Source <-> Target  #" -ForegroundColor White 
    Write-Host "# Finally run the Rollback-TargetInformation when sync is done  #" -ForegroundColor White 
    Write-Host "#################################################################" -ForegroundColor White 
    Write-Host "" 
}

## Rollback of Target PrimarySmtpAddress 
Function Rollback-TargetInformation(){ 

    $data = Import-CSV .\targetinformation.csv 

    $MasterList = @() 
    Foreach($i in $data) 
    { 

        $str = $i.displayname 
        $user = Get-Mailbox -resultsize unlimited -Filter "DisplayName -like '*$str*'" 

        ## Predicts there is only one @testlabs.se address 
        $pri = Get-Mailbox -Identity $user | Select-Object -ExpandProperty EmailAddresses | Where-Object {$_.SmtpAddress -like '*@testlabs.se'} | Select-Object SmtpAddress 
        $adr = $pri.SmtpAddress 

        Write-Host "Configuring mailbox: $user with adress: $adr" -ForegroundColor White 
        Set-Mailbox -Identity $user -PrimarySmtpAddress $adr -EmailAddressPolicyEnabled:$False 

    } 

}

## Verifying the Target PrimarySmtpAddress 
Function Verify-TargetInformation(){

    $data = Import-CSV .\users.csv 

    $filetime = (get-date -format yyyyMMddhhmm) 
    $filename = "verify-$filetime.csv" 
    $MasterList = @() 

    ## Verifying the PrimarySmtpAddress 
    Foreach($i in $data) 
    { 

        $MyObject = New-Object PSObject -Property @{ 

            Name = (Get-Mailbox -Identity $i.PrimarySmtpAddress).Name 
            PrimarySmtpAddress = (Get-Mailbox -Identity $i.PrimarySmtpAddress).PrimarySmtpAddress 
            Database = (Get-Mailbox -Identity $i.PrimarySmtpAddress).Database
            EmailAddresses = ((Get-Mailbox -Identity $i.PrimarySmtpAddress).EmailAddresses -Join ";") 
        } 

        $MasterList += $MyObject 

    } 

    $MasterList | Export-Csv $filename -NoTypeInformation -Encoding Unicode 
    Import-CSV $filename 

    Write-Host "" 
    Write-Host "SMTP Verification is saved into the CSV file: $filename" -ForegroundColor White 
    Write-Host "" 
}
Exchange 2013 script – automatic installation of prerequisites

Exchange 2013 script – automatic installation of prerequisites

I’ve updated a script that was intended for installing prerequisites for Exchange 2010 that were released by a couple of peoples (Anderson Patricio, Pat Richard and Bhargav Shukla). This script have now been updated and applies to Exchange 2013.

It will help you with installing all prerequisites (features) plus the FilterPack(s) and the Unified Communications Managed API. It also provides the option to disable the UAC (User Access Control) and the Windows Firewall.

You can download the script here
Feel free to use it as much as you want, I just want to mention I do not provide support for it and there are no warranty.

The script/code can be viewed below:

#############################################################################
 # Install-Exchange2013PreReqs.ps1
 # Configures the necessary prerequisites to install Exchange 2013 on a
 # Windows Server 2008 R2 server or Windows Server 2012 server
 #
 # Updated by: Jonas Andersson
 # Original written by: Pat Richard, Anderson Patricio and Bhargav Shukla
 #
 # Some info taken from
 # http://www.ucblogs.net/blogs/exchange/archive/2009/12/12/Automated-prerequisite-installation-via-PowerShell-for-Exchange-Server-2010-on-Windows-Server-2008-R2.aspx">http://www.ucblogs.net/blogs/exchange/archive/2009/12/12/Automated-prerequisite-installation-via-PowerShell-for-Exchange-Server-2010-on-Windows-Server-2008-R2.aspx
 # http://msmvps.com/blogs/andersonpatricio/archive/2009/11/13/installing-exchange-server-2010-pre-requisites-on-windows-server-2008-r2.aspx">http://msmvps.com/blogs/andersonpatricio/archive/2009/11/13/installing-exchange-server-2010-pre-requisites-on-windows-server-2008-r2.aspx
 # http://www.bhargavs.com/index.php/powershell/2009/11/script-to-install-exchange-2010-pre-requisites-for-windows-server-2008-r2/">http://www.bhargavs.com/index.php/powershell/2009/11/script-to-install-exchange-2010-pre-requisites-for-windows-server-2008-r2/
 #############################################################################

# Detect correct OS here and exit if no match
 if (-not((Get-WMIObject win32_OperatingSystem).OSArchitecture -eq '64-bit') -and (((Get-WMIObject win32_OperatingSystem).Version -eq "6.1.7601") -or (Get-WMIObject win32_OperatingSystem).Version -eq "6.2.9200")){
 Write-Host "This script requires a 64bit version of Windows Server 2008 R2 or Windows Server 2012, which this is not." -ForegroundColor Red -BackgroundColor Black
 Exit
 }

Function Disable-UAC(){

$path = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System"
 $a = Get-ItemProperty $path -Name EnableLUA

if ($a | Select-String "0")
 {
 Write-Host "UAC is already disabled" -ForegroundColor Green
 return
 }

if ($a | Select-String "1")
 {
 Write-Host "Enabled" -ForegroundColor Red
 Set-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System" -Name "EnableLUA" -Value 0
 Write-host "Registry key HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA has been changed." -ForegroundColor yellow
 Write-Host "UAC is now disabled" -ForegroundColor Green
 }

}

Function Disable-FW(){

$status = netsh advfirewall show allprofiles state

if ($status | Select-String "ON")
 {
 $enabled = $true
 }
 else
 {
 $enabled = $false
 }

if ($enabled -eq $true) {

netsh advfirewall set allprofiles state off
 Write-Host "Firewall is now disabled" -ForegroundColor yellow
 return
 }

if ($enabled -eq $false) {
 Write-Host "Firewall is already disabled" -ForegroundColor Green
 }

}

Function InstallFilterPack(){

if (Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\{95140000-2000-0409-1000-0000000FF1CE}" -ErrorAction SilentlyContinue) {

Write-host "FilterPack is already installed." -ForegroundColor yellow
 return
 }

else
 {

trap {
 Write-Host "Problem downloading FilterPackx64.exe. Please visit: <a href="http://www.microsoft.com/en-us/download/details.aspx?id=26604">http://www.microsoft.com/en-us/download/details.aspx?id=26604</a> and <a href="http://www.microsoft.com/en-us/download/details.aspx?id=17062&quot;">http://www.microsoft.com/en-us/download/details.aspx?id=17062"</a>

break
 }

#set a var for the folder you are looking for
 $folderPath = 'C:\Temp'

#Check if folder exists, if not, create it
 if (Test-Path $folderpath){
 Write-Host "The folder $folderPath exists."
 } else{
 Write-Host "The folder $folderPath does not exist, creating..." -NoNewline
 New-Item $folderpath -type directory | Out-Null
 Write-Host "done!" -ForegroundColor Green
 }

# Check if file exists, if not, download it
 $file1 = $folderPath+"\FilterPack64bit.exe"
 $file2 = $folderPath+"\filterpack2010sp1-kb2460041-x64-fullfile-en-us.exe"

if (Test-Path $file1){
 write-host "The file $file1 exists."
 } else {
 #Download Microsoft Filter Pack
 Write-Host "Downloading Microsoft Filter Pack..." -nonewline
 $clnt = New-Object System.Net.WebClient
 $url = "<a href="http://download.microsoft.com/download/0/A/2/0A28BBFA-CBFA-4C03-A739-30CCA5E21659/FilterPack64bit.exe&quot;">http://download.microsoft.com/download/0/A/2/0A28BBFA-CBFA-4C03-A739-30CCA5E21659/FilterPack64bit.exe"</a>
 $clnt.DownloadFile($url,$file1)
 Write-Host "done!" -ForegroundColor Green
 }

if (Test-Path $file2){
 write-host "The file $file2 exists."
 } else {
 #Download Microsoft Filter Pack SP1
 Write-Host "Downloading Microsoft Filter Pack SP1..." -nonewline
 $clnt = New-Object System.Net.WebClient
 $url = "<a href="http://download.microsoft.com/download/A/A/3/AA345161-18B8-45AE-8DC8-DA6387264CB9/filterpack2010sp1-kb2460041-x64-fullfile-en-us.exe&quot;">http://download.microsoft.com/download/A/A/3/AA345161-18B8-45AE-8DC8-DA6387264CB9/filterpack2010sp1-kb2460041-x64-fullfile-en-us.exe"</a>
 $clnt.DownloadFile($url,$file2)
 Write-Host "done!" -ForegroundColor Green
 }

#Install Microsoft Filter Packs
 Write-Host "Installing Microsoft Filter Packs..."

$args = "/quiet /norestart"
 $setup1 = (Start-Process $file1 -ArgumentList $args -Wait -PassThru).ExitCode
 if ($setup1 -eq 0) { write-host "Successfully installed $file1" -ForegroundColor Green }
 if ($setup1 -ne 0) { write-host "Failed!" -ForegroundColor Red }

$setup2 = (Start-Process $file2 -ArgumentList $args -Wait -PassThru).ExitCode
 if ($setup2 -eq 0) { write-host "Successfully installed $file2" -ForegroundColor Green }
 if ($setup2 -ne 0) { write-host "Failed!" -ForegroundColor Red }

}
 }

Function InstallUMAPI(){

#Change reg key below!
 if (Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\UCMA4" -ErrorAction SilentlyContinue) {

Write-host "Unified Communications Managed API 4.0 Runtime is already installed." -ForegroundColor yellow
 return
 }

else
 {

trap {
 Write-Host "Problem downloading UM API. Please visit: <a href="http://www.microsoft.com/en-us/download/details.aspx?id=34992&quot;">http://www.microsoft.com/en-us/download/details.aspx?id=34992"</a>

break
 }
 #set a var for the folder you are looking for
 $folderPath = 'C:\Temp'

#Check if folder exists, if not, create it
 if (Test-Path $folderpath){
 Write-Host "The folder $folderPath exists."
 } else{
 Write-Host "The folder $folderPath does not exist, creating..." -NoNewline
 New-Item $folderpath -type directory | Out-Null
 Write-Host "done!" -ForegroundColor Green
 }

# Check if file exists, if not, download it
 $file = $folderPath+"\UcmaRuntimeSetup.exe"
 if (Test-Path $file){
 write-host "The file $file exists."
 } else {

#Download Microsoft UM API
 Write-Host "Downloading Microsoft UM API..." -nonewline
 $clnt = New-Object System.Net.WebClient
 $url = "<a href="http://download.microsoft.com/download/2/C/4/2C47A5C1-A1F3-4843-B9FE-84C0032C61EC/UcmaRuntimeSetup.exe&quot;">http://download.microsoft.com/download/2/C/4/2C47A5C1-A1F3-4843-B9FE-84C0032C61EC/UcmaRuntimeSetup.exe"</a>
 $clnt.DownloadFile($url,$file)
 Write-Host "done!" -ForegroundColor Green
 }

#Check/Install Media Foundation feature
 $mf = Get-WindowsFeature "Server-Media-Foundation" | select *

Start-Sleep 2

if ($mf.Installed -eq $False)
 {
 Write-Host "Installing Media Foundation feature..."    -ForegroundColor Green
 Add-Windowsfeature Server-Media-Foundation

Write-Host ""
 Write-Host "Installing of Media Foundation feature completed." -ForegroundColor Green
 Write-Host ""
 Write-Host "Restart the server and restart the task" -ForegroundColor Red
 Write-Host "or else the UM API won't be installed" -ForegroundColor Red
 Write-Host ""

return

}

if ($mf.Installed -eq $True)
 {
 #Install Microsoft UM API
 Write-Host "Installing Microsoft UM API..." -ForegroundColor Green

$args = "/quiet /norestart"
 $setup = (Start-Process $file -ArgumentList $args -Wait -PassThru).ExitCode
 if ($setup -eq 0) { write-host "Successfully installed $file" -ForegroundColor Green }
 if ($setup -ne 0) { write-host "Failed!" -ForegroundColor Red }

}
 }

}

Import-Module ServerManager
 $opt = "None"
 # Do {
 clear
 if ($opt -ne "None") {write-host "Last command: "$opt -foregroundcolor Yellow}
 write-host
 write-host Exchange Server 2013 - Prerequisites script
 write-host Please, select which role you are going to install..
 write-host
 write-host '1) Client Access Server'
 write-host '2) Mailbox'
 write-host '3) Typical (CAS/Mailbox)'
 write-host
 write-host '10) Install Microsoft Filter Pack 2.0'
 write-host '    Required if installing Mailbox Server roles' -foregroundcolor yellow
 write-host '    Automatically set for options 2 and 3' -foregroundcolor yellow
 write-host '11) Install Microsoft UM API'
 write-host '    Required if installing Mailbox Server roles' -foregroundcolor yellow
 Write-Host '12) Disable UAC'
 Write-Host '13) Disable Firewall'
 write-host
 write-host '15) Restart the Server'
 write-host '16) End'
 write-host
 $opt = Read-Host "Select an option.. [1-14]? "

switch ($opt)    {
 1 {

# Windows Server 2008 R2 SP1
 if ((Get-WMIObject win32_OperatingSystem).Version -eq "6.1.7601") {

Import-Module ServerManager
 Add-WindowsFeature "Desktop-Experience", "NET-Framework", "NET-HTTP-Activation", "RPC-over-HTTP-proxy", "RSAT-Clustering", "RSAT-Web-Server", "WAS-Process-Model", "Web-Asp-Net", "Web-Basic-Auth", "Web-Client-Auth", "Web-Digest-Auth", "Web-Dir-Browsing", "Web-Dyn-Compression", "Web-Http-Errors", "Web-Http-Logging", "Web-Http-Redirect", "Web-Http-Tracing", "Web-ISAPI-Ext", "Web-ISAPI-Filter", "Web-Lgcy-Mgmt-Console", "Web-Metabase", "Web-Mgmt-Console", "Web-Mgmt-Service", "Web-Net-Ext", "Web-Request-Monitor", "Web-Server", "Web-Stat-Compression", "Web-Static-Content", "Web-Windows-Auth", "Web-WMI" -restart

}

# Windows Server 2012
 if ((Get-WMIObject win32_OperatingSystem).Version -eq "6.2.9200") {

Install-WindowsFeature "AS-HTTP-Activation", "Desktop-Experience", "NET-Framework-45-Features", "RPC-over-HTTP-proxy", "RSAT-Clustering", "RSAT-Clustering-CmdInterface", "RSAT-Clustering-Mgmt", "RSAT-Clustering-PowerShell", "Web-Mgmt-Console", "WAS-Process-Model", "Web-Asp-Net45", "Web-Basic-Auth", "Web-Client-Auth", "Web-Digest-Auth", "Web-Dir-Browsing", "Web-Dyn-Compression", "Web-Http-Errors", "Web-Http-Logging", "Web-Http-Redirect", "Web-Http-Tracing", "Web-ISAPI-Ext", "Web-ISAPI-Filter", "Web-Lgcy-Mgmt-Console", "Web-Metabase", "Web-Mgmt-Console", "Web-Mgmt-Service", "Web-Net-Ext45", "Web-Request-Monitor", "Web-Server", "Web-Stat-Compression", "Web-Static-Content", "Web-Windows-Auth", "Web-WMI", "Windows-Identity-Foundation" -restart

}

}

2 {

# Windows Server 2008 R2 SP1
 if ((Get-WMIObject win32_OperatingSystem).Version -eq "6.1.7601") {

Import-Module ServerManager
 InstallFilterPack
 Add-WindowsFeature "Desktop-Experience", "NET-Framework", "NET-HTTP-Activation", "RPC-over-HTTP-proxy", "RSAT-Clustering", "RSAT-Web-Server", "WAS-Process-Model", "Web-Asp-Net", "Web-Basic-Auth", "Web-Client-Auth", "Web-Digest-Auth", "Web-Dir-Browsing", "Web-Dyn-Compression", "Web-Http-Errors", "Web-Http-Logging", "Web-Http-Redirect", "Web-Http-Tracing", "Web-ISAPI-Ext", "Web-ISAPI-Filter", "Web-Lgcy-Mgmt-Console", "Web-Metabase", "Web-Mgmt-Console", "Web-Mgmt-Service", "Web-Net-Ext", "Web-Request-Monitor", "Web-Server", "Web-Stat-Compression", "Web-Static-Content", "Web-Windows-Auth", "Web-WMI" -restart

}

# Windows Server 2012
 if ((Get-WMIObject win32_OperatingSystem).Version -eq "6.2.9200") {

InstallFilterPack
 Install-WindowsFeature "AS-HTTP-Activation", "Desktop-Experience", "NET-Framework-45-Features", "RPC-over-HTTP-proxy", "RSAT-Clustering", "RSAT-Clustering-CmdInterface", "RSAT-Clustering-Mgmt", "RSAT-Clustering-PowerShell", "Web-Mgmt-Console", "WAS-Process-Model", "Web-Asp-Net45", "Web-Basic-Auth", "Web-Client-Auth", "Web-Digest-Auth", "Web-Dir-Browsing", "Web-Dyn-Compression", "Web-Http-Errors", "Web-Http-Logging", "Web-Http-Redirect", "Web-Http-Tracing", "Web-ISAPI-Ext", "Web-ISAPI-Filter", "Web-Lgcy-Mgmt-Console", "Web-Metabase", "Web-Mgmt-Console", "Web-Mgmt-Service", "Web-Net-Ext45", "Web-Request-Monitor", "Web-Server", "Web-Stat-Compression", "Web-Static-Content", "Web-Windows-Auth", "Web-WMI", "Windows-Identity-Foundation" -restart

}

}

3 {

if ((Get-WMIObject win32_OperatingSystem).Version -eq "6.1.7601") {

Import-Module ServerManager
 InstallFilterPack
 Add-WindowsFeature "Desktop-Experience", "NET-Framework", "NET-HTTP-Activation", "RPC-over-HTTP-proxy", "RSAT-Clustering", "RSAT-Web-Server", "WAS-Process-Model", "Web-Asp-Net", "Web-Basic-Auth", "Web-Client-Auth", "Web-Digest-Auth", "Web-Dir-Browsing", "Web-Dyn-Compression", "Web-Http-Errors", "Web-Http-Logging", "Web-Http-Redirect", "Web-Http-Tracing", "Web-ISAPI-Ext", "Web-ISAPI-Filter", "Web-Lgcy-Mgmt-Console", "Web-Metabase", "Web-Mgmt-Console", "Web-Mgmt-Service", "Web-Net-Ext", "Web-Request-Monitor", "Web-Server", "Web-Stat-Compression", "Web-Static-Content", "Web-Windows-Auth", "Web-WMI" -restart

}

# Windows Server 2012
 if ((Get-WMIObject win32_OperatingSystem).Version -eq "6.2.9200") {

InstallFilterPack
 Install-WindowsFeature "AS-HTTP-Activation", "Desktop-Experience", "NET-Framework-45-Features", "RPC-over-HTTP-proxy", "RSAT-Clustering", "RSAT-Clustering-CmdInterface", "RSAT-Clustering-Mgmt", "RSAT-Clustering-PowerShell", "Web-Mgmt-Console", "WAS-Process-Model", "Web-Asp-Net45", "Web-Basic-Auth", "Web-Client-Auth", "Web-Digest-Auth", "Web-Dir-Browsing", "Web-Dyn-Compression", "Web-Http-Errors", "Web-Http-Logging", "Web-Http-Redirect", "Web-Http-Tracing", "Web-ISAPI-Ext", "Web-ISAPI-Filter", "Web-Lgcy-Mgmt-Console", "Web-Metabase", "Web-Mgmt-Console", "Web-Mgmt-Service", "Web-Net-Ext45", "Web-Request-Monitor", "Web-Server", "Web-Stat-Compression", "Web-Static-Content", "Web-Windows-Auth", "Web-WMI", "Windows-Identity-Foundation" -restart

}

}
 10 {
 # future - auto detect Internet access
 write-host 'Can this server access the Internet?'
 $filtpack = read-host 'Please type (Y)es or (N)o...'
 switch ($filtpack)                {
 Y { InstallFilterPack }
 N {Write-warning 'Please download and install Microsoft Filter Pack from here: <a href="http://www.microsoft.com/en-us/download/details.aspx?id=26604">http://www.microsoft.com/en-us/download/details.aspx?id=26604</a> and <a href="http://www.microsoft.com/en-us/download/details.aspx?id=17062'}">http://www.microsoft.com/en-us/download/details.aspx?id=17062'}</a>
 }
 }
 11 {
 # future - auto detect Internet access
 write-host 'Can this server access the Internet?'
 $umapi = read-host 'Please type (Y)es or (N)o...'
 switch ($umapi)                {
 Y { InstallUMAPI }
 N {Write-warning 'Please download and install Microsoft UM API from here: <a href="http://www.microsoft.com/en-us/download/details.aspx?id=34992'}">http://www.microsoft.com/en-us/download/details.aspx?id=34992'}</a>
 }
 }
 12 { Disable-UAC }
 13 { Disable-FW }
 15 { Restart-Computer }
 16 {
 Write-Host "Exiting..."
 Exit
 }
 default {write-host "You haven't selected any of the available options. "}
 }
Author of a book – PowerShell cookbook

Author of a book – PowerShell cookbook

If you have missed the news on my twitter, I can tell you that the last 6 months I’ve been busy with writing a book called “Microsoft Exchange 2013 PowerShell Cookbook: second edition” for Packt Publishing.

That’s also why the blog not have been updated that much lately, now it’s time to startup with the activities for the online community work again since the book more or less is completed. Just doing the final updates of the chapters. I want to thank both Anderson Patricio [MVP] and Marcelo Vighi [MVP] for doing a great job with the review.
I also want to send a special thank you to Magnus Björk [MVP] for helping me out when bugs were found.

It have been a great experience doing this project, both exciting and exhausting in the same time because of high tempo and tight time schedules. But I can recommend everyone that thinking of doing this kind of job, DO IT!

You might wonder when it will be released? mid June..

9427EN_MockupCover_Cookbook

More info about the book can be found here:
http://www.packtpub.com/microsoft-exchange-server-2013-powershell-2e-cookbook/book
http://www.amazon.com/Microsoft-Exchange-PowerShell-Cookbook-ebook/dp/B00BP47WHE/ref=sr_1_1?s=digital-text&ie=UTF8&qid=1364252267&sr=1-1

And some information about me:
http://www.packtpub.com/authors/profiles/jonas-andersson

How to set “office” value for multiple Shared Mailboxes

How to set “office” value for multiple Shared Mailboxes

Published: 2013-02-25
Updated: –
Version: 1.0

This script was developed because there was a need to configure every Shared Mailbox with a office value. In Exchange the value is called “Office” while in Active Directory this value is called “physicalDeliveryOfficeName”.

The script is retrieving all shared mailboxes where the office value isn’t populated and creates an array of these mailboxes. It includes a couple of attributes.

It does give you the opportunity to verify the changes that will be done, before they are done.
The array is showed to the screen and also saved as a CSV file called “pre-report-$timestamp.csv”

From each of the shared mailboxes, the script will bring the office value from the corresponding manager and put that value into respective shared mailbox office attribute value.

If there are no manager configured for any of the shared mailboxes, a log file will be created called “no-manager-configured-report.txt” and if there are no office attribute value configured on the managers, a log file will be created called “no-office-configured-report.txt”

When the script is completed, a log file will be created called “completed-report-$timestamp.txt” with the changes that have been done.

####################################################################
# SetOffice.ps1
# Description:
# This PowerShell script will stamp the office field for every shared mailbox
# that doesn't have a value set. The value will be collected from each manager
# If no Manager is set, the script will not stamp the office value
#
# Jonas Andersson, MCC 2011 and 2012
# http://www.testlabs.se/blog
# Twitter @jonand82
####################################################################</pre>
Write-Host "Starting script.." -ForegroundColor White -BackgroundColor Black

$ou = "target.local/Resource Mailboxes"

Write-Host 'Retrieving all Shared Mailboxes without "Office" value..' -ForegroundColor White -BackgroundColor Black

$UserList = Get-User -ResultSize unlimited -OrganizationalUnit $ou -RecipientTypeDetails SharedMailbox -Filter {Office -eq $null}

$MasterList = @()
 foreach ($User in $UserList)
 {
 $MyObject = New-Object PSObject -Property @{

Mailbox = (Get-User -Identity $User).DistinguishedName
 Manager = ((Get-User -Identity $User).Manager).DistinguishedName
 Manage = (Get-User -Identity $User).Manager | ForEach-Object{
 $o = (Get-User $_).Office
 }

Office = $o
 }

$MasterList += $MyObject
 }

if ((Read-Host 'Show and save list, the listed shared mailboxes? (Y/N)') -eq 'Y' )
 {
 $MasterList | Select Mailbox,Manager,Office

$timestamp = Get-Date -UFormat %Y%m%d-%H%M
 $reportfile = ".\pre-report-$timestamp.csv"
 $MasterList | Select Mailbox,Manager,Office | Export-CSV $reportfile -Encoding Unicode -Notype

Write-Host 'The file is saved as '$reportfile''
 }

if ((Read-Host 'Start the configuration? (Y/N)') -eq 'Y')
 {
 Write-Host 'Starting the script..' -ForegroundColor White -BackgroundColor Black
 Foreach ($item in $MasterList)
 {

if (($item.Manager -eq $null) -or ($item.Manager -eq ""))
 {
 Write-Host 'Item '$item.Mailbox' doesnt have a Manager configured!' -ForegroundColor Red -BackgroundColor Black
 $reportfile = "no-manager-configured-report.txt"
 $empty = $item.Mailbox,$item.Manager,$item.Office
 $empty | Out-File -FilePath $reportfile -Append

}

if (($item.Office -eq $null) -or ($item.Office -eq ""))
 {
 Write-Host 'Item '$item.Manager' doesnt have a Office value configured!' -ForegroundColor Red -BackgroundColor Black
 $reportfile = "no-office-configured-report.txt"
 $empty = $item.Mailbox,$item.Manager,$item.Office
 $empty | Out-File -FilePath $reportfile -Append

}

else
 {
 Write-Host 'Configuring the value for item'$item.Mailbox'to'$item.Office'' -ForegroundColor White -BackgroundColor Black -
 Set-Mailbox -Identity $item.Mailbox -Office $item.Office

$timestamp = Get-Date -UFormat %Y%m%d-%H%M
 $reportfile = "completed-report-$timestamp.txt"
 $list = $item.Mailbox,$item.Manager,$item.Office
 $list | Out-File -FilePath $reportfile -Append

}
 }

}

else{
 exit
 }
 

You can use this script for free, just make sure to test it in a lab environment before, I take no responsibility for any actions and I can’t give any support for it.
Feel free to use the script, edit it, publish it. If you do, please make sure to link back to the blog post url.

Download script

Regards,
Jonas

Exchange Server 2013 Preview – Part 3: How to configure site URL’s, Databases and Outlook Anywhere

Exchange Server 2013 Preview – Part 3: How to configure site URL’s, Databases and Outlook Anywhere

I suppose you already have, but if you haven’t read my previous parts in this Exchange 2013 serie, have a look at the links below.

Part 1: Complete guide of how to perform the installation
Part 2: How to do the Basic configuration

This part will include details on how the configuration could be made for Site URL’s/Virtual Directories, Databases, Outlook Anywhere and MAPI vs RPC over HTTPs together with connecting using Outlook 2013.

In the previous part we did install the certificate which included the following names, so we can use these names in the site configuration. (If using HTTPS, the configured name needs to be included into the certificate.)

  • mail.testlabs.se
  • autodiscover.testlabs.se
  • tlcas01
  • tlcas01.testlabs.se
Sites / URL’s

Let’s go through the steps for configuring the sites with the ExternalURL and other settings.
I’ll go through both the EAC and the PowerShell, so you have the opportunity to select which method you prefer.

Let’s start..

In EAC: Go to Servers, select Virtual Directories.

image

Select the server in the menu and which type you want to show. Then press Edit.

image

Let’s start with Autodiscover.

image

By default, Integrated Windows Authentication and Basic authentication is enabled. Press Save.

image

Next, select Exchange ActiveSync (EAS). Press Edit.

image

General settings shows the URL’s, I did type in the ExternalURL like the pic below. Press Authentication.

image

Make sure that Basic authentication is enabled. Press Save.

image

Next, select ECP. Press Edit.

image

General settings shows the URL’s, I did type in the ExternalURL like the pic below. Press Authentication.

image

Authentication default settings is “Use forms-based authentication” enabled. Press Save.

image

A warning, make sure to change all virtual directions. Press OK.

image

Next, select EWS. Press Edit.

image

General settings shows the URL’s, I did type in the ExternalURL like the pic below. Press Authentication.

image

Authentication settings, Integrated Windows authentication is enabled by default. Press Save.

image

Next, select OAB. Press Edit.

image

I did type in the ExternalURL in this setting, the InternalURL was already configured. I did also change the Polling interval from 480 minutes to 60. For having a faster update of the OAB. Press Save.

image

Next, select OWA. Press Edit.

image

General settings shows the URL’s, I did type in the ExternalURL like the pic below. Press Authentication.

image

Forms-based authentication is selected, I did select the Logon format: User name only and did select my domain by the browsing button. Press Features.

image

Showing the default settings. Press File Access.

image

Showing the default settings. Press Save.

image

Next, select PowerShell. Press Edit.

image

General settings shows the URL’s, I did type in the ExternalURL like the pic below. Press Authentication.

image

Both Integrated Windows authentication and Basic authentication was selected by default. Press Save.

image

Using PowerShell

Start the Exchange Management Shell (EMS) and the following commands will do the same work that’s done in EAC.

Autodiscover:
Get-ClientAccessServer | fl *uri*
Set-ClientAccessServer –Identity TLCAS01 –AutoDiscoverServiceInternalUri https://autodiscover.testlabs.se/Autodiscover/autodiscover.xml

image

Exchange ActiveSync (EAS):
Get-ActiveSyncVirtualDirectory | fl *url*, ide*
Set-ActiveSyncVirtualDirectory –Identity “TLCAS01\Microsoft-Server-ActiveSync (Default Web Site)” –ExternalUrl https://mail.testlabs.se/Microsoft-Server-ActiveSync
image

Exchange Control Panel (ECP):
Get-EcpVirtualDirectory | fl *url*, ide*
Set-EcpVirtualDirectory –Identity “TLCAS01\ecp (Default Web Site)” –ExternalUrl https://mail.testlabs.se/ecp

image

Exchange Web Services (EWS):
Get-WebServicesVirtualDirectory | fl *url*, ide*
Set-WebServicesVirtualDirectory –Identity “TLCAS01\EWS (Default Web Site)” –ExternalUrl https://mail.testlabs.se/EWS/Exchange.asmx

image

Offline Address Book (OAB):
Get-OabVirtualDirectory | fl *url*, ide*,pol*
Set-OabVirtualDirectory –Identity “TLCAS01\OAB (Default Web Site)” –ExternalUrl https://mail.testlabs.se/OAB –PollInterval 60

image

Outlook Web App (OWA):
Get-OwaVirtualDirectory | fl *url*, ide*
Set-OwaVirtualDirectory –Identity “TLCAS01\OWA (Default Web Site)” –ExternalUrl https://mail.testlabs.se/OWA

image

PowerShell:
Get-PowerShellVirtualDirectory | fl *url*, ide*
Set-PowerShellVirtualDirectory –Identity “TLCAS01\PowerShell (Default Web Site)” –ExternalUrl https://mail.testlabs.se/powershell

image

Databases

Let’s go through the steps that’s required for renaming the default database, dismount and mount. Also creating new databases. Let’s start with the EAC and then do it in PowerShell.

Let’s start..

In EAC: Go to Servers, select Databases.

Select the default database, named “Mailbox Database 0883045..”. Press Edit.

image

General settings is shown. Press Cancel.

image

Select the database, Dismount it by pressing the … icon and press Dismount database.

image

It does show a warning, that mailboxes being on this database now will be unavailable. Press Yes.

image

Select the database. Press Edit.

image

Give the database a friendly name, example: DB01. Press Maintenance.

image

Maintenance settings is shown. Press Limits.

image

Mailbox limits are shown, these are the default values. Press Client Settings.

image

By default, no Offline address book was selected. Press Browse and make sure to select the address book. Press Save.

image

What about if you want to create a new database?

Let’s start in EAC

Press the Add button (+).

image

Give the database a friendly name, example: DB02. Browse for a mailbox server. And also put in the database path and log path. Press Save.

image

During the creating of the database, there is not option for associate the database with the offline address book. When the database is created, press Edit. Then go to Client Settings and select the Offline address book.

image

Using PowerShell

Start the Exchange Management Shell (EMS) and the following commands will do the same work that’s done in EAC.

Retrieve database information
Get-MailboxDatabase
Get-MailboxDatabase | fl name,*path*

Dismount Database
Dismount-Database –Identity DB01

After the default database is renamed to DB01, I want to move the database file and the logs to another drive. It’s done by the commands below:

Move-DatbasePath –identity DB01 –EdbFilePath “E:\Database\DB01\DB01.edb” –LogFolderPath “F:\Logs\DB01”

Mount-Database DB01

image

Get-OfflineAddressBook

For creating a new database (DB02), we have the opportunity in PowerShell to specify all parameters that’s needed for having all options configured.

New-MailboxDatabase -Name DB02 -EdbFilePath “E:\Database\DB02\DB02.edb” -LogFolderPath “F:\Logs
\DB02” -OfflineAddressBook “\Default Offline Address Book” -Server TLMB01

Mount-Database DB02

image

Note that the OfflineAddressBook is specified during the creation of the database.

Outlook Anywhere

Configuration of the feature Outlook Anywhere can also be done from both the EAC and EMS, in various ways.

Let’s start with the EAC:

Go to the servers menu, and select Servers. Press Edit.

image

Then go to the “Outlook Anywhere” option, type in the external name, example: mail.testlabs.se.
I’m using Basic authentication for Outlook Anywhere. Press Save.

image

And the Configuration is completed.

Using PowerShell

Start the Exchange Management Shell (EMS) and the following commands will do the same work that’s done in EAC.

Enable Outlook Anywhere:
Enable-OutlookAnywhere –Server TLCAS01 –ExternalHostname mail.testlabs.se –InternalHostname tlcas01.testlabs.se –ExternalClientAuthenticationMethod Basic –InternalClientAuthenticationMethod Ntlm –IISAuthentication Ntlm –SSLOffloading:$false

Get-OutlookAnywhere –Server TLCAS01

image

MAPI and RPC

The MAPI/RPC (RPC over TCP) traffic is now gone and  replaced with RPC over HTTP/s instead. With that said no more load balancing of static RPC ports, as far as I know this will make both the Firewall team and the Load Balancer teams work easier, less ports is used together with the requirement of load balancing affinity/sticky session settings is not required anymore. This because of there is no need anymore to have the affinity settings, it can now be load balanced based on IP addresses. Just make sure that the load balancer verifies the Exchange services before sending traffic to it.

Outlook instead will use port 443 (HTTPS) or port 80 (HTTP). I think (and hope) most of you will use RPC over HTTPS, with this said I’ll show you the new Outlook 2013 Preview/beta and how it connects and also the traffic it’s using.

Outlook 2013 Preview, connects to my mailbox in Exchange 2013. It’s using HTTPS to initiate the connection, using port 6001 by default for it’s connection, using RPC over HTTPS.

image

A small picture from Network Monitor when the connection initiated by Outlook 2013.

image

More information around What’s new in Exchange 2013 can be found here.

Next parts will cover Public Folders, Client Access Server Array, Database Availability Groups and more.
Next part can be found here.

Thanks for reading, I hope it helped you guys/girls out there.
If you want me to cover anything special around Exchange 2013, leave a comment.

Exchange Server 2013 Preview – Part 2: How to do the Basic configuration

Exchange Server 2013 Preview – Part 2: How to do the Basic configuration

If you haven’t read it already, I did post a complete guide for installing Exchange 2013, it can be found here. That was part 1, now it’s time for part 2. Which of course is the configuration of the server setup.

We have lots of changes between how you configured Exchange 2007/2010 and 2013.
First thing is that Exchange Management Console is gone and replaced by a refreshed ECP called Exchange Admin Center (EAC), built on Silverlight (I suppose). The “old” Exchange Management Shell (EMS) is still there, so I suppose lots of us geeks will use more PowerShell in the near future.

The fact that EMC is replaced will make the administration easier and more portable, but I still like the EMC better. I will like the EAC better after used it for a while. This portable administration together with Remote PowerShell will be awesome.

I will use both methods for the configuration steps, both EAC and PowerShell.

The easiest way to find the URL path to the EAC is to start the Exchange Management Shell and run the command below:

Get-EcpVirtualDirectory | fl *url*

The picture below is my output from my lab environment

image

So let’s get things started..

Start up an Internet browser and go to the URL output from the command above

image

Mail Flow

Let’s get the mail flow configured first so we can receive mails from external senders.

In EAC: on the left side (menu) press “Mail Flow”.

image

Accepted Domains

Ensure sure that your domains that should be used for SMTP is listed in here for making Exchange able to receive mails for these domains. More info about Accepted Domains can be found here.

In EAC: After selecting “Mail Flow” to the left, press “Accepted Domains” at the top menu in the middle.

image

If your domain is not listed and you need to add it, press the plus mark and fill in the information, like my example below.

image

image

Using PowerShell: Since I’m a geek I like to use PowerShell because it gives you the advantage of see what happens, have the full control and easily build scripts.

For listing and adding a domain like above in PowerShell you should write:

Get-AcceptedDomain
New-AcceptedDomain –Name testlabs.com –DomainName testlabs.com –DomainType Authoritative

image

Email Address Policies

These policies are used to stamp each user mailbox object with an email address/SMTP address.
These policies does not remove any addresses used previously, it just adds new addresses to mail objects.

In EAC: By default after the installation we only have one policy, called Default Policy.

I want to edit this one, by selecting the “Default Policy” and pressing the “pen” icon.

image

The Default Policy is showing up, in the left menu, press “Email Address Format”.

image

Since I live in Sweden and we have some special characters that I want to get rid of, I’m using the custom policy, Address type: SMTP and the Email address parameters:

%råa%räa%röo%g.%råa%räa%röo%s@testlabs.se

%r means it replaces the character after, in this case åäö. Which it replaces with aao.

When you have done the change press the “Save” button at the bottom of the page.

image

Check so that the change is correct, then press the “Save” button.

image

After the changes have been saved, it needs to be applied. This is done by pressing the “Apply” text/button down in the right menu.

image

image

Using PowerShell: Let’s start with listing the Policy and the settings in it. As a final step let’s do the same configuration to the “Default Policy” that we did using EAC.

If you want to create more than just alias@domain.com to your policies, then this is done by comma separation. For setting the Primary SMTP address, use capital letters for SMTP, and for additional addresses use small letters for smtp. See the example below:

Get-EmailAddressPolicy

Get-EmailAddressPolicy | fl

Get-EmailAddressPolicy | Set-EmailAddressPolicy –EnabledEmailAddressTemplates “SMTP: %råa%räa%röo%g.%råa%räa%röo%s@testlabs.se”,”smtp: %m@testlabs.se”

Set-EmailAddressPolicy –identity “Default Policy” –EnabledEmailAddressTemplates “SMTP: %råa%räa%röo%g.%råa%räa%röo%s@testlabs.se”,”smtp: %m@testlabs.se”

Get-EmailAddressPolicy | Update-EmailAddressPolicy

It can easily be checked if the policy has been applied, it will show a True or False value. For checking the value run the command below:

Get-EmailAddressPolicy | fl *appl*

Note: Don’t forget to update the Policy, or else the new addresses won’t be pushed out to the recipients.

image

Receive Connectors

Since the HUB Transport server role now is gone and the HUB role is placed together with the CAS role, this is the server you should be looking at.

After the SMTP domains have been added into the Accepted Domain tab, some settings could be of value to have a look at before starting to use the servers.

A change has been made to the new version, the default connector now named “Default Frontend servername”. It now allows traffic from Anonymous users by default. I suppose this is due to that the Edge Transport Role also is removed.

In EAC: Go to the “Receive Connectors”, found under “Mail Flow”. Make sure to select your CAS server(s) and the “Default Frontend servername”. Then press the “pen” icon for Edit the selected connector.

image

The only thing I did change was the “Maximum receive message size” to 30 MB.
When you have done your changes for the connector, press the Save button.

image

Using PowerShell: Start the Exchange Management Shell, lets view the receive connectors and then make the changes like above.

Get-ReceiveConnector

Get-ReceiveConnector | fl

Set-ReceiveConnector –Identity “TLCAS01\Default Frontend TLCAS01” –MaxMessageSize 30MB

Note: The size can be configured between 64KB up to 2GB.

Verify that the settings was correctly set, using the command below
Get-ReceiveConnector | fl ide*,maxmes*

image


Send Connectors

When the HUB server role now is gone and after the default installation of Exchange we don’t have any send connectors. So… for being able to send out mails to external recipients, let’s create a Send Connector on the CAS server.

In EAC: Go to the “Send Connectors”, found under “Mail Flow”. Press the “plus” icon for Creating a new send connector.

image

Give the send connector a friendly name and select what type it should be. Since this one I’m creating now is for sending to external recipients I’m selecting “Internet”. (Seems like we have a typo, see picture below). Press Next.

image

Select how to route those mails, either by using MX records or through a smart host(s). If you have a mail gateway then you should select smart host and type in it’s IP address. My server is just sending them directly to Internet so I’m using the MX method. Then press Next.

image

Press the “plus” icon for adding the address space this connector should use. In my case it will be “*”. Then it takes care of all domains. Press Save.

image

Then Press Next for accepting the settings you’ve just made.

Next screen will show you which source servers that should be used. Let’s add these into the connector by pressing the “plus” icon and selecting the Mailbox servers.

image

Press Finish button so the connector get’s created.

Note: By default the connector has a maximum message size of 10MB. You can’t configure the maximum send message size when creating the connector, but this can be done by editing the created connector.

Using PowerShell: Start the Exchange Management Shell, lets view the send connectors and then make the changes like above.

Get-SendConnector

Get-SendConnector| fl

This creates a new send connector using the DNS/MX method
New-SendConnector –Name “Outbound” –AddressSpaces ‘*’ –SourceTransportServers TLMB01 –MaxMessageSize 30MB

This creates a new send connector using the smarthost method

New-SendConnector –Name “Outbound” –AddressSpaces ‘*’ –SourceTransportServers TLMB01 –MaxMessageSize 30MB –DNSRoutingEnabled:$false –SmartHosts “10.10.10.10”

This creates a new send connector using the smarthost method together with using the CAS server as a proxy server for sending the mails

New-SendConnector –Name “Outbound” –AddressSpaces ‘*’ –SourceTransportServers TLMB01 –MaxMessageSize 30MB –DNSRoutingEnabled:$false –SmartHosts “10.10.10.10” –FrontEndProxyEnabled:$True

Note: The size can be configured between 0 Bytes up to 2TB.

Verify that the settings was correctly set, using the command below
Get-SendConnector| fl ide*,maxmes*

image

Certificates

As most of you already know we need to request and import a certificate for Exchange. This for having a fully working OWA, ActiveSync etc. certificates needs to be configured so let’s get started.

In EAC: Go to the “Certificates”, found under “Servers”. Select the server and press the “plus” icon for Creating a new certificate request.

image

I’m using an Internal PKI solution, so in this case I want to “Create a request for a certificate from a certificate authority”. Press Next.

image

Type in a friendly name for the certificate. Press Next.

image

If you want to create the request for a wildcard certificate, this is the checkbox you should use.
I don’t want a wildcard certificate, so I just let it be unchecked. Press Next.

image

Press Browse and select which server you want to store it on. Press Next.

image

For each service you can here type in the address, and the request will generate the names in the end. When you’re done press Next.

image

Go through the names in the list and make sure that all names that’s needed are included. Press Next.

image

Fill in Organization name, Department, Country, City and State. Press Next.

image

In my example I did type in the path to a share on my domain controller, which also is my Internal CA. Press Finish.
Example: \\tldc01\certificates\certreq.req

image

When the request is completed, it shows up with the friendly name, together with the status “Pending request”. When the certificate is issued, press the “Complete” button below the status.

image

Type in the URL path to the .cer file, my file is saved on my DC. Press OK.
Example: \\tldc01\certificates\certnew.cer

image

It’s now time for assigning the services to the certificates. This is done by selecting the certificate and press the Edit button.

image

Go to “Services” and add the one’s that should be used. Press Save.

image

Press OK.

image

Check so that the services is assigned to the certificate.

image

Using PowerShell: Start the Exchange Management Shell, lets view the existing certificates and then make a new cert request like above. Finally import the issued certificate.

Get-ExchangeCertificate

Get-ExchangeCertificate | fl

This creates a new certificate request and saves it to a share
New-ExchangeCertificate –Server TLCAS01 –GenerateRequest –FriendlyName Exchange2013-PS –PrivateKeyExportable $true –SubjectName “c=SE, s=Skane, l=Malmo, o=Testlabs, ou=Testlabs, cn=mail.testlabs.se” –DomainName  mail.testlabs.se,autodiscover.testlabs.se –RequestFile “\\tldc01\certificates\test.req”

image

Import-ExchangeCertificate –Server TLCAS01 –FileName “\\tldc01\certificates\certnew-ps.cer” –PrivateKeyExportable $true –FriendlyName Exchange2013-PS

Enable-ExchangeCertificate –Thumbprint A2E6649A22A99BEAB2654BEB403C92BB9D34B404 –Services “IIS, SMTP, POP, IMAP” –Server TLCAS01

Get-ExchangeCertificate

image

Note: Make sure to specify –Server, or else you can have difficulties finding our created request. Mine landed at my Mailbox server even if I did it on the CAS server.

If you haven’t read it already, have a look at Part 1: Complete guide of how to perform the installation

Thanks for reading, I hope that it’s informative and great reading for most of you. It would be awesome if you guys leave some comments, what do you think about Exchange 2013? Maybe you have already installed the Preview/Beta? Which new feature is the best one?

Next part will cover Databases, Outlook Anywhere, Outlook 2013 and MAPI/RPC etc.

Part 3 can be found here

Load More