|
Each contribution is licensed to you under a License Agreement by its owner, not Microsoft. Microsoft does not guarantee the contribution or purport to grant rights to it.
|
Categories |
Connect Exchange Datacenter - 14.0.1(Community)
Script Code
Windows PowerShell
# ConnectExchangeDatacenter.ps1
# Copyright (c) 2010 Microsoft Corporation. All rights reserved.
#
# 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.
# Type get-help [script name] to get help of the script
param(
[Parameter(Position = 0, Mandatory = $false)]
[string]$LookForUpdates="Prompt",
[Parameter(Position = 1, Mandatory = $false)]
[string]$Authentication="Basic",
[Parameter(Position = 2, Mandatory = $false)]
[switch]$ClearCache
)
## Declare all local and global variables ######################################
# The color of the msg text
$foreColor = "Green"
# There will be separate version number for each script
$ConnectScriptVersion="14.0.1"
# This tag is used to search the version number from HTML content (or script code)
# With separate tag, we can update scripts independently
$connectScriptVersionTag = "ConnectScriptVersion"
$commonFunctionsScriptVersionTag = "CommonFunctionsScriptVersion"
$connectionScriptName = "ConnectExchangeDatacenter.ps1"
$commonFunctionsScriptName = "CommonConnectFunctions.ps1"
$connectionScriptUrl = "http://gallery.technet.microsoft.com/ScriptCenter/en-us/15876b57-d0ed-492d-bc8d-dc17cdf2d103"
$commonFunctionsScriptUrl = "http://gallery.technet.microsoft.com/ScriptCenter/en-us/cd04703f-aaee-4abe-a169-e6bd1a3fd5d4"
$fqdn = "ps.outlook.com"
$connectionUri = "https://$fqdn/powershell?serializationLevel=Full"
# We need this global variable to break recursive script call during auto update and script restart
if ($global:versionCheckComplete -eq $null)
{
$global:versionCheckComplete = $false
}
## COMMON CONNECTION FUNCTIONS #################################################
if (test-path $commonFunctionsScriptName)
{
. CommonConnectFunctions.ps1
}
else
{
Write-Error "Cannot find $commonFunctionsScriptName. Please download the script from $commonFunctionsScriptUrl"
}
## Declare all local functions ###############################################
function GetScriptTextFromWeb([string]$scriptName,[string]$scriptUrl)
{
$WebClient = New-Object System.Net.WebClient
# first download the html content (including script) from script center gallery
$htmlText = $WebClient.DownloadString($scriptUrl)
if ($htmlText -eq $null)
{
Write-Host -fore "Red" "Currently the script is not available at $scriptUrl. Please contact Exchange support for more details. Cannot do verion check and auto update this time."
return
}
# parse and load the Html content
$h = new-object -com "HTMLFILE"
$h.IHTMLDocument2_write($htmltext)
# find the script text from html content
foreach ($child in $h.body.childNodes)
{
if ($child.tagName -eq "DIV")
{
$scriptText = $child.innerText
break
}
}
if ($scriptText -ne $null)
{
$scriptLine = select-string -InputObject $scriptText -Pattern $scriptName -AllMatches
if ($scriptLine -ne $null)
{
# we have placed a marker string (the string name) at the beginning and at the end of each script, so that we can extract the script text based on the markers
if ($scriptLine.matches.length -lt 2)
{
Write-Warning "Invalid script format. The script should contain script name as comment at the beginning and at the end of the script. Skipping version check..."
return
}
$start = $scriptLine.matches[0]
$end = $scriptLine.matches[$scriptLine.matches.length-1]
$scriptText = $scriptText.SubString($start.Index-2, $end.Index - $start.Index + $scriptName.length + 2)
}
}
$scriptText
}
function AutoUpdateScript([string]$scriptName, [string]$scriptText, [string]$scriptUrl, [string]$currentScriptVersion)
{
$backupScriptName = ($scriptName.split(".")[0]+"_"+$currentScriptVersion+"."+$scriptName.split(".")[1])
copy-item $scriptName $backupScriptName
set-content -path $scriptName -value $scriptText
Write-Host -fore $foreColor "Auto update complete. The script has been backed up as $backupScriptName"
if ($scriptName -eq "ConnectExchangeDatacenter.ps1")
{
Write-Host "Restarting the script $scriptName"
$global:versionCheckComplete = $true
$cmd = "$scriptName $script:paramString"
iex $cmd
Exit
}
}
function check-version ([string]$scriptName, [string]$scriptUrl, [string]$currentScriptVersion, [string]$currentScriptVersionTag)
{
Write-Host -fore $foreColor "Checking version of the script $scriptName. Current version is $currentScriptVersion"
$scriptText = GetScriptTextFromWeb $scriptName $scriptUrl
if ($scriptText -ne $null)
{
# now look for the script version tag in script header
$uploadedScriptVersionLine = select-string -InputObject $scriptText -Pattern $currentScriptVersionTag
if ($uploadedScriptVersionLine -ne $null)
{
# script version is 6 charcter i.e. 14.0.0
$uploadedScriptVersion = $uploadedScriptVersionLine.Line.Substring($uploadedScriptVersionLine.matches[0].Index + $currentScriptVersionTag.length + 2, 6)
if ($uploadedScriptVersion -ne $null)
{
Write-Host -fore $foreColor "The version of the uploaded script is $uploadedScriptVersion"
$currentVersion = New-Object System.Version $currentScriptVersion
$uploadedVersion = New-Object System.Version $uploadedScriptVersion
if ($uploadedVersion -gt $currentVersion)
{
Write-Host -fore $foreColor "The version of the script $scriptName is older than the version of the uploaded script in $scriptUrl"
AutoUpdateScript $scriptName $scriptText $scriptUrl $currentScriptVersion
}
elseif ($uploadedVersion -lt $currentVersion)
{
Write-Warning "The version number in $scriptName is higher than the version number in the uploaded script. Skipping version check..."
}
else
{
Write-Host -fore $foreColor "The version of your script matched with the version of the uploaded script."
}
}
else
{
Write-Warning "Could not find the version number in $scriptName. Skipping version check..."
}
}
else
{
Write-Warning "Could not find the script version tag $currentScriptVersionTag in $scriptName. Skipping version check..."
}
}
}
function Nego2Enabled
{
$osVer = [environment]::osversion
$isWin7 = ($osVer.Version.Major -ge 7) -or (($osVer.Version.Major -ge 6) -and ($osVer.Version.Minor -ge 1))
$isWin7
}
## FILTERS #################################################################
## Assembles a message and writes it to file from many sequential BinaryFileDataObject instances
Filter AssembleMessage ([String] $Path) { Add-Content -Path:"$Path" -Encoding:"Byte" -Value:$_.FileData }
## now actually call the functions
if ($global:versionCheckComplete -eq $false)
{
if ($LookForUpdates -eq "Skip")
{
Write-Host -fore $foreColor "Skipping version check..."
}
elseif ($LookForUpdates -eq "Prompt")
{
$optCheckVersion = Read-Host "Do you want to check the version of the current script and do auto update (y/n)?"
}
if (($LookForUpdates -eq "Auto") -or ($optCheckVersion -eq "y"))
{
# we need to save the user input parameters for the next recursive call during auto update
$matchResult = select-string -InputObject $myinvocation.Line -pattern " -"
if ($matchResult -ne $null)
{
$script:paramString = $matchResult.Line.Substring($matchResult.Matches[0].Index + 1, $matchResult.Line.Length - $matchResult.Matches[0].Index - 1)
}
check-version $commonFunctionsScriptName $commonFunctionsScriptUrl $CommonFunctionsScriptVersion $commonFunctionsScriptVersionTag
check-version $connectionScriptName $connectionScriptUrl $ConnectScriptVersion $connectScriptVersionTag
}
elseif ($optCheckVersion -eq "n")
{
Write-Warning "You have skipped version check and auto update for $connectionScriptName. The current script might not work correctly. You can download the updated script from $connectionScriptUrl"
}
elseif ($optCheckVersion -ne $null)
{
Write-Warning "Invalid response. Skipping version check and auto update..."
}
if (($LookForUpdates -ne "Skip") -and ($LookForUpdates -ne "Prompt") -and ($LookForUpdates -ne "Auto"))
{
Write-Host -fore Red "Invalid value for parameter LookForUpdates. Valid values are 'Skip', 'Prompt' and 'Auto'"
Exit
}
}
else
{
Write-Host -fore $foreColor "Skipping version check for script restart..."
}
if ($global:versionCheckComplete -ne $null)
{
Remove-Variable versionCheckComplete -Scope Global
}
## First clear up any existing sessions and modules in the current runspace. Ideally there should be only one session in the runspace ###
Write-Host -fore Yellow "Removing any existing sessions and modules from the current runspace..."
Get-PSSession | Remove-PSSession
Get-Module | Remove-Module
## Now establish the connection with Exchange Datacenter Server #################
Write-Host -fore Yellow "Connecting to Exchange Server $fqdn ..."
Write-Host -fore $foreColor ("Using Powershell version {0} (Build version {1})" -f $PSVersionTable.PSVersion.ToString(),$PSVersionTable.BuildVersion.Tostring())
# by default connecting using Basic auth
if ($Authentication -eq "Basic")
{
Write-Host -fore $foreColor "Using Basic authentication...."
$userName = Read-Host "Please enter your Username"
$secureString = Read-Host -AsSecureString Password
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList $userName,$secureString
$global:remoteSession = new-pssession -connectionURI $connectionUri -ConfigurationName Microsoft.Exchange -Authentication Basic -credential $credential -AllowRedirection
}
elseif ($Authentication -eq "Nego2") #using Nego2 Auth
{
if (-not (Nego2Enabled))
{
Write-Host -fore Yellow "The current OS is not Win7, Nego2 Authentication might not work correctly in a non-Win7 OS. If you have installed any Identity Client Runtime Library (i.e. wllogin.msi) or enabled Windows Live ID sign-in assistant in outlook, then ignore this warning"
}
Write-Host -fore $foreColor "Using Nego2 authentication...."
$connectionUri = ($connectionUri.Split("?")[0]+"/PowerShell.htm")
$credential = Get-ExLiveIDCredential -connectionUri $connectionUri
$global:remoteSession = new-pssession -connectionURI $connectionUri -ConfigurationName Microsoft.Exchange -Authentication Negotiate -credential $credential -AllowRedirection
}
else
{
Write-Error "Invalid value for -Authentication. Use either 'Basic' or 'Nego2' Authentication. By default 'Basic' Authentication is used"
Exit
}
if ($global:remoteSession -ne $null)
{
$global:connectedFqdn = $fqdn
Write-Host -fore $foreColor "Importing session (i.e. Exchange cmdlets/scripts) in the current runspace ..."
if ($ClearCache)
{
ImportPSSession -ClearCache:$true
}
else
{
ImportPSSession -ClearCache:$false
}
}
else
{
$forumUrl = "http://outlookliveanswers.com/forums/11.aspx"
$powershellFAQUrl = "http://help.outlook.com/en-us/140/cc875890.aspx"
Write-Host -fore $foreColor "Please consult the Powershell FAQ at $powershellFAQUrl and discussion forum at $forumUrl for troubleshootng information. For more help please contact outlook support"
}
# .SYNOPSIS
# Creates a new remote powershell session to the Microsoft Exchange Hosted Datacenter and
# imports the session into the current user's runspace.
#
# .DESCRIPTION
# Use this script to create a new remote powershell session to one of the Microsoft
# Exchange Hosted Datacenter. By default, it connects to ps.outlook.com and redirects to
# appropriate site based on user credential.
#
# .PARAMETER LookForUpdates
# Check the version of the current scripts and do auto update
# values:
# Skip - Skip version check and auto update
# Prompt (default value) - Prompt before version check and auto update
# Auto - Do version check and auto update without user prompt
# .PARAMETER Authentication
# Currently supported Authentication types are 'Basic' and 'Nego2'
# In both cases it will prompt for user credential
# Default: Basic
# .PARAMETER ClearCache
# When remote powershell session is created for the first time, then the session is cached
# locally at %APPDATA%\Microsoft\Exchange\RemotePowerShell, so that we can use the cache
# from next remote powershell connections.
# Use of this switch will clear the cache before creating a new remote powershell session
# Default: false
#
# .EXAMPLE
# ConnectExchangeDatacenter.ps1
#
# Creates a new remote powershell session to ps.outlook.com endpoint.
# It will prompt for version check and auto upate. It will also prompt
# for credentials and will use Basic Auth
#
# .EXAMPLE
# ConnectExchangeDatacenter.ps1 -LookForUpdates:Skip
#
# It will skip version check and auto upate.
# It will prompt for credentials and will use Basic Auth
#
# .EXAMPLE
# ConnectExchangeDatacenter.ps1 -LookForUpdates:Prompt
#
# It will prompt before version check and auto update
#
# .EXAMPLE
# ConnectExchangeDatacenter.ps1 -LookForUpdates:Auto
#
# It will do version check and auto update without user prompt
#
# .EXAMPLE
# ConnectExchangeDatacenter.ps1 -LookForUpdates:Auto -Authentication:Nego2
#
# It will not prompt for version check or auto upate.
# It will prompt for credentials and will use Nego2 Authentication
#
# .EXAMPLE
# ConnectExchangeDatacenter.ps1 -ClearCache
#
# It will clear the cached session before creating new remote powershell session.
# ConnectExchangeDatacenter.ps1
Platforms
For online peer support, join
The Official Scripting Guys Forum!
To provide feedback or report bugs in sample scripts, please start a new discussion on the Discussions tab for this script.
Disclaimer
The sample scripts are not supported under any Microsoft standard support program or service. The sample scripts are provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages.
Be the first to create a discussion.
|