Export-ExchangeURLs.ps1
<#PSScriptInfo
.VERSION 3.3.4 .GUID 0a1b89dc-e2b3-4e34-b1ad-e86ca7f6833d .AUTHOR Sam Drey .COMPANYNAME Microsoft Canada #> <# .SYNOPSIS This script dumps the URLs of all your Exchange servers in a CSV file .DESCRIPTION This script exports the URLs of all the Exchange servers in a CSV file by default, or dumps the info to the screen (you can then redirect to a file if you wish) if you use the -DoNotExport switch with the script. .PARAMETER E2010 When specified, will export E2010 only, or if specified with E2007 / E2013 / 2016, will export the specified versions. When none of E2007, E2013, E2016 are specified, all versions are scanned. .PARAMETER E2013 When specified, will export E2013 only, or if specified with E2007 / E2016, will export the specified versions. When none of E2007, E2013, E2016 are specified, all versions are scanned. .PARAMETER E2016 When specified, will export E2016 only, or if specified with E2007 / E2013, will export the specified versions. When none of E2007, E2013, E2016 are specified, all versions are scanned. .PARAMETER DoNotExport This parameter tells the script not to export to a file. The results will just be dumped to the screen. .PARAMETER CheckVersion This parameter dumps the current script version - the script stops processing after displaying the version if this parameter is specified, no matter what other parameter is also specified. .INPUTS None. .OUTPUTS Exports a CSV file, or the screen. .EXAMPLE .\Export-ExchangeURLs.ps1 Will export all URLs for all Exchange servers' virtual directories into a file named ExchangeURLs_Day_Date_Time.csv .EXAMPLE .\Export-ExchangeURLs.ps1 -DoNotExport Will just print the results into the PowerShell console. .NOTES V3.2 -> Fixed mistake : Typo in OWAexternalURL, ECP and EWS, and OAB ... fixed V3 -> adding switches to select which Exchange version to check (not finished yet) .LINK https://github.com/SammyKrosoft #> [CmdletBinding(DefaultParameterSetName = "E2010")] Param( [Parameter(Mandatory = $False, Position = 1, ParameterSetName = "Ex2010")] [Parameter(Mandatory = $False, Position = 1, ParameterSetName = "Ex2013")] [Parameter(Mandatory = $False, Position = 1, ParameterSetName = "Ex2016")] [switch]$DoNotExport, [Parameter(Mandatory = $False, Position = 2, ParameterSetName = "Ex2010")][switch]$E2010, [Parameter(Mandatory = $False, Position = 3, ParameterSetName = "Ex2013")][switch]$E2013, [Parameter(Mandatory = $False, Position = 4, ParameterSetName = "Ex2016")][switch]$E2016, [Parameter(Mandatory = $False, Position = 5, ParameterSetName = "checkversion")][Switch] $CheckVersion ) <# ------- SCRIPT_HEADER (Only Get-Help comments and Param() above this point) ------- #> #Initializing a $Stopwatch variable to use to measure script execution $stopwatch = [system.diagnostics.stopwatch]::StartNew() #Using Write-Debug and playing with $DebugPreference -> "Continue" will output whatever you put on Write-Debug "Your text/values" # and "SilentlyContinue" will output nothing on Write-Debug "Your text/values" $DebugPreference = "Continue" # Set Error Action to your needs $ErrorActionPreference = "SilentlyContinue" #Script Version $ScriptVersion = '3.3.4' <# Version History v3.3.4 - added export server Site information as ServerSite v3.3.3 - added -ADPropertiesOnly for Get-MAPIVirtualDirectory v3.3.2 - removed "AutoDiscName" column as it's the same value as "ServerName" v3.3.1 - changed author's name to Sam Drey and current company v3.3 - added MAPI URLs export v3.2 - See Notes v3.1 : fixed Exchange version switches, Get-ClientAccessSErvice is for E2016 only, NOT E2013. v1.0 -> v2 Added export of Outlook Anywhere with External Hostname (E2010, E2013, E2016) and Internal Hostname (not existing in E2010) Fixed output file name Added -DoNoExport switch, to not export to a file... #> # Log or report file definition # NOTE: use #PSScriptRoot in Powershell 3.0 and later or use $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition in Powershell 2.0 # $LogOrReportFile1 = "$PSScriptRoot\ReportOrLogFile_$(get-date -f yyyy-MM-dd-hh-mm-ss).csv" # Other Option for Log or report file definition (use one of these) # $LogOrReportFile2 = "$PSScriptRoot\PowerShellScriptExecuted-$(Get-Date -Format 'dd-MMMM-yyyy-hh-mm-ss-tt').txt" If ($CheckVersion) {Write-Host "Script Version v$ScriptVersion";exit} <# ---------------------------- /SCRIPT_HEADER ---------------------------- #> <# -------------------------- DECLARATIONS -------------------------- #> <# /DECLARATIONS #> <# -------------------------- FUNCTIONS -------------------------- #> <# /FUNCTIONS #> <# -------------------------- EXECUTIONS -------------------------- #> #Loading Exchange 2010 snapins enabling script to be executed on a basic Powershell session #Note: you must have Exchange Admin tools installed on the machine where you run this. Add-PSSnapin microsoft.exchange.management.powershell.admin -erroraction 'SilentlyContinue' | OUT-NULL Add-PSsnapin Microsoft.Exchange.Management.PowerShell.E2010 -erroraction 'SilentlyContinue' | OUT-NULL Add-PSsnapin Microsoft.Exchange.Management.PowerShell.Setup -erroraction 'SilentlyContinue' | OUT-NULL Add-PSsnapin Microsoft.Exchange.Management.PowerShell.Support -erroraction 'SilentlyContinue' | OUT-NULL #For Exchange 2007 and 2013, add the corresponding modules/snapins, or simply execute the script into an Exchange MAnagement Shell :-) #Getting all Exchange servers in an array #Note: you can target only one server, or get servers list from a file, #just change the $Servers = @(Get-ClientAccessServer) line with $Servers = @(Get-content ServersList.txt) for example to get servers from a list... $Servers = @() #Sample Server Filtering: # $Exchange2010CASServers = Get-ExchangeServer * | ? {$_.serverRole -match "Client" -and $_.AdminDisplayVersion -match '14.'} | Ft name, serverRole, AdminDisplayVersion $ServerVersionFilter = $null $ExchangeServers = Get-ExchangeServer * #Filtering out Exchange versions # 14.x => Exchange 2010 # 15.0 => Exchange 2013 # 15.1 => Exchange 2016 if ($E2010) { Write-debug "E2010 switch on"; $ExchangeServers = $ExchangeServers | ? {$_.ServerRole -match "Client" -and $_.AdminDisplayVersion -match '14\.'} If ($ExchangeServers -eq $null) { $msg = "No Exchange 2010 servers found - Try -E2013 or E2016 or no switch ... exiting."; Write-host $msg exit } Else { $msg = "Found $($ExchangeServers.count) Exchange 2010 servers." Write-host $msg } } if ($E2013) { Write-debug "E2013 switch on";$ExchangeServers = $ExchangeServers | ? {$_.AdminDisplayVersion -match '15\.0'} If ($ExchangeServers -eq $null) { $msg = "No Exchange 2013 servers found - Try -E2013 or E2016 or no switch ... exiting."; Write-host $msg exit }Else { $msg = "Found $($ExchangeServers.count) Exchange 2013 servers." Write-host $msg } } if ($E2016) { Write-debug "E2016 switch on";$ExchangeServers = $ExchangeServers | ? {$_.AdminDisplayVersion -match '15\.1'} If ($ExchangeServers -eq $null) { $msg = "No Exchange 2016 servers found - Try -E2013 or E2016 or no switch ... exiting."; Write-host $msg exit }Else { $msg = "Found $($ExchangeServers.count) Exchange 2016 servers." Write-host $msg } } If (!$E2010 -and !$E2013 -and !$E2016) { Write-debug "No switches - Discovering all servers`nNOTE: always run scripts from highest version of Exchange otherwise you won't see all servers"; If ($ExchangeServers -eq $null) { $msg = "No Exchange Exchange 2010, 2013 or 2016 servers found ... exiting."; Write-host $msg exit }Else { $msg = "Found $($ExchangeServers.count) Exchange servers." Write-host $msg } } $Servers = $ExchangeServers $Servers | Select Name, ServerRole, @{Label = "Exchange Version"; Expression = {$_.AdminDisplayVersion}} | ft -a # DEBUG PURPOSE : MANUAL EXIT (BREAK) BELOW - COMMENT WHEN NOT DEBUGGING # exit #Initializing counters to setup a progress bar based on the number of servers browsed # (more useful in an environment where you have dozen of servers - had 45 in mine) $Counter=0 $Total=$Servers.count #Initializing the variable where I'll put all the results of my object browsing $report = @() #For each server discovered in the "$Servers = Get-ClientAccessServer" line, # grab the Virtal Directories properties and store it in a custom Powershell object, # and then add this object in the $report array variable to eventually dump the whole result in a text (CSV) file. foreach( $Server in $Servers) { #$Computername=$Server.Name <- not needed for now #This is to print the progress bar incrementing on each server (increment is later in the script $Counter++ it is... $Pct=($Counter/$Total)*100 Write-Progress -Activity "Processing Server $Server" -status "Server $Counter of $Total" -percentcomplete $pct #For the current server, get the main vDir settings (including AutodiscoverServiceInternalURI which is important to determine #whether the Autodiscover service will be hit using the Load Balancer (recommended). $EAS = Get-ActiveSyncVirtualDirectory -Server $Server -ADPropertiesOnly | Select Name, InternalURL,externalURL $OAB = Get-OabVirtualDirectory -Server $Server -ADPropertiesOnly | ? {$_.Name -like "*OAB*"} | Select Name,internalURL,externalURL $OWA = Get-OwaVirtualDirectory -Server $Server -ADPropertiesOnly | Select Name,InternalURL,externalURL $ECP = Get-EcpVirtualDirectory -Server $Server -ADPropertiesOnly | Select Name,InternalURL,externalURL #testing if there is an Exchange 2013/2016 in the $ExchangeServers collection - If TRUE then use Get-ClientAccessService, ELSE user Get-ClientAccessServer $TestE2016 = ($ExchangeServers | % {$_.AdminDisplayVersion -match "15\.1"}) -join ";" If ($TestE2016 -match "$true"){ $AutoDisc = get-ClientAccessService $($Server.Name) | Select identity,AutodiscoverServiceInternalUri } Else { $AutoDisc = get-ClientAccessServer $($Server.Name) | Select identity,AutodiscoverServiceInternalUri } $EWS = Get-WebServicesVirtualDirectory -Server $Server -ADPropertiesOnly | Select NAme,identity,internalURL,externalURL $OA = Get-OutlookAnywhere -Server $Server -ADPropertiesOnly | Select Name,InternalHostName, ExternalHostName #If you want to dump more things, use the below line as a sample: #$ServiceToDump = Get-Whatever -Server $Server | Select Property1, property2, .... <- don't need the "Select property", you can omit this, it will just get all attributes... $MAPI = Get-MAPIVirtualDirectory -Server $Server -ADPropertiesOnly | Select Name, InternalURL, ExternalURL # .... <- don't need the "Select property", you can omit this, it will just get all attributes... #Initializing a new Powershell object to store our discovered properties $Obj = New-Object PSObject #the below is a template if you need to dump more things into the final report #just replace the "ServiceToDump" string with the service you with to dump - don't forget to #Get something above like the $Service = Get-whatever -Server #$Obj | Add-Member -MemberType NoteProperty -Name "ServiceToDump-vDirNAme" -Value $ServiceToDump.Name #$Obj | Add-Member -MemberType NoteProperty -Name "ServiceToDump-InternalURL" -Value $ServiceToDump.InternalURL #$Obj | Add-Member -MemberType NoteProperty -Name "ServiceToDump-ExternalURL" -Value $ServiceToDump.ExternalURL $Obj | Add-Member -MemberType NoteProperty -Name "ServerName" -Value $Server.Name $Obj | Add-Member -MemberType NoteProperty -Name "ServerSite" -Value $Server.Site $Obj | Add-Member -MemberType NoteProperty -Name "ServerVersion" -Value $Server.AdminDisplayVersion #$Obj | Add-Member -MemberType NoteProperty -Name "EASName" -Value $EAS.Name $Obj | Add-Member -MemberType NoteProperty -Name "EASInternalURL" -Value $EAS.InternalURL $Obj | Add-Member -MemberType NoteProperty -Name "EASExternalURL" -Value $EAS.ExternalURL # $Obj | Add-Member -MemberType NoteProperty -Name "OABName" -Value $OAB.Name $Obj | Add-Member -MemberType NoteProperty -Name "OABInternalURL" -Value $OAB.InternalURL $Obj | Add-Member -MemberType NoteProperty -Name "OABExternalURL" -Value $OAB.ExternalURL #$Obj | Add-Member -MemberType NoteProperty -Name "OWAName" -Value $OWA.Name $Obj | Add-Member -MemberType NoteProperty -Name "OWAInternalURL" -Value $OWA.InternalURL $Obj | Add-Member -MemberType NoteProperty -Name "OWAExternalURL" -Value $OWA.ExternalURL # $Obj | Add-Member -MemberType NoteProperty -Name "ECPName" -Value $ECP.Name $Obj | Add-Member -MemberType NoteProperty -Name "ECPInternalURL" -Value $ECP.InternalURL $Obj | Add-Member -MemberType NoteProperty -Name "ECPExternalURL" -Value $ECP.ExternalURL $Obj | Add-Member -MemberType NoteProperty -Name "AutoDiscURI" -Value $AutoDisc.AutodiscoverServiceInternalURI # $Obj | Add-Member -MemberType NoteProperty -Name "EWSName" -Value $EWS.Name $Obj | Add-Member -MemberType NoteProperty -Name "EWSInternalURL" -Value $EWS.InternalURL $Obj | Add-Member -MemberType NoteProperty -Name "EWSExternalURL" -Value $EWS.ExternalURL $Obj | Add-Member -MemberType NoteProperty -Name "OutlookAnywhere-InternalHostName(NoneForE2010)" -Value $OA.InternalHostName $Obj | Add-Member -MemberType NoteProperty -Name "OutlookAnywhere-ExternalHostNAme(E2010+)" -Value $OA.ExternalHostName $Obj | Add-Member -MemberType NoteProperty -Name "MAPIInternalURL" -Value $MAPI.InternalURL $Obj | Add-Member -MemberType NoteProperty -Name "MAPIExternalURL" -Value $MAPI.ExternalURL #Appending the current object into the $report variable (it's an array, remember) $report += $Obj #Incrementing the Counter for the progress bar $Counter++ } If (!($DoNotExport)){ #Building the file name string using date, time, seconds ... $DateAppend = Get-Date -Format "ddd-dd-MM-yyyy-\T\i\m\e-HH-mm-ss" $CSVFilename=$PSScriptRoot+"\ExchangeURLs_"+$DateAppend+".csv" #Exporting the final result into the output file (see just above for the file string building... $report | Export-csv -notypeinformation -encoding Unicode $CSVFilename Notepad $CSVFilename } Else { Write-Host "Won't create a file because you specified the -DoNotExport parameter" -ForegroundColor Yellow -BackgroundColor Blue Write-Host "Just dumping to the screen this time ..." -ForegroundColor DarkBlue -BackgroundColor red $Report } <# /EXECUTIONS #> <# ---------------------------- SCRIPT_FOOTER ---------------------------- #> #Stopping StopWatch and report total elapsed time (TotalSeconds, TotalMilliseconds, TotalMinutes, etc... $stopwatch.Stop() Write-Host "`n`nThe script took $($StopWatch.Elapsed.TotalSeconds) seconds to execute..." <# ---------------- /SCRIPT_FOOTER (NOTHING BEYOND THIS POINT) ----------- #> |