DCSIMG
January 2010 - Posts - Shay Levy

Shay Levy

If you repeat it, PowerShell it!

January 2010 - Posts

Webinar: Using PowerShell with Microsoft Online Services

Source: Microsoft Online Services Team Blog

Join Jenna Lyday (Microsoft Online Services PM responsible for e-mail Migration) on Thursday, 1/28/2010 for the third webinar in our migration series. In this webinar, Jenna will demonstrate how to use Windows PowerShell commands to:

- Provision and activate users
- Perform a simple migration from Hosted Exchange to Exchange Online
- Grant a user Full Mailbox Access permissions on another user's mailbox

If you like managing your environment from the command line, or scripting common administrative tasks, don’t miss this week’s webinar.

Date: Thursday, January 28th
Start time: 11: AM Pacific Standard Time (UTC – 8 hrs)
Duration: 1 hour

Click here to register for this webinar.

Click here to view the recording of this webinar. The PowerPoint slides are available here.

 

Utility to create a numeric range Regular Expression

Have you ever needed a regular expression to match a numeric range? If so, check Regex_For_Range. This is definitely one of the tools you’d want to add to your Regular Expression toolbox!

 

PowerShell Localized Online help

Windows PowerShell online help content is now available in Chinese (simplified and traditional), German, Italian, Korean, Portuguese (Brazil), and Russian. Spanish, French, and Japanese are soon to follow.

http://technet.microsoft.com/zh-cn/library/bb978526.aspx
http://technet.microsoft.com/zh-tw/library/bb978526.aspx
http://technet.microsoft.com/de-de/library/bb978526.aspx
http://technet.microsoft.com/it-it/library/bb978526.aspx
http://technet.microsoft.com/ko-kr/library/bb978526.aspx
http://technet.microsoft.com/pt-br/library/bb978526.aspx
http://technet.microsoft.com/ru-ru/library/bb978526.aspx

How to modify email addresses with PowerShell 2.0

One of the most asked question across many PowerShell forums, by Exchange administrators, is how to modify email addresses for mailbox users. The most common used code to add new email address in Exchange 2007 is:

PS > $mbx = Get-Mailbox shay

PS > $mbx.EmailAddresses += “newAddress@domain.com”
PS > Set-Mailbox -Identity $mbx –EmailAddresses $mbx.EmailAddresses


With Windows PowerShell 2.0 and Exchange 2007 (and above, sorry guys no 2003 ) we can use the Update-List cmdlet to add,remove or replace email addresses in a middle of a pipeline.

PS > Get-Mailbox shay | Select-Object -ExpandProperty EmailAddresses | `
Where-Object {$_.PrefixString -eq 'smtp'} SmtpAddress : shay@domain.com AddressString : shay@domain.com ProxyAddressString : SMTP:shay@domain.com Prefix : SMTP IsPrimaryAddress : True PrefixString : SMTP

 

We see that my mailbox has only one email address. Lets try to add two more addresses and then get the email addresses collection back:

PS > Get-Mailbox shay | `
Update-List -Property EmailAddresses -Add ScriptFanatic@domain.com,ShayL@domain.com | `
Set-Mailbox


PS > Get-Mailbox shay | Select-Object -ExpandProperty EmailAddresses | `
Where-Object {$_.PrefixString -eq 'smtp'} SmtpAddress : ShayL@domain.com AddressString : ShayL@domain.com ProxyAddressString : smtp:ShayL@domain.com Prefix : SMTP IsPrimaryAddress : False PrefixString : smtp SmtpAddress : ScriptFanatic@domain.com AddressString : ScriptFanatic@domain.com ProxyAddressString : smtp:ScriptFanatic@domain.com Prefix : SMTP IsPrimaryAddress : False PrefixString : smtp SmtpAddress : shay@domain.com AddressString : shay@domain.com ProxyAddressString : SMTP:shay@domain.com Prefix : SMTP IsPrimaryAddress : True PrefixString : SMTP

 

UPDATE [11/22/2010]: The method described below no longer works in Exchange 2010 and Exchange 2007 SP2. Check this post for more information.

Notice that the primary email address is indicated by the ProxyAddressString property (True) and the ProxyAddressString property which starts the with an uppercased prefix of ‘SMTP:’ . To remove email addresse(s) we use the –Remove parameter:

PS > Get-Mailbox shay | ` 
     Update-List -Property EmailAddresses –Remove ScriptFanatic@domain.com,ShayL@domain.com | `
     Set-Mailbox

 

 

The Add and Remove parameters can be used together in a pipeline, however we cannot remove the primary address:

PS > Get-Mailbox shay | `
Update-List -Property EmailAddresses -Remove shay@domain.com | Set-Mailbox Update-List : Cannot remove the primary SMTP address 'shay@domain.com'.
Please promote another valid SMTP address before removing this one.

 

But we can set a new email address as the primary address (and remove the old one later), just add the ‘SMTP:’ prefix.

PS > Get-Mailbox shay | Update-List -Property EmailAddresses -Add "SMTP:PSFanatic@domain.com" | Set-Mailbox

 

From the Update-List cmdlet help description:

“This cmdlet works only when the property that is being updated supports the IList interface that Update-List uses. Also, any Set-* cmdlets that accept an update must support the IList interface. The core cmdlets that are installed with Windows PowerShell do not support this interface. To determine whether a cmdlet supports Update-List, see the cmdlet Help topic.”

 

So, what other properties support the IList interface? With the following command you can get a list of mailbox properties that can be modified with Update-List.

PS > $mbx = Get-Mailbox shay 
PS > $mbx.GetType().GetProperties() | `
Where-Object {$_.PropertyType.GetInterface("System.Collections.IList",$true)} | `
Select-Object Name Name ---- Languages ProtocolSettings ResourceCustom Extensions AcceptMessagesOnlyFrom AcceptMessagesOnlyFromDLMembers AddressListMembership EmailAddresses GrantSendOnBehalfTo PoliciesIncluded PoliciesExcluded RejectMessagesFrom RejectMessagesFromDLMembers UMDtmfMap ObjectClass

 

Finally, there is also a –Replace parameter we can use to replace all existing email addresses with new ones. For more information see the code examples for Update-List.

QuickTip - One-liners to get WinRM port numbers

With PowerShell 2.0 the default Windows Remote Management (WinRM) port numbers has changed from 80/443 (HTTP/HTTPS) to 5985/5986. One reason for changing the ports was a collision with internet servers which used the same ports. These ports are configured when you enable remoting in PowerShell 2.0, typically by using the Enable-PSRemoting cmdlet.

So, if you need a quick reminder about the port numbers WinRM uses for its listeners…


PS > Get-ChildItem WSMan:\localhost\Service\DefaultPorts | Format-Table -AutoSize Name,Value

Name  Value
----  -----
HTTP  5985
HTTPS 5986


PS > Get-ChildItem WSMan:\localhost\Client\DefaultPorts  | Format-Table -AutoSize Name,Value

Name  Value
----  -----
HTTP  5985
HTTPS 5986


Note: To run these commands in Windows Vista, Windows Server 2008, and later versions of Windows, you must start Windows PowerShell with the "Run as administrator" option.

PowerShell ISE on Windows Server 2008 R2


As you probably know PowerShell 2.0 is installed by default on Windows 7 and Windows Server 2008 R2PowerShell 2.0 shipped with a new feature called Windows PowerShell Integrated Scripting Environment (ISE), A graphical user interface code editor. In PowerShell 2.0 you can launch ISE simply by executing ‘ise’ in the console (built-in Alias) or by clicking on its shortcut(s) in the programs menu.

However, on Windows Server 2008 you won’t be able to find it:

 

If you open PowerShell and type ‘ise’ you’ll get an error:

 

So, where exactly is it? ISE is shipped as a Windows Feature. You need to load the Server Manager module and add it with the Add-WindowsFeature cmdlet. Once the feature is added the ‘ise’ Alias will be available and new shortcuts will be placed in the programs folder.

ise1

Module manifest gotcha

Module authors can use a manifest file for their modules (although this is not required). A manifest file is a .psd1 file that contains a hash table. The keys and values in the hash table describe the contents and attributes of the module, define the prerequisites, and determine how the components are processed. How do you know all the hash table keys? You don’t have to. PowerShell can create the file for you with the New-ModuleManifest cmdlet.

New-ModuleManifest creates a new module manifest (.psd1) file, populates its values, and saves the manifest file in a specified path. You can further edit the file and change the values simply by opening it in your favorite text editor. To verify that your manifest file is valid use the Test-ModuleManifest cmdlet.

OK, now to the gotcha. Here’s a snippet from PSRemoteRegistry manifest file:

# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '2.0'

# Minimum version of the Windows PowerShell host required by this module
PowerShellHostVersion = '2.0'
 

Modules were introduced in PowerShell 2.0 so it was natural to set the value of ‘PowerShellVersion’ to 2.0. I assumed the same for ‘PowerShellHostVersion’ which proved to be wrong. Why?

When you load the PSRemoteRegistry module in PowerShell everything is working great. PowerShell’s version and Host version are set to 2.0:

PS > $host.Version

Major  Minor  Build  Revision
-----  -----  -----  --------
2      0      -1     -1


PS > $PSVersionTable

Name                           Value
----                           -----
CLRVersion                     2.0.50727.4927
BuildVersion                   6.1.7600.16385
PSVersion                      2.0
WSManStackVersion              2.0
PSCompatibleVersions           {1.0, 2.0}
SerializationVersion           1.1.0.1
PSRemotingProtocolVersion      2.1


BUT,
this is not the case with many PowerShell IDE’s. For example, both of the most popular PowerShell editors, PowerGUI and PowerShell Plus, host versions are not 2.0. These editors use a custom host and the developers can define whatever value they want for the version. If you try to load PSRemoteRegistry in one of these editors you’ll get a similar error to this:

The current PowerShell host is: 'PowerShellPlus Host' (version 1.0.0.0). 
The module '...\PSRemoteRegistry.psd1' requires a minimum PowerShell host version of '2.0' to execute.

I would like to thank @jkavanagh58 for reporting the issue!

There are many PowerShell editors out there and you can’t know for sure what host version each one uses, you do though, want your module to load in whatever editor the user uses. To be on the safe side, do not set a value for ‘PowerShellHostVersion’.

UPDATE (01/25/2010), Make sure you read the follow-up post from the PowerShell Team blog.

Remote Registry PowerShell Module

 

PSRemoteRegistry

About two years ago I wrote a Stand alone registry functions library to help managing Windows Registry on local or remote computers. Now that PowerShell 2.0 has released, I’ve taken the time to convert the library to Advanced Functions and now they are part of a PowerShell module.

The big improvement in the functions, beside the richness of PowerShell 2.0 features used in the module (support for Common Parameters, Comment Based Help and declaring a function that acts similar to a compiled cmdlet), is that now the functions can be used together in a pipeline. All functions are documented so you can get help (code examples etc) for any function with Get-Help.

The project, PSRemoteRegistry, is released on CodePlex. Here’s a list of the functions:

Get-RegBinary
Get-RegDefault
Get-RegDWord
Get-RegExpandString
Get-RegKey
Get-RegMultiString
Get-RegQWord
Get-RegString
Get-RegValue
New-RegKey
Remove-RegKey
Remove-RegValue
Set-RegBinary
Set-RegDefault
Set-RegDWord
Set-RegExpandString
Set-RegMultiString
Set-RegQWord
Set-RegString
Test-RegKey
Test-RegValue

I’d love to hear your comments, suggestions, bugs (if you find any), please report them on the project’s Discussions page or in the comments box below.