August 2010 - Posts

As you are probably aware, Exchange 2010 service pack 1 was released last week, on the Internet (a so-called RTW [release to web] by Microsoft) at the Microsoft Exchange Team Blog. The release posting was The Future of Exchange Starts Here: Exchange Server 2010 SP 1 Is Now Available.

In my opinion, SP1 represents Exchange 2010 as it "should have been" at its original release. You can finally control RBAC (Role Based Access Control) in the GUI, Retention Policies now work properly and can be controlled in the GUI, common DAG options are now available in GUI, themes are available in OWA; plus a large number of bug fixes and other improved feature content. You can read the article about What's New in Exchange 2010 SP1.

However, along with this has come some controversy. You cannot install Exchange 2010 SP1 without first installing a handful of hotfixes. This is a hard-block in the Exchange setup program, which means that if the hotfixes are not detected, the setup program will abort. The list of hotfixes are available in the article Exchange 2010 SP1 Prerequisites and if you don't have them installed, the Exchange setup program also informs you of this and tells you where to get them.

Now, this is a first for Exchange setup. In the past, Exchange may have required a particular service pack and/or OS version, but not specific hotfixes. The issue with hotfixes are, as I see it, three:

[1] They must be individually requested,

[2] There is confusion about which specific hotfix to get (you will always need the x64 version, and if you are running on Windows Server 2008 SP2 then you get the Vista version; if you are running on Windows Server 2008 R2, then you get the Windows 7 version), and

[3] Hotfixes are not fully regression tested and should "only be installed on computers experiencing this particular problem".

It is this last one that makes people stop and say "whoa!" But it shouldn't.

Microsoft has required this configuration. Microsoft supports this configuration. Don't make it an issue, because it isn't.

Hotfixes are not fully regression tested because they are designed to fix a specific issue in a specific module of a specific piece of software. It does not make sense to go through a full service-pack set of testing for a single fix. Also, Microsoft has been running millions of mailboxes on this codebase (in their Live@Edu environment) for quite some time, as well as over half-million TAP customer mailboxes. These fixes have been tested in production environments and Microsoft does support them.

In my opinion, Microsoft should require these hotfixes. If Microsoft is aware of a particular problem and a fix is available for that problem - then I believe they should require that fix. I don't want an Exchange service pack released with known issues that are going to affect the end-user customer stability of the service pack.

There is some question about why these fixes aren't available on WSUS or Microsoft Update; and the answer is simple: these are not security related fixes, they are not Exchange fixes, and they will not affect every single Microsoft server installation. However, they are known to affect Exchange and thus need to be installed on Exchange servers.

My only complaint about the process is the naming of the hotfixes. Installing a "Windows 7" hotfix on a "Server 2008 R2" computer makes sense to me - but it doesn't to the average system administrator. The same is true for installing a "Vista" hotfix on a "Server 2008 Service Pack 2" computer.

So...feel safe. You have the warm-and-fuzzy you want. Microsoft fully supports the deployment of these hotfixes on an Exchange server.

Until next time...

If there are things you would like to see written about, please let me know.

Posted by michael | with no comments

A common request is to get a list of all distribution groups and the members contained in that distribution group. The question came up on a mailing list I frequent today, and my initial response was a PowerShell "one-liner" (actually five lines, but all a single PowerShell statement).

The one-liner worked, but it had a couple of limitations: it wasn't very pretty (that is, the output was formatted poorly) and if there were than one user set to manage the distribution group, that would be reportedly incorrectly. It was also slower than it had to be.

Note: a distribution group may also be a security group. From an Exchange Server perspective, the important thing is whether the group is mail-enabled or not.

So, I took that five-liner, cleaned it up, fixed the ManagedBy reporting bug, and sped it up (by using an embedded pipeline to report on the members contained in a distribution group). That turned it into a 50+ line script (which includes 10 lines of comments!). As I said on the mailing list - you can generate quick results with PowerShell. That's good enough for most admins. But if you want it pretty and "production quality" then it's going to take a little more time.

You can take this report and pipe it to out-string in order to save the output to a disk file. Then you can inspect the file later, email it, copy-n-paste it, whatever you want.

Here is the script:

##
## Report-DistributionGroupsAndMembers.ps1
## v1.1

##
## Michael B. Smith
## http://TheEssentialExchange.com
## August, 2010
##
## Requires Exchange Management Shell
## Should work with either PowerShell v1 or v2
## Tested on both Exchange 2007 and Exchange 2010

##

function formatManager($formatstring, $manager)
{
	$formatstring -f $manager.Name, ($manager.Parent.ToString() + "/" + $manager.RDN.ToString().SubString(3))
}

Get-DistributionGroup -ResultSize Unlimited |% {
	$group = $_
	"Group Name & Identity: {0}, {1}" -f $group.Name, $group.Identity
	$managedBy = $group.ManagedBy
	if( $managedBy -is [Microsoft.Exchange.Data.Directory.ADObjectId] )
	{
		formatManager "Group manager: {0}, {1}" $managedBy
	}
	elseif( $managedBy.Count -gt 1 )
	{
		[bool]$first = $true
		foreach( $manager in $managedBy ) 
		{
			if( $first ) 
			{
				formatManager "Group managers: {0}, {1}" $manager
				$first = $false
			}
			else
			{
				formatManager "                {0}, {1}" $manager
			}
		}
	}
	elseif( $managedBy.Count -gt 0 )
	{
		formatManager "Group manager: {0}, {1}" $managedBy[0]
	}

	"Members:"
	Get-DistributionGroupMember -Identity $group.Identity -ResultSize Unlimited |% {
		foreach( $member in $_ )
		{
			"`t$($member.Name)"
		}
	}
	"---"
}

Until next time...

If there are things you would like to see written about, please let me know.

--Edit on August 20, 2010
The original script would not display ManagedBy on Exchange 2007 (I'm running Exchange 2010). This is because ManagedBy in Exchange 2010 always returns an array-type object (it can contain multiple users). In Exchange 2007, the ManagedBy value is always a singleton. The required changes to the script are in red.

Michael B.

Posted by michael | with no comments

On a mailing list recently, SBS author and PowerShell MVP Charlie Russel posted how he used PowerShell to check whether a given PowerShell session was elevated. He also used that information to change the background color of the session (elevated shells are dangerous things!).

I took Charlie's code and expanded it a bit and "made it mine". I often need to know whether I'm running as an administrator, a server operator, and/or a backup operator. This is because I write lots of Exchange PowerShell scripts (which often require server operator or local administrator privileges) and backup PowerShell scripts (which require the user running the script to be a backup operator). The same technique Charlie used can also be used to determine those things. The key element here is the IsInRole() method of System.Security.Principal.WindowsPrincipal. For detailed information about that .Net class, google/bing for System.Security.Principal.WindowsPrincipal.

The IsInRole() method operates against a WindowsIdentity object. This is obtained from the current process.

The script is pretty self-explanatory. It is designed to be dot-sourced so the functions can be used within your current script. I've also included Charlie's functionality for changing the background of an elevated shell session.

Without further ado....

##
## IsProtectedRole.ps1
##
## Contains functions for identifying protected roles the current user has tokens for.
##
## Intended for dot-sourcing.
##
## based on code from Charlie Russell (www.scribes.com).
##

$identity  = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object System.Security.Principal.WindowsPrincipal( $identity )

##
## Starting with Vista/Server2008, if UAC is enabled, then a user who has either direct
## or indirect membership in the BuiltIn\Administrators group is assigned not one but
## TWO security tokens. One of those tokens has the administrator privilege, and one
## does not. In order for you to have administrator privilege in PowerShell, you must
## start the PowerShell session from: Angel another elevated shell (either PowerShell or
## cmd.exe), or Beer elevate the session when you start the shell (i.e., "Run As Administrator").
##

function IsAdministrator
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::Administrator )
}

function IsUser
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::User )
}

function IsPowerUser
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::PowerUser )
}

function IsGuest
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::Guest )
}

function IsAccountOperator
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::AccountOperator )
}

function IsSystemOperator
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::SystemOperator )
}

function IsPrintOperator
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::PrintOperator )
}

function IsBackupOperator
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::BackupOperator )
}

function IsReplicator
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::Replicator )
}

function MarkAdministratorShell
{
	If (IsAdministrator)
	{
		$script:effectivename = "Administrator"
		$host.UI.RawUI.Backgroundcolor = "DarkRed"
		$host.UI.RawUI.Foregroundcolor = "White"
	}
	else
	{
		$script:effectivename = $identity.name
		$host.UI.RawUI.Backgroundcolor = "White"
		$host.UI.RawUI.Foregroundcolor = "DarkBlue"
	}

	clear-host
}

# write-host 'Administrator' (IsAdministrator)
# write-host 'User' (IsUser)
# write-host 'PowerUser' (IsPowerUser)
# write-host 'Guest' (IsGuest)
# write-host 'AccountOperator' (IsAccountOperator)
# write-host 'SystemOperator' (IsSystemOperator)
# write-host 'PrintOperator' (IsPrintOperator)
# write-host 'BackupOperator' (IsBackupOperator)
# write-host 'Replicator' (IsReplicator)

Until next time...

If there are things you would like to see written about, please let me know.

Posted by michael | with no comments
Filed under: ,

I recently provided input to Marriette Knap, a Small Business Server MVP, in a blog posting of her's called How to install BlackBerry Enterprise Server Express on a SBS 2008.

I believe that this posting is the best resource for installing BES/X available right now; whether you are installing BES/X on an Exchange Server, on a Domain Controller/Group Catalog server, or on a standalone server.

If you are installing BES/X on a DC/GC or directly on an Exchange server, I highly recommend you follow the instructions contained in that blog post.

Until next time...

If there are things you would like to see written about, please let me know.

Posted by michael | with no comments
Filed under: , ,