Office 365: Connecting to Exchange Online with Remote PowerShell

As you may have heard, the Office 365 beta has started and it includes Microsoft Exchange Online, which is powered by Exchange Server 2010 SP1, and it can be fully managed via PowerShell v2 remoting. So, if you’re in the Office 365 beta, you can use the steps below to connect to Exchange Online with remote PowerShell from any machine with an internet connection. You just need PowerShell v2, which is installed by default on Windows 7 and 2008 R2. It can be downloaded and installed on down-level operating systems through Windows Update, or from here.

The process is very similar to how you would configure an implicit remoting session to an on-premise Exchange 2010 server. I blogged about how to do this here a while back. To connect to Exchange Online, use the following commands:

$cred = Get-Credential

When you execute the above command, you’ll be prompted for your Office 365 credentials. Enter your username in UPN format, such as user@domain.com. Next, create a new PSSession object using the following syntax:

$s = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $cred -Authentication Basic -AllowRedirection

The initial remote endpoint you’ll want to use is at ps.outlook.com as shown above. The -AllowRedirection switch parameter used in this command will allow redirection to the appropriate Exchange server using different URI. You’ll see a warning message in the shell informing you of the new server URI when you execute the above command.

Next, import the cmdlets to your local shell session:

$importresults = Import-PSSession $s

This will create a PSModuleInfo object and import the cmdlets into your local session. At this point, you are ready to start working with the Exchange cmdlets, but if you take a look at the module first, you’ll notice a couple of interesting things:

$importresults.ExportedFunctions.Count

Notice that the function count for this module is only 295. This means that you only have access to a fraction of the cmdlets that you would in an on-premise Exchange 2010 environment. You can run Get-Command as shown below to page through all of the Exchange cmdlets made available through the remote session:

Get-Command -Module $importresults | Out-Host -Paging

You’ll notice as you go through the cmdlets that most of them are recipient specific cmdlets. Since this is a hosted solution, you’ll see that cmdlets like *-MailboxServer, *-ExchangeServer, etc. are not available to you.

So, that’s all there is to it. If you want to learn more about Office 365, check out the Office 365 home page, and keep an eye on the Office 365 blog for news and updates.

Update 5/19/11: Just a quick update about PowerShell execution policy…

From the cmdlet help for Import-PSSession:

To use Import-PSSession, the execution policy in the current session cannot be Restricted or AllSigned, because the module that Import-PSSession creates contains unsigned script files that are prohibited by these policies.

The default PowerShell execution policy on a machine is set to Restricted. You can change the execution policy to RemoteSigned using Set-ExecutionPolicy RemoteSigned to get the above example to work. This actually happens automatically when installing the Exchange 2010 tools on a machine, but if you are importing the cmdlets on a system without the tools, you’ll need to manually set the execution policy to a less restrictive setting (if you have not already done so). See the help fileabout_Execution_Policies for more details. Thanks to Terence who posted about his experience with this in the comments.

(source : http://www.mikepfeiffer.net/2010/11/office-365-connecting-to-exchange-online-with-remote-powershell/ )

Windows PowerShell 3.0 and Server Manager Quick Reference Guides

Quickly learn tips, shortcuts, and common operations in the new Windows Powershell 3.0, Windows PowerShell Workflow, Windows PowerShell ISE, Windows PowerShell Web Access, Server Manager for Windows Server 2012 Release Candidate, WinRM, and WS-Man.

http://www.microsoft.com/en-us/download/details.aspx?id=30002

 

PowerShell on Linux, Solaris, Mac, PHONES!!! etc

Igor Moochnick announced the first release of PASH, an open source implementation of PowerShell.  (I tripled check the date on his blog to make sure it really said April 6th and not April 1st. 🙂 ).  This is really exciting stuff.  This is one of the most requested items from IT shops that run heterogeneous environments.  They love PowerShell and want ALL their IT Pros to adopt it.  I haven’t tried it yet so I don’t know what it does/does not implement but I’m pretty excited about it.  I can’t wait to give it a try.

I’ll have to talk with the .NET guys about how they work with the MONO team to ensure compatibility.  If it gets/stays compatible, that is a super good thing for customers.  It it becomes a variation or separate dialect and confuses our customers, then that would be problem.

BTW – just to make one point REALLY clear – PowerShell running across heterogeneous platforms was a project goal from the very beginning of the project.  We architected and designed PowerShell so that our only “true” dependency was on .NET.  There are only 1 or 2 cases where I know that we call a Windows API (code signing).  In other words – what Igor is doing IS PERFECTLY FEASIBLE.  Sure, he won’t have WMI cmdlets on those other environments – you’ll have incidental variations – that is not a problem.  The engine and the language should work perfectly.

One last point.  I’m really looking forward to getting the Open Source communities input on PowerShell and suggestions on ways to improve it.  Their usage scenarios will be different and will highlight any flaws or shortcomings we have in other areas (e.g. text parsing/manipulation).  I look forward to hearing their complaints/recommendations.  Adding their perspective and insight will make PowerShell a better technology for everyone.

 

Check this out:

Windows (duh !..)

Pash on Mono + SuSE Linux

Pash on Compact .NET Framework

and (drum roll …) Pash on Mac

 

What a nice day!

Video: Dmitry Sotnikov – PowerShell Jobs in v2 and v3

Another day – another recording from PowerShell Deep Dive. For a change, this one is from a session delivered by yours truly. :) And it is on PowerShell jobs (also known as background jobs) and the functionality that they had in PowerShell 2.0 and are getting in PowerShell 3.0.

PowerShell jobs allow you to run your commands and scripts in the background without blocking your PowerShell. You can run multiple jobs, check their status, and collect results. We will also get a sneak peek of the new Jobs functionality coming in Windows 8! 

 

 

This is a live recording from European TEC 2011 PowerShell Deep Dive conference. See more PowerShell Deep Dive recordings here.

By the way, TEC US is just around the corner – April 29 – May 2, 2012 in San Diego. The agenda has already been published and is absolutely fantastic.

 

(source : http://dmitrysotnikov.wordpress.com/2012/03/28/video-dmitry-sotnikov-powershell-jobs-in-v2-and-v3/ )

Windows Azure PowerShell Cmdlets

Microsoft Azure The Windows Azure PowerShell Cmdlets 2.2.2 enable you to browse, configure, and manage Windows Azure Compute and Storage services directly from PowerShell.  These tools can be helpful when developing and testing applications that use Windows Azure Services.  For instance, using these tools you can easily script the deployment and upgrade of Windows Azure applications, change the configuration for a role, and set and manage your diagnostic configuration and diagnostic data. 

You can view a full list of the PowerShell Cmdlets here.

 

 

The cmdlets are based on the the Windows Azure Management and Diagnostics APIs and the full source code is available through this CodePlex project so you can better understand the underlying APIs.   Finally, the documentation included with the download package also shows how to use the cmdlets to perform a new Windows Azure deployment and retrieve information about a hosted service.

(source : http://wappowershell.codeplex.com/ )

Exchange 2010 FAQ: How Do I Install the Exchange 2010 Management Tools?

The Exchange Server 2010 management tools can be installed on a computer running one of the following operating systems:

  • Windows Vista 64-bit with Service Pack 2
  • Windows 7 64-bit
  • Windows Server 2008 64-bit with Service Pack 2
  • Windows Server 2008 R2

To install the Exchange 2010 management tools on your Windows 7 computer you first need to configure the pre-requisite components.

Open the Control Panel, click on Programs and then click on Turn Windows Features On or Off.  Enable the features shown here.

Enable Windows 7 features required for Exchange Server 2010 management tools

Download the Exchange Server 2010 SP1 installation files and extract them to a temporary folder on your computer.  From that folder launch Setup.exe.  If your computer is missing either the .NET Framework or Windows PowerShell pre-requisites there will be links for Step 1 and 2 to download and install them.

Install pre-requisites for Exchange Server 2010 SP1 on Windows 7

Otherwise click on Step 3 and choose Install only languages from the DVD.

Choose language options for installing Exchange Server 2010 SP1 on Windows 7

Next, click on Step 4 to begin the installation.

Begin installation of Exchange Server 2010 SP1 on Windows 7

Click Next at the introduction page, then accept the license agreement and click Next, then choose your preference for Error Reporting and click Next again.

At the Installation Type page choose Custom Exchange Server Installation, and also tick the box to Automatically install Windows Server roles and features required for Exchange Server and click Next.

Custom Exchange Server installation for installing management tools on Windows 7

Select the Management Tools role and click Next.

Installing the Management Tools role for Exchange 2010 on Windows 7

When the Readiness Checks have completed successfully click Install.

Begin installation of Exchange 2010 management tools on Windows 7

After the install has completed you can launch the Exchange Management Console from the Start -> All Programs -> Microsoft Exchange Server 2010 menu.

(source : http://exchangeserverpro.com/exchange-2010-install-management-tools )

Import-Mailbox – Import mailboxes from PST into Exchange 2007 using powershell cmdlets

In Exchange 2003, one of the simplest ways to move mailboxes from one Exchange organisation to another was using exmerge. It was particularly useful for sites using ‘Small Business Server’ where the level of data and requirements were low.

In Exchange 2007, exmerge is not a supported method for Importing from PST files. The functionality has been naturally replaced with the Import-Mailbox cmdlet.

Prerequisites

1) You need to run a 32bit version of the Exchange Management tools (SP1 or higher, it should not be RTM, although the destination server for the import process can be RTM), and therefore require a 32 bit computer where you can install the management tools for the organisation. Make sure you use 2007 SP1 or higher management tools.

2) You need Outlook 2003 SP2 or higher installed on this PC.

3) You need to have full access rights to the mailbox you are importing to. You also need to be either Exchange Org Admin if mailboxes are across multiple servers, or Exchange Server Admin if the mailboxes are all on one server.

** A note on account permissions **

If you have tried with an account that does not have the correct Exchange administrator role, once you have fixed the issue by assigning either Exchange Org Admin or Exchange Server Admin you will need to Logout of the management station and log back in again for this change to take effect.

4) Update the computer with update rollup 9 (if using SP1) once you have installed the Management Tools.

5) You need to have created the mailbox enabled users first, and the user ‘alias’ (which is usually the users login name) needs to match the name of the pst file.

Step 1 – Install the Exchange 2007 SP1 Management Tools

Log in to the PC which has Exchange 2007 Management Tools SP1 installed and Outlook 2003 SP2 or higher installed with an appropriate account. During testing I was using Windows7, and this already has all the prerequisites for the management tools out the box. You may need to install the Management Tools prerequisites if you are using an older operating system.

Run a Custom install, and install just the management tools. We do not want to install any other roles on this workstation.

After the install, make sure that you run ALL the same update rollups as is on the Exchange server(s) in your organisation.

Step 2 – Add Full Access Permissions to the Mailboxes

Double check the account you are using on the management computer is an Exchange Organisation admin or Exchange server admin. Next is to add FullAccess to all the mailboxes. This is done using the Add-MailboxPermission cmdlet. I will not go into detail on this cmdlet. Suffice to say that running the following will give the user account ‘shaun’ FullAccess permission on all mailboxes for a particular mailbox server (omit the)

Get-ExchangeServer <servername> | Get-Mailbox | Add-MailboxPermission -User Shaun -AccessRights FullAccess -inheritancetype all

(after you are done, you may wish to remove these permissions, to do so, use the Remove-MailboxPermissions -User Shaun -AccessRights FullAccess -inheritancetype all -confirm:$false)

Of course, if you wish, you can perform this using the GUI, just go to EMC –> Recipient Configuration –> Mailbox and select the users –> Managed Full Access Permissions… on the Action pane and add the account there.

Step 3 – Using the Import-Mailbox cmdlet

Now is time for the Import-Mailbox command. The Import-Mailbox command has a couple of parameters that we are especially interested in.

-Identity

As the name suggests, this is where you specify the mailbox you would like to use for the destination of the import routine.

-PSTFolderPath

This will point the Import routine to look in the path for the PST files we are interested in. If you have only ONE PST file to import for a specific user, you can reference the exact PST file here and it will import the PST file. However be careful that you do not specify an explicit PST file and pipe multiple Mailboxes to the command, otherwise it will import the same PST file for all users which could have some embarrassing results!

-MaxThreads

This is the number of mailboxes to move at any one time. Now, this will largely depend on the resources that you have available. The typical value is 4, and this is normally more or less acceptable for this operation unless you have thousands of mailboxes, then you may want to increase this. Just remember ultimately you will have hardware bottlenecks.

-ValidateOnly

Using this switch is similar to the whatif switch in other cmdlets (and this one in fact). It will not move any data, only highlight if the process is likely to be successful and notify you if there are any issues you need to take care of.

So once we have the PST file(s) in the PSTFolderPath of our choosing run the command depending on your situation:

Importing a single PST to a single Mailbox:

Import-Mailbox <MAILBOX ALIAS> -PSTFolderPath <PathToFolderContainingPST>

Importing a bunch of PST files to their associated Mailboxes:

Dir c:PSTFiles*.pst | Import-Mailbox

Go through ALL mailboxes, and find associated PST and import:

Get-Mailbox | Import-Mailbox -PSTFolderPath <PathToFolderContainingPST>

So as you can see, this routine is all in the preparation of the environment. The actual commands you run to do the Import are small, sweet and efficient. The great thing about using Powershell for this task is that it is so scalable, if you have a situation where there are many PST’s you need to import, this will quite happily do the work.

 

References:

http://msexchangeteam.com/archive/2007/04/13/437745.aspx – You Had Me At EHLO… : How to Export and Import mailboxes to PST files in Exchange 2007 SP1

http://technet.microsoft.com/en-us/library/bb629586.aspx – Import-Mailbox cmdlet Technet reference

http://technet.microsoft.com/en-us/library/bb691363.aspx – How to Import Mailbox Data Technet reference

(source : http://exchangeshell.wordpress.com/2009/09/05/import-mailbox-import-mailboxes-from-pst-into-exchange-2007-using-powershell-cmdlets/ )

-ErrorAction and -ErrorVariable

Let me take a minute to tell you about 2 of my favorite things in Windows PowerShell:  -ErrorAction and –ErrorVariable

You may have heard me talk about being maniacal about doing a great job with error handling … this is one the cornerstones of our architecture.

Here is the background:  Cmdlets are implemented by subclassing a base class.  The engine reflects against this class looking for public properties that have a .net attribute on them identifying them as a PARAMETER.  Why is this a good idea?  Well think about it, the base class can also have public properties with the PARAMETER attribute.  And that’s exactly what we do.  We call these Common Parameters (because I failed to convince our writers that it was a noble and worthwhile task to teach the planet the meaning of the word “ubiquitous”).

You might be asking yourself – how would I find out more about common parameters?
Hmmm… so you want to “get help about common parameters”.  Hmmm, I wonder want a good way to express this idea in PowerShell would be ……
How about:

PS> get-help about_CommonParameters
TOPIC
Common Parameters

SHORT DESCRIPTION
Parameters that every cmdlet supports.

LONG DESCRIPTION
Windows PowerShell includes several common parameters that all
cmdlets support. This feature provides a consistent interface to
Windows PowerShell.

When a cmdlet supports a common parameter, the use of the parameter
does not cause an error. However, the parameter might not have any
effect in some cmdlets.

The common parameters are:

Parameter      Description
———      ————————————————–
Verbose        Boolean. Generates detailed information about the
operation, much like tracing or a transaction log.
This parameter is effective only in cmdlets that
generate verbose data.

Debug          Boolean. Generates programmer-level detail about the
operation. This parameter is effective only in cmdlets
that generate debug data.

ErrorAction    Enum. Determines how the cmdlet responds when an error
occurs. Values are: Continue [default], Stop,
SilentlyContinue, Inquire.

ErrorVariable  String. Specifies a variable that stores errors from
the command during processing. This variable is
populated in addition to $error.

OutVariable    String. Specifies a variable that stores output from
the command during processing.

OutBuffer      Int32. Determines the number of objects to buffer
before calling the next cmdlet in the pipeline.

In addition to the common parameters, there are two parameters that
cmdlets support if they change the system state.

Parameter     Description
———     ——————————————————-

WhatIf        Boolean. Explains what will happen if the command is
executed, without actually executing the command.

Confirm       Boolean. Prompts the user for permission before
performing any action that modifies the system.

SEE ALSO
For information about parameters, type:

help about_Parameter

You think it, you type it, you get it.  🙂

So back to -ErrorAction and -ErrorVariable.  These are implemented by the engine on behalf of the Cmdlet – the developer doesn’t have to do anything.  They just call WriteError() and we do the rest.

Here is the easiest way to show this working:

PS> Stop-Process 13,23
Stop-Process : Cannot find a process with the process identifier 13.
At line:1 char:13
+ Stop-Process  <<<< 13,23
Stop-Process : Cannot find a process with the process identifier 23.
At line:1 char:13
+ Stop-Process  <<<< 13,23

PS> Stop-Process 13,23 -ErrorAction Stop  # Only 1 error
Stop-Process : Command execution stopped because the shell variable “ErrorA
ctionPreference” is set to Stop: Cannot find a process with the process ide
ntifier 13.
At line:1 char:13
+ Stop-Process  <<<< 13,23 -ErrorAction Stop  # Only 1 error

PS> Stop-Process 13,23 -ErrorAction silentlycontinue  # No errors

PS> Stop-Process 13,23 -ErrorAction inquire  # ASK
Confirm
Cannot find a process with the process identifier 13.
[Y] Yes  [A] Yes to All  [H] Halt Command  [S] Suspend  [?] Help
(default is “Y”):h
Stop-Process : Command execution stopped because the user selected the Halt
option.
At line:1 char:13
+ Stop-Process  <<<< 13,23 -ErrorAction inquire  # ASK
PS>
PS>
PS> Stop-Process 13,23 -ErrorVariable a -ErrorAction SilentlyContinue

PS> $a[0]
Stop-Process : Cannot find a process with the process identifier 13.
At line:1 char:13
+ Stop-Process  <<<< 13,23 -ErrorVariable a -ErrorAction SilentlyContinue

PS> $a[0] |fl * -Force

Exception             : Microsoft.PowerShell.Commands.ProcessCommandExcepti
on: Cannot find a process with the process identifi
er 13.
TargetObject          : 13
CategoryInfo          : ObjectNotFound: (13:Int32) [Stop-Process], ProcessC
ommandException
FullyQualifiedErrorId : NoProcessFoundForGivenId,Microsoft.PowerShell.Comma
nds.StopProcessCommand
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo

PS> $a |ft TargetObject -force -auto
TargetObject
————
13
23

 

Now one thing that is not obvious to people is that you can specify a “+” in front of the variable name for ErrorVariable and we will ADD the errors to that variable.

PS> $err=@()
PS> stop-process 13 -ea silentlycontinue -ErrorVariable err
PS> $err.count
1

PS> stop-process 23 -ea silentlycontinue -ErrorVariable +err
PS> $err.count
2
PS> $err
Stop-Process : Cannot find a process with the process identifier 13.
At line:1 char:13
+ stop-process  <<<< 13 -ea silentlycontinue -ErrorVariable err
Stop-Process : Cannot find a process with the process identifier 23.
At line:1 char:13
+ stop-process  <<<< 23 -ea silentlycontinue -ErrorVariable +err

Lastly,  you don’t need to type out –ErrorAction or –ErrorVariable, we have defined parameter aliases for these so you can just type –EA and -EV

 

(source : http://blogs.msdn.com/b/powershell/archive/2006/11/03/erroraction-and-errorvariable.aspx)

Managing dedicated Rooms

Here are some commands to use to manage Dedicated Room mailboxes.

Dedicated Rooms can also be scheduled by some restricted people.

Getting delegates list :

$GetDelegates=(Get-MailboxCalendarSettings “$Room”).ResourceDelegates

Setting Delegates :

$Mbx=Get-Mailbox “$Room”
$Mbx|Set-MailboxCalendarSettings -ResourceDelegate $Delegates
$Delegates is an Array value

Remove a delegate :

$Mbx=Get-Mailbox “$Room”
$delDelegate <- SAM of the delegate to remove
$NewDelegates=($Mbx|
Get-ADPermission |
Where-Object {-not $_.isinherited} |
Where-Object {$_.user -match “^DOMAIN”}|
ForEach-Object {
If(($_.User.ToString().split(“/”)[1]) –ne $delDelegate){
$_.User.ToString().split(“/”)[1]
}
}
)
$Mbx|Set-MailboxCalendarSettings -ResourceDelegate $NewDelegates

Add a delegate :

$Mbx=Get-Mailbox “$Room”
$DelegateToAdd <- SAM of the delegate to add
$NewDelegates=($Mbx|
Get-ADPermission |
Where-Object {-not $_.isinherited} |
Where-Object {$_.user -match “^DOMAIN”}|
ForEach-Object {
If(($_.User.ToString().split(“/”)[1]) –ne $delDelegate){
$_.User.ToString().split(“/”)[1]
}
}
)
$NewDelegates += $DelegateToAdd
$Mbx|Set-MailboxCalendarSettings -ResourceDelegate $NewDelegates

Get a manager of a dedicated room :

$Mbx=Get-Mailbox “$Room”
$Manager=(get-user $Mbx).Manager

 Modify a Manager :

Function Remove_Old_Mgr ([string]$Upn, [string]$Nom, [string]$Responsible ) {
$domainResponsible=$RespDomain + ” + $Responsible
Remove-MailboxPermission -Identity $UPN `
-AccessRights FullAccess `
-User $Responsible `
-DomainController $Controller
Remove-ADPermission -Identity “$($Nom)” `
-AccessRights ReadProperty `
-User $DOMAINResponsible `
-DomainController $Controller
Remove-ADPermission -Identity “$($Nom)” `
-AccessRights WriteProperty `
-User $DOMAINResponsible `
-DomainController $Controller
}

Function Set_New_Mgr ([string]$Upn, [string]$Nom, [string]$Responsible) {
$DOMAINResponsible=$RespDomain + ” + $Responsible
Add-MailboxPermission -Identity $UPN `
-AccessRights FullAccess `
-User $Responsible `
-DomainController $Controller
Add-ADPermission -Identity “$($Nom)” `
-AccessRights ReadProperty `
-User $DOMAINResponsible `
-DomainController $Controller
Add-ADPermission -Identity “$($Nom)” `
-AccessRights WriteProperty `
-User $DOMAINResponsible `
-DomainController $Controller
}

$Mbx=Get-Mailbox “$Room”
remove_old_mgr $Mbx.UserPrincipalName $Mbx.Name $Manager
$Mbx | Set-User -Manager $NewManager
set_new_mgr $Mbx.UserPrincipalName $Mbx.Name $NewManager