Do Your Exchange Online Admin Tasks with PowerShell

Posted Leave a commentPosted in Exchange, Office 365, PowerShell

There are some things in Exchange that you just need to use PowerShell for.  If you use Exchange Online or Office 365, the web portal exposes a lot of the admin functionality that you might need, but there are certain actions that require PowerShell.

Accessing the Exchange PowerShell cmdlets on a local server is one thing, but accessing those cmdlets in a hosted environment can be a little trickier.  After I had to type these a half-dozen times, my brain wasn’t getting it quite yet, so I build a little script that covers what you need to need to establish a connection to the remote Exchange environment.

(more…)

Exchange 2010: Database Copies with PowerShell

Posted Leave a commentPosted in Exchange, PowerShell

I needed a quick and dirty method to add database copies to other servers in an Exchange 2010 Database Availability Group (DAG).  I had three servers, each with 10 databases.  Each one of those databases should have a copy on the other two servers. 

Now, this is painful if you have to use the GUI to do it – not that it takes a lot, but it’s time consuming.  The Add-MailboxDatabaseCopy cmdlet is very helpful in PowerShell, but still I wanted to automate it since my naming conventions were pretty standard.

So, I wrote a PowerShell script to automate this process.  Essentially, the script has a few variables and I dome some loop magic to drop everything into place. 

$servers = "E2K10MBX01", "E2K10MBX02", "E2K10MBX03"
$databases = "DB1", "DB2", "DB3", "DB4", "DB5", "DB6", "DB7", "DB8", "DB9", "DB10"
 
foreach($database in $databases)
{
       foreach($server in $servers)
       {
              foreach($copyserver in $servers)
              {
                     "Adding mailbox copy for $server-$database to $copyserver..."
                     Add-MailboxDatabaseCopy -Identity $server-$database -MailboxServer $copyserver -ErrorAction "Continue"
              }
       }
}

This script is quick and dirty for a lab environment.  Keep in mind that this doesn’t do any error checking and there is no validation to see if a database is already homed to a server.  This just uses the cmdlet to try to create the database copy; if it is successful, you’re good to go.  If it fails, the script just keeps on rolling.  No harm, no foul.

Exchange 2010 Pre-Req Setup (Updated)

Posted Leave a commentPosted in Exchange

A couple of months back I wrote a post on how to automatically install pre-requisites for Exchange 2010 on a Windows 2008 (including R2) server.

I specifically talked about a method for doing this with ServerManagerCmd.exe, which is included with Windows Server 2008.  However, in Windows Server 2008 R2, ServerManagerCmd is deprecated and the recommended method is to use PowerShell (as pointed out by my buddy, Josh). 

The Add-WindowsFeature cmdlet in PowerShell provides the capability to add individual Windows features directly from a script.  You can use Get-WindowsFeature to obtain a detailed list of available features, ones that are installed, and their “official” name if you wish to install them via PowerShell.

To install the required pre-reqs for Exchange 2010, from a PowerShell prompt, be sure to add the Server Manager module so the Add-WindowsFeature and Get-WindowsFeature cmdlets are available.

Import-Module ServerManager

Once you have imported the module, then you can use Add-WindowsFeature to take care of the rest.

Add-WindowsFeature -Name RSAT-ADDS-Tools, RPC-over-HTTP-proxy, NET-HTTP-Activation, Web-Dyn-Compression, Web-Windows-Auth, Web-Digest-Auth, Web-Basic-Auth, Web-Lgcy-Mgmt-Console, Web-Metabase, Web-ISAPI-Ext, Web-Server -Concurrent

PowerShell with Compellent and Exchange 2010

Posted 2 CommentsPosted in Compellent, Development, Exchange, PowerShell

I’ve been doing lots of work in the lab lately with Exchange 2010 to understand all the new changes and how it works with the Compellent Storage Center.

With Exchange 2010, the concept of Storage Groups no longer exists.  Databases are the sole object and are a peer to the server now.  Database names must be unique, but can be moved from server to server as necessary.

In the past, I’ve shared some scripts on how to provision storage for an Exchange 2007 environment.  I’ve slightly reworked this script to account for no longer needing storage groups, but to also automatically create the mailbox database on the Exchange Server and mount it when completed.

# NAME: Exchange2010LabCreate.ps1
# DESC: PowerShell script to create and map volumes for Exchange 2010 Lab
# BY  : Justin Braun, Compellent Technologies, Inc.
# DATE: November 24, 2009
# VER : 1.0
#
# 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.
#
 
####################################################
# ERROR HANDLING
####################################################
    #"SilentlyContinue": do not print, continue 
    #"Continue": Print, continue (this is the default) 
    #"Stop": Halt the command or script 
    #"Inquire": Ask the user what to do 
    $ErrorActionPreference = "Inquire"
 
####################################################
# STORAGE CENTER CONFIGURATION INFORMATION
####################################################
    $schost = "storagecenter.lab.test"
    $user = "username"
    $pass = "password"
 
####################################################
# EXCHANGE STORAGE CONFIGURATION
####################################################    
    # Number of Databases Per Server
    $dbsize = "1TB"
    $dbtotal = 1
    $dbDiskFolder = "Assigned"
 
####################################################
# SERVER INFORMATION
####################################################
    # Server to Map To (server defintion on CSC must match server name in Windows because of VDS)
    $ServerName = "E2K10MBX01"
 
####################################################
# MISC. CONFIGURATION SETTINGS
####################################################
    # Volume folder name
    $SCParentFolderName = "E2K10MBX01"
    
    # Use custom disk folders for each volume? (if $false, then a single disk folder config is assumed)
    $useCustomDiskFolders = $false
    
    #Mountpoints (set to $true if mountpoint volumes weren't previously created.  Mountpoint volumes will be 1G by default)
    $createMountpointRoot = $true
    
    # Mountpoint Root
    $dbmproot = "M:\Exchange"
    $dbRootDrive = "M:"
 
##########################################################################################
##########################################################################################
# DO NOT EDIT BELOW THIS LINE !
##########################################################################################
##########################################################################################
 
 
# Creates volume with specified name and size using connection instantiated on script launch
function CreateVolume
{
    param
    (
        [string]     $VolumeName,
        [string]     $VolumeSize,
        [string]     $MPRoot,
        [string]     $SCDiskFolder,
        [bool]         $IsMountPoint
    )
 
    Write-Output "Creating new volume: $volumename..."
    if($useCustomDiskFolders -eq $true)
    {$scvolume = New-SCVolume -Name $VolumeName -Size $VolumeSize -ParentFolder $SCParentFolderName -StorageType $SCDiskFolder;}
    else
    {$scvolume = New-SCVolume -Name $VolumeName -Size $VolumeSize -ParentFolder $SCParentFolderName;}
 
    # Maps volume previously created and returned from CreateVolume function
    Write-Output "Mapping new volume $volumename to $servername..."
    
    # Map Volume (if multiple HBA ports are server will be used, make sure that MPIO is installed on server and remove -SinglePath switch from next line
    New-SCVolumeMap -VolumeIndex $scvolume.Index -ServerIndex $scserver.Index -SinglePath
 
    # Rescan Server
    Write-Output "Rescanning server for new volume..."
    Rescan-DiskDevice -Server $ServerName -RescanDelay 5
 
    # Issue Drive Letter / Mount Point
    Write-Output "Creating access path for new volume..."
    $device = Get-DiskDevice -SerialNumber $scvolume.SerialNumber
    
    # Check to see if the device is there yet after initial rescan
    if($device -eq $null)
    {
        # Device is still null, so let's perform up to 10 rescans before we move on
        $scancount = 0
        
        do
        {
            # Rescan the disk
            Write-Output "Rescanning server for new volume..."
            Rescan-DiskDevice -Server $ServerName -RescanDelay 5
            $scancount ++
            
            # Try getting the device again
            $device = Get-DiskDevice -SerialNumber $scvolume.SerialNumber
        }
        until($device -ne $null -or $scancount -eq 10)
    }
    
    # Set variable (this is only used if this is a drive letter mount)
    $finalpath = $MPRoot
    
    # Set full mountpoint path (create path if it doesn't exist)
    if($IsMountPoint -eq $true)
    {
        $finalpath = "$MPRoot\$VolumeName"
        
        # Check to make sure the full mountpoint path acutually exists, otherwise create it
        if (!(Test-Path -path "$finalpath\"))
        {
            New-Item "$finalpath\" -type directory
        }
    }
    
    Write-Output "Onlining Disk and setting access path to $finalpath..."
 
    # Finish creation of mountpoint/drive access
    Set-DiskDevice -SerialNumber $device.SerialNumber -Online
    Set-DiskDevice -SerialNumber $device.SerialNumber -ReadOnly:$false 
    $newvol = New-Volume -DeviceName $device.DeviceName -Server $ServerName -Label $VolumeName -AccessPath $finalpath
    
    # Null out device
    $device = $null
}
 
function LoadSnapins
{
    # Load Exchange Management Shell & Compellent Storage Center Snapins (if not already)
     $LoadedSnapins = Get-PSSnapin;
    $SnapinsToLoad = "Compellent.StorageCenter.Scripting", "Microsoft.Exchange.Management.PowerShell.E2010"
    
    "Adding PowerShell Snapins..."
 
    foreach($snapin in $SnapinsToLoad)
    {
        if (get-pssnapin $snapin -ea "silentlycontinue") 
        {
            write-host "$snapin is already loaded."
        }
        elseif (get-pssnapin $snapin -registered -ea "silentlycontinue") 
        {
            Add-PSSnapin $snapin
            Write-Host "$snapin is now loaded."
        }
        else 
        {
            write-host "PSSnapin $snapin not found" -foregroundcolor Red
        }
    }
}
 
#############################
# START SCRIPT
#############################
 
$started = Get-Date
 
#Load Requested Snapins
LoadSnapins
 
# Initialize Connection for Storage Center
#$pass = Read-Host -AsSecureString -Prompt "Please provide the Storage Center password for $user"
$securepass = ConvertTo-SecureString $pass -AsPlainText -Force
$connection = Get-SCConnection -HostName $schost -User $user -Password $securepass -Save $schost -Default
 
# Create new Volume Folder if it doesn't exist
$volumefolder = Get-SCVolumeFolder -Name $SCParentFolderName
if($volumefolder -eq $null)
{
    Write-Output "Creating new volume folder: $SCParentFolderName..."
    $volumefolder = New-SCVolumeFolder -Name $SCParentFolderName;
}
 
# Get server information for the server that we are mapping all of the volumes to
$scserver = Get-SCServer -Name $ServerName
 
# Create New Mount Point Volumes for database and logs (if requested)
if($createMountpointRoot -eq $true)
{
    CreateVolume "$ServerName-Exchange-MP" "1G" $dbRootDrive $dbDiskFolder $false
}
 
# Reset counters
$dbcount = 1
 
# Loop through total amount of databases for the server
do
{
    CreateVolume "$ServerName-DB$dbcount" $dbsize $dbmproot $dbDiskFolder $true
    
    "Creating mailbox database in Exchange 2010..."
    New-MailboxDatabase -Server $ServerName -Name "$ServerName-DB$dbcount" -EdbFilePath "$dbmproot\$ServerName-DB$dbcount\$ServerName-DB$dbcount.edb" -LogFolderPath "$dbmproot\$ServerName-DB$dbcount\Logs\"
    
    "Mounting new mailbox database..."
    Mount-Database -Identity "$ServerName-DB$dbcount"
    
    $dbcount ++ 
}
until($dbcount -eq $dbtotal + 1)
 
 
# Complete!
$ended = Get-Date
Write-Output "Volume Creation Complete!"
Write-Output "Started: $started"
Write-Output "Finished: $ended"
 
#############################
# END SCRIPT
#############################

There are a number of areas in which this script can be improved and that I will continue to work on. 

Exception handling is very important.  Understanding how your code could react in particular scenarios is difficult, but you don’t want your script to bomb out every time you run it either.  I’ve build quite a bit of exception handling into the mapping and mounting portions of the script, but this can always be reworked to be improved.

Quick Hit: Installing Pre-Reqs for Exchange 2010

Posted 2 CommentsPosted in Exchange, Windows Server

This can be a bit tricky … and you can either get enough exposure by doing it so many times that you just know what needs to be installed before you start, or you can get through a bunch of steps in the setup before it stops to tell you that the right things aren’t installed and can’t continue.

Exchange 2010 requires Windows Server 2008 or Windows Server 2008 R2.  You can use Server Manager to install the Web Server (IIS) role, however, there are many, many pieces to IIS that are broken out into individual components in 2008.  Which ones are required to get you the prerequisites you need to get through the Exchange 2010 installation?

Instead, consider using ServerManagerCmd.exe, which is built-in in Windows 2008 to automate the role installation for you.  This command is very useful in installing new components and making sure that you have the pieces you need.  From a command line, run:

ServerManagerCmd -i RSAT-ADDS Web-Server Web-Metabase Web-Lgcy-Mgmt-Console Web-ISAPI-Ext NET-HTTP-Activation Web-Basic-Auth Web-Digest-Auth Web-Windows-Auth Web-Dyn-Compression RPC-over-HTTP-proxy Web-Net-Ext –Restart

This will install the necessary components including ADDS which needs to be installed for remote administration of Active Directory and for the Exchange 2010 schema extensions to be installed.  Once the command completes, the server will restart.  After that, you’re ready for your Exchange 2010 installation.

You can find more information on ServerManagerCmd.exe on Technet.