Archive for the 'PowerShell' Category

Powershell 2.0 Script to Backup GPOs

 

A little while back I posted a Powershell 1.0 script to backup all the GPOs in a domain.  Now that Powershell 2.0 is available together with the Group Policy module it is much easier to script Group Policy tasks.  The attached script is basically a re-write of my previous script, but now using the Powershell 2.0 cmdlets. 

The script is intended for use with the Windows Task Scheduler.  For example, by backing up the GPOs to disk on a daily basis you have a simple method for restoring accidentally deleted (or badly modified) GPOs.  In my customers’ environments I combine this task with a scheduled full volume snapshot to disk, so that a number of days worth of backups are available.

 


#########################################################
#
# Name: BackupGPOsV2.ps1
# Author: Tony Murray
# Version: 1.0
# Date: 25/02/2010
# Comment: PowerShell 2.0 script to backup all
# GPOs within a domain
#
######################################################### 

 

# Import the modules that we need
import-module activedirectory
import-module grouppolicy 

# Specify the location for the backups
$BackupPath = "C:\Backup\GPO\" 

# Create the backup folder if it doesn’t exist
if(test-path -path $BackupPath)
{write-host “The folder” $BackupPath “already exists”}
else
{New-Item $BackupPath -type directory} 

 

# Remove any previous backups from the folder
##  Note: You will need to move the backups off to tape/disk
##  archive daily if you need access to older GPO versions
Remove-Item $BackupPath\* -Recurse -Force 

# Find out what domain this computer is in
$mydomain = get-ADDomain -current LocalComputer 

# Get all the GPOs in the specified domain
$AllDomGPOs = get-gpo -domain $mydomain.DNSRoot -all 

# Loop through the array
Foreach ($GPO in $AllDomGPOs)
{
    # Backup the GPO to the specified path
    backup-GPO $GPO.DisplayName -path $BackupPath
} 

#End 

Powershell one-liner for gathering mailbox stats

 

The Get-MailboxStatistics cmdlet is great for showing a range of detailed information about the mailboxes in your organisation.  Sometimes you need to pare down the information to just the really useful stuff (such as mailbox size, item count, etc.) and push it to a CSV file.  Here’s one that I find helpful:

 


get-exchangeserver | where-object {$_.IsMailboxServer -eq $true } | `

Get-MailboxStatistics | Sort-Object TotalItemSize -Descending | `

Select-Object DisplayName,@{label="TotalItemSize(MB)";`

expression={$_.TotalItemSize.Value.ToMB()}},`

ItemCount,ServerName,StorageGroupName,DatabaseName | `

export-csv c:\stats.csv –NoTypeInformation

How to Find Exchange Server 2007 Build Information

The other day I applied Update Rollup 1 for Exchange Server 2007 Service Pack 2 in my test lab and wanted to check that the update was successfully applied.  Being something of a Powershell fan I first tried the command shown below:

(get-exchangeserver MyE2K7Server).admindisplayversion

The output showed Version 8.2 (Build 176.2), which is the same as Exchange Server 2007 SP2 without the Update Rollup.  Next I look at the value using the Exchange Management Console (EMC), which showed me the same information.

Sp2

I even checked the registry under HKLM\SOFTWARE\Microsoft\Exchange\v8.0\<role> and the ConfiguredVersion value shows the same (8.2.176.2).

The only place I noticed the build number had been incremented was in the EMC under Help->About.

After some Googling I found the statement below from Microsoft’s Ananth Ramanathan

Successful installation of an update rollup should not be ascertained by the version number shown in the admin tools. The version number displayed by Exchange Management Console or other administrative mechanisms is obtained from the Exchange Server Object in Active Directory. If we update the Exchange Server Object in Active Directory to show a new version number for every rollup, it would require additional privileges for the account being used to install the rollup. Since many large customers have split level administrative model where the Exchange administrators do not have permissions to the Active Directory we do not update the Active Directory with an updated version number when the rollup is installed.

Another factor is that the rollup is no different than a Hotfix/Update for other products from Microsoft. So as an administrator you should do what you usually do for validating that the Hotfix is correctly installed/ In Windows Server 2003, you will need to go to Add//Remove programs in control panel and make sure the “Show Updates” checkbox is selected at the top. In Windows Server 2008, you will need to go to “View Installed Updates” in the Control Panel.

Ananth’s method is fine you want to look at one Exchange Server, but what if you want to list the build levels for all Exchange servers in your organisation?  Powershell to the rescue!  Here’s a script I put together to show the names, editions and build numbers for each Exchange server in the organisation.

#########################################################
#
# Name: GetExchangeBuild.ps1
# Author: Tony Murray
# Version: 1.0
# Date: 24/11/2009
# Comment: PowerShell script to list build info
# for each Exchange Server in the organisation
#
#########################################################

#Uncomment the line below if running from Powershell outside the EMS
#add-pssnapin Microsoft.Exchange.Management.Powershell.Admin

$exsrvs = (get-exchangeserver)
foreach ($exsrv in $exsrvs)
{
$version = (get-exchangeserver -identity $exsrv).admindisplayversion
$edition = (get-exchangeserver -identity $exsrv).edition
write-host “=====================================================”
write-host “Exchange Server: $exsrv”
write-host $version
write-host “Edition: $edition”
write-host “Installed Update Rollups:”
$baseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey(’LocalMachine’, $exsrv)
$regKey = “SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\461C2B4266EDEF444B864AD6D9E5B613\Patches\”
$baseKey = $baseKey.OpenSubKey($regKey)
$Updates = $baseKey.GetSubKeyNames()
ForEach($Update in $Updates)
{
$fullPath= $regKey + $Update
$UpdateKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey(’LocalMachine’, $exsrv)
$UpdateKey = $UpdateKey.OpenSubKey($fullPath)
$values = $UpdateKey.GetValueNames()
ForEach($value in $values)
{
if ($value -eq “DisplayName”)
{Write-host $UpdateKey.GetValue($value)}
}
}
write-host “=====================================================”
}

Let me know if you have any problems with the script, or if you can think of ways to improve it.

Tony