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/

Surface Hub – account creation

Background

Most of you already know what a Surface Hub is since Microsoft have pushed really hard for these devices. If you for some unknown reason doesn’t know what it is, or how it looks like. Then take a look at the following link: https://www.microsoft.com/microsoft-surface-hub/en-us

As you may know (or don’t, doesn’t matter..) I’m responsible to the technical solution of Office 365 and being a bit more specific; Skype for Business is the main one for me.

However, it took me a while to actually figure out what kind of accounts that was needed for the Surface Hub device to be honest. You can read about this at TechNet of course but they are just talking about device account (and what the heck is that? computer or user?)..

So what that said I wanted to share the knowledge I got so far from creation of the “device” accounts, which is a ROOM MAILBOX and nothing else (a customized room mailbox).

So to the steps that was taken:

Step 1:

  • Create one CSV file including the accounts we want to get created

In general the CSV file looks similar to the formatting of the text below

alias;upn;name;password
edu.surfacehub_55;edu.surfacehub_55@testlabstrial.onmicrosoft.com;Surface Hub 55;Welcome2016!!
edu.surfacehub_84;edu.surfacehub_84@testlabstrial.onmicrosoft.com;Surface Hub 84;Welcome2016!!

Note: an example of the CSV file can be found below:

Step 2:

For automating the creation of the listed accounts in the file, we can easily utilize PowerShell

Start:


$accounts = Import-Csv ".\surfacehubacct.csv" -Delimiter ";"

# Prereq's
$countrycode = (Get-CsTenant).CountryAbbreviation
$regpool = (Get-CsTenant).TenantPoolExtension
$regpool = $regpool.Substring($regpool[0].IndexOf(':') + 1)
$skuid = (Get-MsolAccountSku | Where-Object {$_.AccountSkuID.Contains("ENTERPRISEPACK"); })
$easpolicys = Get-MobileDeviceMailboxPolicy

if ($easpolicys.Count -gt 1)
{
foreach ($easpolicy in $easpolicys)
{
if (($easpolicy.PasswordEnabled -eq $False) -and ($easpolicy.AllowNonProvisionableDevices -eq $null -or $easpolicy.AllowNonProvisionableDevices -eq $True))
{
$easpolicy = $easpolicy
}

else
{
Write-Host "The policy is incompatible with the surface hub." -ForegroundColor Red
$easpolicy = $null
New-MobileDeviceMailboxPolicy -Name "SurfaceHubs" -PasswordEnabled $False -AllowNonProvisionableDevices $True
Write-Host "A new Mobile Device Mailbox Policy has been created" -ForegroundColor Green
$easpolicy = Get-MobileDeviceMailboxPolicy
}
}
}

if ($easpolicys.Count -eq $null)
{
if (($easpolicys.PasswordEnabled -eq $False) -and ($easpolicys.AllowNonProvisionableDevices -eq $null -or $easpolicys.AllowNonProvisionableDevices -eq $True))
{
$easpolicy = $easpolicys
}

else
{
Write-Host "The policy is incompatible with the surface hub." -ForegroundColor Red
$easpolicy = $null
New-MobileDeviceMailboxPolicy -Name "SurfaceHubs" -PasswordEnabled $False -AllowNonProvisionableDevices $True
Write-Host "A new Mobile Device Mailbox Policy has been created" -ForegroundColor Green
$easpolicy = "SurfaceHubs"
}
}

if (!$easpolicys)
{
Write-Host "No policy can be found." -ForegroundColor Red
$easpolicy = $null
New-MobileDeviceMailboxPolicy -Name "SurfaceHubs" -PasswordEnabled $False -AllowNonProvisionableDevices $True
Write-Host "A new Mobile Device Mailbox Policy has been created" -ForegroundColor Green
$easpolicy = Get-MobileDeviceMailboxPolicy
}

foreach ($account in $accounts)
{
New-Mailbox -MicrosoftOnlineServicesID $account.upn -Alias $account.alias -Name $account.name -Room -EnableRoomMailboxAccount $True -RoomMailboxPassword (ConvertTo-SecureString -String $account.password -AsPlainText -Force)
Set-Mailbox -Identity $account.upn -Type Regular
Set-CASMailbox -Identity $account.upn -ActiveSyncMailboxPolicy SurfaceHubs
Set-Mailbox -Identity $account.upn -Type Room
Set-Mailbox -Identity $account.upn -RoomMailboxPassword (ConvertTo-SecureString -String $account.password -AsPlainText -Force) -EnableRoomMailboxAccount $True
Set-CalendarProcessing -Identity $account.upn -AutomateProcessing AutoAccept -AddOrganizerToSubject $False –AllowConflicts $False –DeleteComments $False -DeleteSubject $False -RemovePrivateProperty $False -AddAdditionalResponse $True -AdditionalResponse "This is a Surface Hub room!"
Set-CalendarProcessing -Identity $account.upn -ProcessExternalMeetingMessages $True
Set-MsolUser -UserPrincipalName $account.upn -PasswordNeverExpires $True
Set-MsolUserLicense -UserPrincipalName $account.upn -AddLicenses $skus.AccountSkuId
Set-MsolUser -UserPrincipalName $account.upn -UsageLocation $countrycode
Enable-CsMeetingRoom -Identity $account.upn -RegistrarPool $regpool -SipAddressType UserPrincipalName
}

This post has been published mostly for remembering myself on how the accounts should be created (if possible), when having a scenario where they cannot be created in the on-premises Active Directory and being synchronized.

A follow up post will come later on regarding the accounts of Surface Hub

Great collaboration with Daniel Blunda regarding these accounts!

Upcoming book publication | Exchange 2013 SP1 – PowerShell v5

I wanted to let you all know that a second book will soon be released, about Exchange 2013 SP1 and PowerShell v5. At a current stage using PS v5 with 2013 SP1 isn’t supported.
However, there are some new great things around it and those will be brought up in the book.

I have received tons of great feedback from Hakim Taoussi, Mark Andrews and Steve Goodman.
In summary, it was a great collaboration between the Packt Publishing people and me as author and the reviewers. Really great contributions everyone!

The books is now in the final stage and will be released during the summer. It can already now be pre-ordered at: https://www.packtpub.com/networking-and-servers/microsoft-exchange-server-powershell-cookbook-third-edition.

 

Exchange 2016 Preview | vNext

Yesterday, Swedish time Exchange 2016 preview was announced being able for public download.

Since I do work for Microsoft, I don’t want to write about any release time frame, the Product Group (PG) has said later this year.

If you want to read more about the preview from the PG, see the link: http://blogs.technet.com/b/exchange/archive/2015/07/22/announcing-exchange-server-2016-preview.aspx

A direct link to the download of the preview: http://www.microsoft.com/en-us/download/details.aspx?id=48210

 

From now on I will try to be more active on the blog again, publishing interesting articles and news.
Cheers

Summary of year 2014

Summary:

Fantastic, beautiful, hectic, fun, stressed… well.. this year (2014) got it all! In most ways it has been great 🙂
In the professional way I took the opportunity to join Microsoft AB/MCS (Microsoft Consulting Services) and together with that me and my wife (yes we got married this year too) moved from Malmö to Stockholm in late February 2014.

We had some struggle to find an rental apartment but sorted it out, then sold my old apartment and bought a new one in Stockholm. In the meantime we planned our wedding and had our wedding in May together with family and friends. On the spare time in there between somewhere, I also trained for a 30km running competition in the forests in Stockholm called Lidingöloppet.
In the autumn I think we spent most of our spare time and weekends with renovating the new apartment and finally we are pretty much done, just some minor things to complete now.

wedding

 

 

 

 

 

 

 

 

At MCS, I’ve been spending a lot of time working with Office 365, with most of its workloads and done deep dive’s into DirSync and Azure AD Sync, AD FS for Office 365 but also working with Exchange on-premise and advanced PowerShell creating identities in Office 365/Azure AD and also been involved in automation an creation of an whole test environment of virtual servers, including applications and settings in Azure using PowerShell Desired State Configuration (DSC).

 

Goals for 2015:

Health – It’s time to start serious training at the gym again and take care of the health a bit better than 2014. This is no #1 priority for me 🙂

Exchange 2013 PowerShell book update – upcoming 3rd edition of the success story (Microsoft Exchange Server 2013 PowerShell Cookbook: Second Edition) is planned to be released in June/July 2015. Now based on PowerShell v4/v5 and also includes Desired State Configuration (DSC). For more news about this use the link above and follow me on twitter.

Career – The plan is to dig into details about SharePoint, Azure, Lync, FIM/MIM.. many things to learn!

Together with a colleague planning to release a cross-platform “App” to Windows Phone, iPhone and Android. Keep you’re eyes open here for more news about that!

Address Book Policy using Exchange Online (Office 365)

The question were raised a couple of times and I couldn’t find any related articles besides the official TechNet articles, so I decided to write one myself.

Some organizations have the need of separating people from seeing each other in the global address list (GAL), this is known as GAL segmentation and have been on the surface for a long time.

However, when it comes to do a segmentation in Office 365 and Exchange Online, it can be challenging and difficult, so I decided to write this article and provide an example of how this can be done.

 

Scenario – segmentation between school (students & teachers) and others (teachers, admin personnel and managers).

In detail the teachers and the students should be able finding each other in the address lists, while the administrators shouldn’t be able finding the students in their lists. However, administrators and teachers should be able to reach out through the address lists.

 

ABP

 

RBAC

By default the global administrator DON’T have access to manage the address lists, so either add the Address List Management permissions into the Organization Management role group or create a new role group with the role Address List Management and add the appropriate user into the group.

 

Attributes

One way of making sure the segmentation is working they way it is expected is to make it possible grouping the users using the extensionAttribute/CustomAttribute values in AD/Exchange.
These should be configured in the on-premise Active Directory (AD).

In this example all students and teachers has a value of “EDU” in their extensionAttribute15/CustomAttribute15, while the others have a value of “ADM” in their extensionAttribute14/CustomAttribute14 so they can easily be filtered.

With the attribute values in place, we need to configure address lists, global address list, offline address book, address book policy and finally apply it to the mailboxes.

This is done using PowerShell for Exchange Online running the following cmdlets..

 

Configuration for students and teachers


New-AddressList -Name "AL-EDU-Users-DGs" -RecipientFilter {((RecipientTypeDetails -eq 'UserMailbox') -or (RecipientTypeDetails -eq "MailUniversalDistributionGroup") -or (RecipientTypeDetails -eq "DynamicDistributionGroup")) -and (CustomAttribute15 -eq "EDU")}

New-AddressList -Name "AL-EDU-Rooms" -RecipientFilter {((Alias -ne $null) -and ((RecipientDisplayType -eq 'ConferenceRoomMailbox') -or (RecipientDisplayType -eq 'SyncedConferenceRoomMailbox'))) -and (CustomAttribute15 -eq "EDU")}

New-GlobalAddressList -Name "GAL-EDU" -RecipientFilter {(CustomAttribute15 -eq "EDU")}

New-OfflineAddressBook -Name "OAB-EDU" -AddressLists "GAL-EDU"

New-AddressBookPolicy -Name "ABP-EDU" -AddressLists "AL-EDU-Users-DGs","AL-EDU-Rooms" -OfflineAddressBook "\OAB-EDU" -GlobalAddressList "\GAL-EDU" -RoomList "\AL-EDU-Rooms"

Get-Mailbox | Where {$_.CustomAttribute15 -eq "EDU"} | Set-Mailbox -AddressBookPolicy "ABP-EDU"

 

Configuration for administrator personnel, managers and teachers


New-AddressList -Name "AL-ADM-Users-DGs" -RecipientFilter {((RecipientTypeDetails -eq 'UserMailbox') -or (RecipientType -eq "MailUniversalDistributionGroup") -or (RecipientType -eq "DynamicDistributionGroup")) -and (CustomAttribute14 -eq "ADM")}

New-AddressList -Name "AL-ADM-Rooms" -RecipientFilter  {((Alias -ne $null) -and ((RecipientDisplayType -eq 'ConferenceRoomMailbox') -or (RecipientDisplayType -eq 'SyncedConferenceRoomMailbox'))) -and (CustomAttribute14 -eq "ADM")}

New-GlobalAddressList -Name "GAL-ADM" -RecipientFilter {(CustomAttribute14 -eq "ADM")}

New-OfflineAddressBook -Name "OAB-ADM" -AddressLists "GAL-ADM"

New-AddressBookPolicy -Name "ABP-ADM" -AddressLists "AL-ADM-Users-DGs","AL-ADM-Rooms" -OfflineAddressBook "\OAB-ADM" -GlobalAddressList "\GAL-ADM" -RoomList "\AL-ADM-Rooms"

Get-Mailbox | Where {$_.CustomAttribute14 -eq "ADM"}  | Set-Mailbox -AddressBookPolicy "ABP-ADM"

 

Configuration for teachers (“Everyone”)

The configuration for the teachers is a bit different since they should be able to see all users, in my example I do configure the policy to include all address lists, this can be configured so it matches your requirements.


New-AddressBookPolicy -Name "ABP-Teachers" -AddressLists "AL-ADM-Users-DGs","AL-ADM-Rooms","AL-EDU-Users-DGs","AL-EDU-Rooms","All Groups","All Contacts","All Distribution Lists","All Rooms","All Users" -OfflineAddressBook "\Default Offline Address Book" -GlobalAddressList "\Default Global Address List" -RoomList "\All Rooms"

Get-Mailbox | Where {$_.CustomAttribute1 -eq “teachers”} | Set-Mailbox -AddressBookPolicy "ABP-Teachers"

 

Ps. In the example for applying the policy to teachers, I’ve filtered the users using extensionAttribute1/CustomAttribute1 with the value of “teachers”.

 

The final result is shown below..

Students – able to find students and teachers in GAL

2014-09-30 13-51-27

Admins – able to find admins, managers and teachers in GAL

2014-09-30 13-53-06

Managers – able to find admins, managers and teachers in GAL

2014-09-30 13-54-05

Teachers – able to find everyone in GAL

2014-09-30 14-00-11

 

I hope this gave a more clear picture of the configuration to you, feel free to comment or give any feedback!

 

More information:

http://technet.microsoft.com/en-us/library/jj657455(v=exchg.150).aspx

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. "}
 }

Congratulations 2014 Microsoft MVP!

Congratulations 2014 Microsoft MVP!

This year started in the best possible way when I received the MVP Award for Exchange Server, I’m honored and very proud over this special recognition!

I want to give out lots of thanks to everyone out there for visiting this blog, buying and reading the PowerShell book and other activities I’ve been involved in.

I also want to say thanks to Mike Pfeiffer and Packt Publishing for making it possible for me to publish the book. I want to send out a special thanks to Magnus Björk and Hakim Taoussi for their great support.


Dear Jonas Andersson,
Congratulations! We are pleased to present you with the 2014 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others. We appreciate your outstanding contributions in Exchange Server technical communities during the past year.

Finally, here’s a picture of the award I got this Friday 🙂

bild(1)

Load More