Zoho Banner September 2011

Archive for the ‘Windows Server 2008 R2’ Category

 

On and off over the past couple of days I’ve been trialling one of Quest’s cloud services – OnDemand Recovery for AD.  The other service that Quest currently offers in the Microsoft space is Log Management, which allows the collection, storage and forensic analysis of Windows Event Log data. 

For those of you familiar with Quest’s Recovery Manager for AD, the OnDemand version has similarities, but quite a few differences too.  You can find a useful table comparing the feature sets of the two products here.

The basic concept behind OnDemand Recovery for AD is that by subscribing to a cloud service to support the recovery of AD objects you avoid having to deploy and manage infrastructure components within your environment.  At USD0.60 per user per month the service is likely to attract SMB customers, but is unlikely to tempt large enterprises that typically have existing, comprehensive backup and recovery solutions.

The first thing that popped into my head when I looked at the feature set was why anyone would subscribe to the service when Windows Server 2008 R2 AD includes the AD Recycle Bin (for free).  The Recycle Bin combined with the “Protection from accidental deletion” feature (introduced in Windows Server 2008 AD) can provide a reasonably comprehensive toolset for protection and deleted object recovery.  After spending some time looking at Quest’s product it struck me that OnDemand Recovery for AD has two significant advantages over the native Microsoft toolset:

  1. Ease of use.  The OnDemand web interface is very straightforward to set up and operate.  A child could do it.  The same cannot be said of the AD Recycle Bin, which requires that you know your way around Powershell AD cmdlets.
  2. Ability to restore objects to a previous state.  The AD Recycle Bin is great for restoring deleted objects, but doesn’t let you revert an existing, non-deleted object back to a previous state.  For example, let’s say you run a script that accidentally changes the telephoneNumber attribute of 5000 users to “911”.  In this scenario you can’t use the AD Recycle Bin to change the numbers back because the objects have been modified, not deleted.  You would typically need to go through the process of an authoritative restore of those objects from backup – a time consuming task that carries an element of risk.  With OnDemand Recovery for AD you could have those 5000 user objects reverted to their previous state within a couple of minutes.  I have included screenshots below to illustrate just how simple this is.

From your OnDemand Recovery for AD home page select “Restore”

rmadod0a

Choose the backup that contains the content that you would like to revert to.

rmadod1

The OnDemand software then compares the current state of AD objects with those in the backup set and then displays any differences.

rmadod2

In this example, two objects with differences are detected.  One is a modification (update) and the other is a deletion.  In this example, I selected the modified object (Autumn Metzler).

rmadod3a

After clicking Finish you see the restore operation in progress.

rmadod4

And that’s it! Ok, in this example I only worked with one object, but the principle is the same for multiple objects and the OnDemand product allows you to multi-select objects that you want to restore.

On balance I think Quest’s OnDemand Recovery for AD service is going to be a good choice for SMBs that are looking for a simple and easy-to-use product for quick AD object recovery.

I’ve only scratched the surface of the product’s capabilities here.  If you want to learn more I recommend giving the product a trial (very simple to setup) and perusing the following document:

Protect Your Data with Quest OnDemand Recovery for Active Directory

A couple of weeks ago I blogged about using Quest’s ActiveRoles Quick Connect Express for Exchange 2010 Global Address List synchronisation (GAL Sync).  Since then I’ve written a step-by-step guide which will hopefully help others who want to use this very useful freeware utility.  You can download the guide (pdf format) here:

GAL Sync with ActiveRoles Quick Connect Express – Step-by-Step Guide v1

I have also updated the Powershell script that exposes the provisioned Contact objects in the target GAL.  You can download the script here:

ConfigureContacts.ps1

If you have any feedback on the guide please post a comment here or contact me directly (tony@activedir.org)

Many moons ago I provided a CSV file containing 200 sample AD user accounts together with instructions on how to use CSVDE to import the accounts into AD. I often use these sample accounts in lab environments and for presentations. I thought it would be fun to write a small powershell script to read the same CSV input file and create the accounts using the AD cmdlets from Windows Server 2008 R2.

You can download the CSV file here.

And here’s the Powershell script….

#########################################################
#
# Name: BulkCreate200UsersFromCSV.ps1
# Author: Tony Murray
# Version: 1.0
# Date: 29/12/2010
# Comment: PowerShell 2.0 script to
# bulk create users from csv file
#
#########################################################

# Function to test existence of AD object
function Test-XADObject() {
   [CmdletBinding(ConfirmImpact="Low")]
   Param (
      [Parameter(Mandatory=$true,
                 Position=0,
                 ValueFromPipeline=$true,
                 HelpMessage="Identity of the AD object to verify if exists or not."
                )]
      [Object] $Identity
   )
   trap [Exception] {
      return $false
   }
   $auxObject = Get-ADObject -Identity $Identity
   return $true
}


# Import the Active Directory Powershell Module
Import-Module ActiveDirectory -ErrorAction SilentlyContinue

# Specify the target OU for new users
$targetOU = "OU=Standard Users,OU=_North,DC=North,DC=com"

# Find the current domain info
$domdns = (Get-ADDomain).dnsroot # for UPN generation

# Specify the folder and CSV file to use
$impfile = "C:\util\CSV\200Users.csv"

# Check if the target OU is valid
$validOU = Test-XADObject $targetOU
If (!$validOU)
{ 
 write-host "Error: Specified OU for new users does not exist - exiting...."
 exit
} 

# Set the password for all new users
$password = read-host "Enter password" -assecurestring
    
# Parse the import file and action each line
$users = Import-CSV $impFile
foreach ($user in $users)
{
$samname = $user.samaccountname
$dplname = $user.displayname
$givname = $user.givenname
$surname = $user.sn
$upname = "$samname" + "@" +"$domdns"
New-ADUser –Name $dplname –SamAccountName $samname –DisplayName $dplname `
-givenname $givname -surname $surname -userprincipalname $upname `
-Path $targetou –Enabled $true –ChangePasswordAtLogon $true `
-AccountPassword $password
}


#All done

You can download the script here.

Quest has just released a freeware product called Quick Connect Express for Active Directory. If you’re looking for something that fills the gap left by the (now pensionable) Microsoft Identity Integration Feature Pack, then this may well be it.  I’ve spent the last day looking at the product’s capabilities for running Exchange 2010 Global Address List synchronisation and I have to say I’ve very impressed.  Aside from the price tag ($0.00 suits the pocket of most), the best thing about QQCE is that it’s really easy to set up and configure.

At the time of writing the download link points to the wrong version of Quick Connect.  I only worked this out when the installer prompted me for a connection to the ActiveRoles Server Administration Service (something not used with the Express version).  I’m sure Quest will sort this out soon, but in the meantime, you can obtain the correct version by registering with the Quest Support web site and downloading the software and associated documentation from there.  You should end up with the following two files:

  • Quest_QuickConnectSyncEngineStandaloneModex64_470.msi (this is the 64-bit version – a 32-bit version is also available)
  • QuickConnectStandaloneMode_4.7_AdminGuide.pdf

Optionally, you can also download the Quick Connect Powershell provider:

  • Quest_QuickConnectManagementShellStandaloneModex64_470.msi

I chose to install the software on a Windows Server 2008 R2 Standard Edition machine together with SQL Server 2008 R2.  QQCE uses SQL databases to store the synchronisation data, but SQL Server doesn’t need to be on the same machine.

If I have time I’ll work on a step-by-step guide for GAL Sync using QQCE, but in the meantime here are some of the configuration details I used in my lab. ***Update Jan 2011 – step-by-step guide now available***

My first forest (ad.contoso.com) runs Windows Server 2008 R2 functional level and has Exchange 2010 SP1 RU2.  The second forest (ad.fabrikam.com) has the same versions.  I joined the server running QQCE to the CONTOSOE domain, but it could equally have been joined to the FABRIKAM domain.  I then configured GAL Sync in the direction CONTOSO –> FABRIKAM.  In other words, I had users in CONTOSO that I wanted to appears as Contacts in the FABRIKAM Global Address List.  Of course it is also possible to perform two-way GAL sync with the tool – I just didn’t take it that far.

Once you have completed the installation, the first thing to do is select one of the two domains as the “Managed Domain” for QQCE.  For the purposes of GAL sync the selection is arbitrary.  You then configure the second domain as a “Connected System”.

qqc_connections1

You then need to set up the workflow.  I chose to configure three separate workflow steps for the GAL Sync (Provisioning, Update and Deprovisioning).  This ensures that any creation, modification or deletion of mailbox-enabled users in CONTOSO are reflected in FABRIKAM.

The provisioning aspect of the workflow requires the most work.  The tool can easily be configured to provision Contact objects in the target, but a custom post-sync Powershell script is required to ensure the contacts appear in the GAL.

qqc_provisoning1

My script (which you can download here) invokes a remote Powershell session against a FABRIKAM Exchange server and uses the Get-Contact and Set-Contact cmdlets to ensure the attributes required for GAL visibility are stamped on the Contact objects.

qqc_provisoning_script

When configuring the Source information, I specified the OU containing the mailbox-enabled User objects and identified them using the homeMDB attribute.  If the homeMDB attribute is present on a User object you can assume it is mailbox-enabled.

qqc_provisoning2

The Target window in the configuration wizard allows you to specify what object type to create (Contact in my case).  You also specify the rule(s) for generating the object name. I chose the source User object’s Display Name attribute to generate the name (cn) for the corresponding Contact object.

qqc_provisoning3

Finally, you specify which attributes on the source object should be populated on the target object during provisioning.  My choices are fairly obvious, but note in particular that I used the mail attribute from the source to create the Contact object’s targetAddress attribute.  The targetAddress attribute is important for Contacts as it is the one Exchange uses for routing purposes.

qqc_provisoning4

The Update and Deprovisioning steps are much simpler to configure, so I won’t show them here.

Once the workflow setup is compete you can configure them to run according to a schedule that you specify.  Once per day is probably sufficient in most cases.

The remaining task is to create a mapping rule for the User->Contact relationship.  This is required to allow the Update and Deprovisioning workflow steps to match the correct target object based on changes or deletions in the source domain.

qqc_workflow1

And that’s it really.  You can pretty much have the whole thing up and running in an hour or less!

Much kudos to Quest for pushing this out as a free tool.  Of course GAL Synchronisation is not the sole purpose of the tool, but I suspect it’ll be the major drawcard for many organisations given its usefulness in migration and coexistence scenarios.  The major alternatives for GAL Sync with Exchange 2010 are ILM/FIM and SimplSync, both of which cost money and, in the case of FIM at least, require a great deal more configuration effort.

Tony

 

If you’ve been working with Exchange 2010 Service Pack 1 you will know that there are several pre-requisites to download and install. Once downloaded you end up with a bunch of *.msu (Windows Update) files.  If, like me, you have to install them on several servers and don’t like the idea of having to double-click to install them via the UI you look for ways to simplify the process.  Powershell struck me as the obvious solution, but I couldn’t find any cmdlets that manage Windows Updates.  There are some examples, such as this from James O’Neill, but which are somewhat too elaborate for what I wanted to do.  In the end I wrote a small script (below) that calls wusa.exe to install the updates.  Not the prettiest method.  Hopefully Microsoft will provide set of cmdlets to manage Windows Updates in the next version of Windows.

#########################################################
#
# Name: InstallWindowsUpdates.ps1
# Author: Tony Murray
# Version: 1.0
# Date: 16/11/2010
# Comment: PowerShell script to install 
# Windows Update files
#
#########################################################

# Specify the location of the *.msu files
$updatedir = "C:\E2010 SP1 Prereqs\"
###

$files = Get-ChildItem $updatedir -Recurse
$msus = $files | ? {$_.extension -eq ".msu"}

foreach ($msu in $msus)
{
    write-host "Installing update $msu ..."
    $fullname = $msu.fullname
    # Need to wrap in quotes as folder path may contain spaces
    $fullname = "`"" + $fullname + "`""
    # Specify the command line parameters for wusa.exe
    $parameters = $fullname + " /quiet /norestart"
    # Start wusa.exe and pass in the parameters
    $install = [System.Diagnostics.Process]::Start( "wusa",$parameters )
    $install.WaitForExit()
    write-host "Finished installing $msu"
}

write-host "Restarting Computer"
#Restart-Computer

If someone has a better method for doing this, please let me know.

I was recently involved in a task to consolidate an OU structure.  Part of this involved moving user objects from one OU to another and re-linking GPOs that were linked to the old OU to the new OU.  There were a large number of links and I didn’t fancy adding them manually, so I spent a little time writing a PoSH script to do it.   Enjoy!  As always, please post a comment if know of a better/different way to do the same thing.

######################################################### 
# 
# Name: CopyGPOLinks.ps1 
# Author: Tony Murray 
# Version: 1.0 
# Date: 26/10/2010 
# Comment: PowerShell 2.0 script to copy GPO links from 
# one OU to another 
# 
######################################################### 

# Import the Group Policy module 
Import-Module GroupPolicy 

### Set global variables 

# Source for GPO links 
$Source = "OU=Sales,DC=contoso,DC=com" 
# Target where we want to set the new links 
$Target = "OU=Logistics,DC=contoso,DC=com" 

### Finished setting global variables 

# Get the linked GPOs 
$linked = (Get-GPInheritance -Target $source).gpolinks 

# Loop through each GPO and link it to the target 
foreach ($link in $linked) 
{ 
    $guid = $link.GPOId 
    $order = $link.Order 
    $enabled = $link.Enabled 
    if ($enabled) 
    { 
        $enabled = "Yes" 
    } 
    else 
    { 
        $enabled = "No" 
    } 
    # Create the link on the target 
    New-GPLink -Guid $guid -Target $Target -LinkEnabled $enabled -confirm:$false 
    # Set the link order on the target 
    Set-GPLink -Guid $guid -Target $Target -Order $order -confirm:$false 
}

Tony

In a migration scenario it is sometimes useful to have a security and/or distribution Active Directory group in the target domain where the membership is comprised of migrated user objects.  Here’s a Powershell 2.0 script that I put together that populates the membership of a group based on a specific sIDHistory value.  It can be run as a one-off after the migration or can be invoked via a scheduled task to keep up to date during a migration.

The script also creates a new event log source and then writes the logging information to the application event log on the machine from which it is run.  This is not essential to the script, so scrub it out if you want to. 

You can download a copy of the script here: sidhistorybasedgroupmembership.txt

######################################################### 
# 
# Name: SIDHistoryBasedGroupMembership.ps1 
# Author: Tony Murray 
# Version: 1.0 
# Date: 11/07/2010 
# Comment: PowerShell 2.0 script to 
# populate group membership based on sIDHistory values 
# 
#########################################################  

#Import the Active Directory Powershell Module 
Import-Module ActiveDirectory -ErrorAction SilentlyContinue   

#Create a new Event log source for the script (only needs to be run once) 
New-EventLog -logName Application -Source "Legacy Users Group Management" ` 
-ErrorAction SilentlyContinue   

$SearchBase = "OU=User Objects,DC=fabrikam,DC=local" 
$OUArr = Get-ADUser -LDAPFilter "(samaccounttype=805306368)" ` 
-SearchBase $SearchBase -SearchScope SubTree   

# Now we need the domain security identifier or at least a portion of it 
$DomSID = "S-1-5-21-1584567894-2535104369-4141123456"   

$Group = "Legacy Users" 
$MbrArr = get-adgroupmember -identity $Group   

# Loop through the Users found beneach the OU tree 
# and check to see if the user is already 
# a member of the group. If so, do nothing. 
# If not, then add the user as a member. 
Foreach ($User in $OUArr) 
{ 
    $object = [ADSI]"LDAP://$User" 
    $objectsidh = $object.sIDHistory.value 
    If (!$objectsidh) 
    { 
        # write-host "sIDHistory is blank" 
    } 
    Else 
    { 
        $objectsidh = $Object.getex(“sidhistory”) 
        trap 
            { 
            #write-host "Error: $_" 
            continue 
            } 
        foreach($sid in $objectSidh) 
        { 
            $sidh = new-object System.Security.Principal.SecurityIdentifier $sid,0 
            if ($sidh -Match $DomSID) 
            { 
                if ($MbrArr -Match $User.distinguishedName) 
                { 
                    #The user is already member - do nothing 
                } 
                else 
                { 
                    # We need to add the user as a member 
                    write-eventlog -logname Application ` 
                    -source "Legacy Users Group Management" ` 
                    -eventID 3001 -entrytype Information -message "$User added to $Group" 
                    Add-ADGroupMember -Identity $Group -Members $User 
                } 
            } 
            else 
            { 
                # No match with sidHistory - do nothing 
            } 
        } 
    } 
}

The other day I had to uninstall Exchange 2010 from a server with the CAS and Hub Transport roles.  It all went well until the point where it was uninstalling the Hub Transport role.  The uninstall then ground to a halt with the following error:

Log Name:      Application
Source:        MSExchange Configuration Cmdlet – Management Console
Date:          20/05/2010 4:11:01 p.m.
Event ID:      4
Task Category: General
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      HUBCAS1.contoso.com
Description:
(PID 6920, Thread 31) Task Uninstall-MsiPackage writing error when processing record of index 0. Error: Microsoft.Exchange.Configuration.Tasks.TaskException: Couldn’t open package ‘D:\Program Files\Microsoft\Exchange Server\V14\Mailbox\MSFTE.MSI’. Another version of this product is already installed. Installation of this version cannot continue. To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel. Error code is 1638. —> System.ComponentModel.Win32Exception: Another version of this product is already installed. Installation of this version cannot continue. To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel
   — End of inner exception stack trace —
   at Microsoft.Exchange.Management.Deployment.MsiUtility.GetProductCode(String packagePath)
   at Microsoft.Exchange.Management.Deployment.MsiUtility.IsInstalled(String packagePath)
   at Microsoft.Exchange.Management.Deployment.UninstallMsi.InternalValidate()

After scratching my head for a few minutes, I uninstalled Update Rollup 3 for Exchange Server 2010 and then re-tried the uninstall for Exchange.  It went through perfectly. 

I hadn’t realised it was necessary to remove any Update Rollups before uninstalling Exchange, but it it seems it is required in this case.

Some time ago I blogged about the Acctinfo2.dll tool and how unfortunate it was that a 64-bit version was not available.  Well, the good news is that you can now download a 64-bit version from here:

 Acctinfo2_64bit.zip

I have tested the DLL on both Windows Server 2008 and Windows Server 2008 R2 and it seems to work well.  However, please note this version is completely unsupported!  Download at use entirely at your own risk.

Tony

You receive the following message when installing Update Rollup 3 for Exchange Server 2010:

“Setup Wizard for Update Rollup 3 for Exchange Server 2010 (KB981401) ended prematurely because of an error. Your system has not been modified. To install this program at a later time, please run the installation again.”

exchange-2010-ru3-error.JPG

In my case this turned out to to be a User Account Control (UAC) gotcha.  Basically, I didn’t launch the *.msp file using “Run as Administrator”.  Interestingly, the error is misleading in that it does modify the system.  If you look at the installed updates on the system the Update Rollup appears as being installed.  In other words it is partly installed.

exchange-2010-ru3-error-2.JPG

The steps to resolve the issue are:

1. Go to Control Panel, Programs, Programs and Features, Installed Updates.  Highlight the update and then click Uninstall.

2. Open a CMD prompt using right-click “Run as Administrator”.  Browse to the folder where the file is located and launch the file named Exchange2010-KB981401-x64-en.msp.

One of these days I’m really going to get the hang of UAC :-) . Until I do, it would be really nice if the Microsoft product teams could provide more helpful error messages for UAC failures.