TechnoGist

gist (jst)# The central idea; the essence…

Archive for the ‘Exchange2003’ tag

PoshBoard – Powershell and Silverlight Web Portal

with one comment

I have started to look at performance and charge back visualization options for my environment. The final result would be a web portal/dashboard providing visual data for my peers and management. I have been following a project on “CodePlex” called “PoshBoard” by Antoine Habert.

The author Antoine Habert describes it as a,

“PowerShell Dashboard is a modular IT web portal based onPowerShell and Silverlight controls”

I will be starting to look at “PoshBoard” and will be posting my progress, I am really impressed with this project.

Links:

Site: http://www.poshboard.com/
Author “Antoine Habert” Blog: http://www.devinfra.blogspot.com/

Hope this helps.

All information is provided on an AS-IS basis, with no warranties and confers no rights.

Written by Paul Brice

May 12th, 2010 at 11:31 am

AD and Kerberos Token Bloat – Analyzing Group Nesting

with one comment

How To: Analyze Nested AD Groups.

I am working on a Kerberos Token size issue (Token Bloat) and need to accurately depict a groups nested members for token size analysis and remediation.

Brief Token Bloat Explanation:

Token Bloat is where due to several factors including deep group nesting the Kerberos token utilized in AD for resource authentication bloats towards the set limit or even beyond. This can cause larger logon times to resources and even issues in applications like Exchange 2003 that can only exist on a 32Bit OS.

I came across this article on the “Microsoft Active Directory Group PowerShell” blog, it has a great script for analysing nested group memberships. Unfortunately to use the PowerShell script you need to be running Windows 2008 servers for the Active Directory cmdlets to be available. The environment that I required the script for was not W2008 so I converted the script to use the Quest cmdlets available with the Quest Active Roles Management PSSnapIn.

You will need to have these installed before using this script.

The script originally written by the MS AD PowerShell team, provides a visual tree view of the groups and their nested levels, a ‘MaxNestingLevel’ value and a ‘NestedGroupMembershipCount’.

Example:

PS C:\> Get-QADGroupNesting.ps1 group-name

Or

PS C:\> Get-QADGroupNesting.ps1 group-name -ShowTree

The above example not only displays group statistics it also plots the structure of the group in a tree format.

Download Script at PoshCode.org

Code:

##########Copy the below script into a new file called Get-ADGroupNesting.ps1
 
Param (
    [Parameter(Mandatory=$true,
        Position=0,
        ValueFromPipeline=$true,
        HelpMessage="DN or ObjectGUID of the AD Group."
    )]
    [string]$groupIdentity,
    [switch]$showTree
    )
#Validate Quest PSSnapin is loaded
Add-PSSnapin -Name Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue
$global:numberOfRecursiveGroupMemberships = 0
$lastGroupAtALevelFlags = @() 
 
function Get-GroupNesting ([string] $identity, [int] $level, [hashtable] $groupsVisitedBeforeThisOne, [bool] $lastGroupOfTheLevel)
{
    $group = $null
    $group = Get-QADGroup -Identity $identity -SizeLimit 0
    if($lastGroupAtALevelFlags.Count -le $level)
    {
        $lastGroupAtALevelFlags = $lastGroupAtALevelFlags + 0
    }
    if($group -ne $null)
    {
        if($showTree)
        {
            for($i = 0; $i -lt $level - 1; $i++)
            {
                if($lastGroupAtALevelFlags[$i] -ne 0)
                {
                    Write-Host -ForegroundColor Blue -NoNewline "  "
                }
                else
                {
                    Write-Host -ForegroundColor Blue -NoNewline "│ "
                }
            }
            if($level -ne 0)
            {
                if($lastGroupOfTheLevel)
                {
                    Write-Host -ForegroundColor Blue -NoNewline "└─"
                }
                else
                {
                    Write-Host -ForegroundColor Blue -NoNewline "├─"
                }
            }
            Write-Host -ForegroundColor Blue $group.Name
        }
        $groupsVisitedBeforeThisOne.Add($group.DN,$null)
        $global:numberOfRecursiveGroupMemberships ++
        $groupMemberShipCount = $group.memberOf.Count
        if ($groupMemberShipCount -gt 0)
        {
            $maxMemberGroupLevel = 0
            $count = 0
            foreach($groupDN in $group.memberOf)
            {
                $count++
                $lastGroupOfThisLevel = $false
                if($count -eq $groupMemberShipCount){$lastGroupOfThisLevel = $true; $lastGroupAtALevelFlags[$level] = 1}
                if(-not $groupsVisitedBeforeThisOne.Contains($groupDN)) #prevent cyclic dependancies
                {
                    $memberGroupLevel = Get-GroupNesting -Identity $groupDN -Level $($level+1) -GroupsVisitedBeforeThisOne $groupsVisitedBeforeThisOne -lastGroupOfTheLevel $lastGroupOfThisLevel
                    if ($memberGroupLevel -gt $maxMemberGroupLevel){$maxMemberGroupLevel = $memberGroupLevel}
                }
            }
            $level = $maxMemberGroupLevel
        }
        else #we've reached the top level group, return it's height
        {
            return $level
        }
        return $level
    }
}
$global:numberOfRecursiveGroupMemberships = 0
$groupObj = Get-QADGroup -Identity $groupIdentity -SizeLimit 0
if($groupObj)
{
    [int]$maxNestingLevel = Get-GroupNesting -Identity $groupIdentity -Level 0 -GroupsVisitedBeforeThisOne @{} -lastGroupOfTheLevel $false
 Add-Member -InputObject $groupObj -MemberType NoteProperty  -Name MaxNestingLevel -Value $maxNestingLevel -Force
 Add-Member -InputObject $groupObj -MemberType NoteProperty  -Name NestedGroupMembershipCount -Value $($global:numberOfRecursiveGroupMemberships - 1) -Force
 $groupObj | Select-Object Name,DN,MaxNestingLevel,NestedGroupMembershipCount | Format-List
}

Hope this helps
All information is provided on an AS-IS basis, with no warranties and confers no rights.

Written by Paul Brice

January 25th, 2010 at 8:33 pm

Scanning Active Directory for SMTP Addresses

without comments

How To: Scanning Active Directory for SMTP Addresses.

When an object in AD is mail enabled it is assigned an SMTP address. Sometimes these addresses are assigned incorrectly to objects or a requested address is already in use on a object and you need to find the object that it is assigned to. I come across this situation sometimes and the simplest way is to query AD for the SMTP address. The SMTP addresses are stored in an AD attribute called “proxyAddresses” this holds all addresses including SMTP. Using the QUEST PowerShell PSSnapIn, you can query AD for this attribute using an LDAP filter.

Querying AD using Quest cmdlets and LDAP query.

Get-QADObject -LdapFilter "(proxyAddresses=*$Address*)" -IncludedProperties "proxyAddresses"

Using the above command with perform the filter, however you will only pull back the default cached set of attributes for the object so I add the ‘-includeallproperties’ switch to pull all attributes available for the object back into the cache.
I also set the ‘-SizeLimit 0′ so the result set isn’t limited to the standard 1000 returned objects.

The below code turns the basic shell command into a ‘Function’ called ‘Get-ProxyAddress.ps1′.
Instructions:

  1. Copy the below code into a file called ‘Get-ProxyAddress.ps1′
  2. Open the PowerShell shell and traverse to the directory that hosts the above file
  3. Run the script using this syntax, “./Get-ProxyAddress.ps1 address@domain.com”
  4. address@domain.com being the SMTP address you are searching for.

The output details either that the SMTP address is not found in AD or the below attributes are listed for the object that own the SMTP address.

  • Name
  • DisplayName
  • ObjectClass
  • Email
  • AccountisDisabled
  • AccountisLockedOut
  • MailNickName
  • LegacyExchangeDN

Download Script from PoshCode.org

Code:

Param (
    [Parameter(Mandatory=$true,
        Position=0,
        ValueFromPipeline=$true,
        HelpMessage="Enter SMTP address to search for in Active-Directory."
    )]
    [string]$objSMTP
	)
Function Get-ProxyAddresses ([string]$Address){
$objAD = $null
$objAD = Get-QADObject -LdapFilter "(proxyAddresses=*$Address*)" -IncludeAllProperties -SizeLimit 0 -ErrorAction SilentlyContinue
Write-Output $objAD
}#Close Function
#Validate Quest PSSnapin is loaded
Add-PSSnapin -Name Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue
#Run Function to search AD for SMTP address
$Results = $null
$Results = Get-ProxyAddresses -Address $objSMTP | Select-Object Name,DisplayName,ObjectClass,Email,AccountisDisabled,AccountisLockedOut,MailNickName,LegacyExchangeDN -ErrorAction SilentlyContinue
IF($Results -eq $null){
Write-Host ""
Write-Host "No Object Found with .attribute[proxyAddress] containing $objSMTP."}
Else{$Results | Format-List *}
#End

Hope this helps.

All information is provided on an AS-IS basis, with no warranties and confers no rights.

Written by Paul Brice

January 19th, 2010 at 11:54 pm

Disconnected Mailboxes in Exchange 2003

without comments

I was looking into finding all disconnected/orphaned mailboxes in an Exchange2003 org. Normally I would use either an old VBScript I have or the Exchange 2003 ESM. I thought it would be good to experiment with PowerShell and try to simplify the VBScript that I have.

Below is a PowerShell script that utilizes ADSI to gather all Exchange 2003 servers in your configuration container. Then for each server it utilizes WMI to connect to the Root/MicrosoftExchangeV2 ‘NameSpace’ and the Exchange_Mailbox provider. From there we filter on only mailboxes that the “DateDiscoveredAbscentInDS” property is NOT NULL. That data is then passed through the pipeline to a Select-Object where a custom Hash table is built to display the Server Name of the filtered mailboxes. The filtered mailboxes and the selected data is then passed through the pipeline and exported to a .csv file on the root of C:\ named with the format C:\DisconnectedMailboxes_%Servername%.csv.

Code:

[String]$StrFilter = "(objectCategory=msExchExchangeServer)"
$objRootDSE = [ADSI]"LDAP://RootDSE"
[String]$strContainer = $objRootDSE.configurationNamingContext
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = New-object System.DirectoryServices.DirectoryEntry("LDAP://$strContainer")
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Subtree"
$colResults = $objSearcher.FindAll()
ForEach ($objResult in $colResults) {
[String]$ServerDN = $objResult.Properties.distinguishedname
$objServer = [ADSI]"LDAP://$ServerDN"
[String]$Server = $objServer.cn
Get-WmiObject -NameSpace Root\MicrosoftExchangeV2 -Class Exchange_Mailbox -Computer $Server | `
Where { $_.DateDiscoveredAbsentInDS -ne $null } | `
Select-Object @{N="Server";E={$_.__Server}},`
StorageGroupName,StoreName,MailboxDisplayName,Size,DateDiscoveredAbsentInDS | `
Export-Csv "C:\DisconnectedMailboxes_$Server.csv" -NoTypeInformation
}#End ForEach

Hope this helps.

All information is provided on an AS-IS basis, with no warranties and confers no rights.

Written by Paul Brice

August 19th, 2009 at 10:56 pm

Exporting 2003 Mailbox Data to CSV

without comments

I have been using this code for a while and thought I would post it.

I manage several Exchange 2003 servers, this PowerShell code will allow you to pull Mailbox data from each server into their own .CSV file.
It uses a built Array for the server list and parses the Array to get Mailbox data from each server.

$Mailboxes = $Null
$Computers = "Server1","Server2","Server3","Server4"
ForEach($Computer in $Computers)
{
$Mailboxes = Get-WmiObject -NameSpace Root\MicrosoftExchangeV2 -Class Exchange_Mailbox -Computer $Computer
$Mailboxes | Export-Csv "C:\Mailboxes_$Computer.csv" -NoTypeInformation
}

You can combine this with ADSI code to discover all your Exchange 2003 servers in your Directory.
This would give you Mailbox data on all of your Exchange 2003 servers without the need for a manual Array.

[Array]$ExchSrvs = @("")
[String]$StrFilter =(objectCategory=msExchExchangeServer)$objRootDSE = [ADSI]“LDAP://RootDSE”
[String]$strContainer = $objRootDSE.configurationNamingContext
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = New-object System.DirectoryServices.DirectoryEntry(”LDAP://$strContainer)
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = “Subtree”
$colServers = $objSearcher.FindAll()
ForEach($objServer in $colServers)
{
[String]$Server = $objResult.Properties.name
$ExchSrvs += $Server
}
$ExchSrvs.Count

Your final script would look something like this.

[Array]$ExchSrvs = @("")
[String]$StrFilter =(objectCategory=msExchExchangeServer)$objRootDSE = [ADSI]“LDAP://RootDSE”
[String]$strContainer = $objRootDSE.configurationNamingContext
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = New-object System.DirectoryServices.DirectoryEntry(”LDAP://$strContainer)
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = “Subtree”
$colServers = $objSearcher.FindAll()
ForEach($objServer in $colServers)
{
[String]$Server = $objResult.Properties.name
$Mailboxes = $Null
$Mailboxes = Get-WmiObject -NameSpace Root\MicrosoftExchangeV2 -Class Exchange_Mailbox -Computer $Server
$Mailboxes | Export-Csv "C:\Mailboxes_$Server.csv" -NoTypeInformation
}

Hope this helps.

All information is provided on an AS-IS basis, with no warranties and confers no rights.

Written by Paul Brice

June 13th, 2009 at 12:16 am

Searching for DL's with Exchange Expansion Servers

without comments

Question:

Do we have any Email enabled groups in Active Directory that have an Exchange 2003 expansion server explicitly specified in its properties and who manages them? 

Expansion Server:

“Exchange server dedicated to expanding the members of a specific mail enabled group (distribution list)”

Answer:

So I would need to look at  Active Directory for all email enabled distribution lists that have the attribute ‘msExchExpansionServerName’ (which only exists when a group is mail enabled), and that it’s value is not blank. If the attribute is blank the distribution list is set to default which is ‘Any server in the organization’. The value can be viewed on the ‘Exchange Advanced’ TAB on the groups properties in ADUC.

Here is the PowerShell one line command that I used. I am utilizing the Quest Active Roles Management cmdlets.

You will need the following:

  1. DN, GUID or Canonical Name of the Domain or Container where you wish to search for groups. (The example quotes a DN for the group container)
  2. Quest Active Roles Management Shell snapin.
Get-QADGroup -SearchRoot 'OU=GrouOU,DC=company,DC=com' -SizeLimit 0 -LdapFilter '(msExchExpansionServerName=*)' -IncludeAllProperties | Select-Object name,msexchexpansionservername,managedby

If you need any assistance in using the Quest Active Roles Management cmdlets see this article.

Note:

I use the ‘-IncludeAllProperties’property of the ‘Get-QADGroup’ cmdlet to ensure the ‘msExchExpansionServerName’ attribute is returned into the local cached object result set, by default this would not be returned, for more information see this article..

Hope this helps.

All information is provided on an AS-IS basis, with no warranties and confers no rights.

Written by Paul Brice

June 8th, 2009 at 1:43 am

Scheduling ExMON Traces in Exchange 2003

without comments

When monitoring Mapi Client statistics, having to manually run the traces can be a troublesome.
After some investigation I found a way to schedule the EXMON traces using a tool called “Tracelog.exe” which is part of the W2000 Resource Kit.

Windows 2000 Resource Kit: Tracelog
Exchange User Monitor: ExMON

For this posting I will assume you have EXMON installed and have also run the installation for the Windows 2000 Resource Kit tool “TraceLog” found above.There are obviously several ways you can both schedule and manipulate the Exchange traces. For me the simplest is to create a folder, preferably on another local disk not your “system” drive. In the folder place both the “tracelog.exe” from the tracelog installation folder and a copy of the “.guid” file from the EXMON application folder.

Once created you can then proceed to create the Schedule jobs in the AT Scheduler.

You will need to create two scheduled jobs, one to start the trace and one to stop the trace.

Start Trace Command:
Tracelog.exe -start [sessionid] -guid [GUID file location] -f [Trace file location]

E.g.

TRACELOG.EXE -start "Exchange Trace" -guid guid.txt -f Trace.etl

Stop Trace Command:
Tracelog.exe -stop [sessionid]

E.g.

TRACELOG.EXE -stop "Exchange Trace"

Utilizing the above command in scheduled jobs, will enable you to schedule captures of Exchange User/Client Mapi session information. I normally embed the commands in batch files and add commands to rename and move the capture files off the DAS on the physical system. This will eliminate the need to keep track of the files and move them to prevent disks usage issues.

E.g.

In a command file you could have the following commands to stop a trace, rename and move a file.

TRACELOG.EXE -stop "Exchange Trace"Rename D:\trace.etl \\Remote\Server_EXMON-%date:~4,2%-%date:~7,2%-%date:~10,4%.etl

Hope this helps.

All information is provided on an AS-IS basis, with no warranties and confers no rights.

Written by Paul Brice

June 4th, 2009 at 8:37 pm

Posted in Exchange 2003

Tagged with ,

Getting Exchange 2003 Database Statistics

without comments

I routinely analyze Exchange 2003 stores. To do this I previously had written a VB script that dumps all the mailboxes on an Exchange 2003 server using the Exchange_Mailbox WMI class, but as this is a PowerShell article i hear you say “How does this help me?”.
I use PowerShell more and more I really enjoy the simplicity and power of the PowerShell cmdline. So I started to look into producing some clean one liners or small scripts to produce something similar to my large VB script solution.

Note: In all examples below just replace “Server” with an Exchange 2003 server name.

Getting all Exchange 2003 Mailboxes on a single server using WMI,

GWMI -NameSpace Root\MicrosoftExchangeV2 -Class Exchange_Mailbox -ComputerName $Server | Export-CSV "C:\Scripts\Mailboxes.csv" -NoTypeInformation

The next step is to start filtering the output to get detailed information on trouble spots, for example to look for any mailboxes that contain more than ’5000′ items.
To find these we use the ‘.totalItems’ property of the ‘Exchange_Mailbox’ class.

Getting all Exchange 2003 Mailboxes on a single server that have more than 5000 ‘Items’,

GWMI -NameSpace Root\MicrosoftExchangeV2 -Class Exchange_Mailbox -ComputerName $Server |  Where{$_.totalitems -gt '5000'} | Export-CSV "C:\Scripts\Mailboxes.csv" -NoTypeInformation

Another WMI ‘Exchange_Mailbox’ class property I use is the ‘.DateDiscoveredAbsentInDS’ this tells me the date the mailbox was disconnected/deleted from the User Object in AD. If for any reason you do not want the store to clean up these automatically you can script the purge of the mailboxes using VBScript or PowerShell. The below code will enable you to see the mailboxes that are ready to be purged but will take no action.

Getting all Exchange 2003 Mailboxes that have been deleted (disconnected from their AD User object) and are ready to be ‘Purged’ on a single server,

GWMI -NameSpace Root\MicrosoftExchangeV2 -Class Exchange_Mailbox -ComputerName $Server |  Where{$_.DateDiscoveredAbsentInDS -ne $NULL} | Export-CSV "C:\Scripts\Mailboxes.csv" -NoTypeInformation

Another part to the Exchange Mailbox is the counterpart attributes held in the User object. Some of these attributes are the status of the Mailbox, for example “Is the user over his/her set limits?” or “Is the account disabled in AD?”. To find out the answers here we need to interrogate the user object attribute values. To do this there are many methods depending upon the version of PowerShell you are using and if you have the Quest Management tools loaded. In the example below i am utilizing the Quest Management Tools.

Hope this helps.

All information is provided on an AS-IS basis, with no warranties and confers no rights.

Written by Paul Brice

May 26th, 2009 at 10:23 am

Searching Files – Exchange Mailbox Move Logs

without comments

I came into a situation today where PowerShell again came to the rescue.
I needed a time and date for a mailbox move in the past. We performed these moves using ‘Exchange 2003 System Manager’ (ESM). Once the moves are completed ESM places a resultant .XML file in the profile of the logged on user in a “My Documents\Exchange Task Wizard Logs\” folder. Unfortunately this was over a month ago otherwise I could examine the Exchange system logs for the successful move EventID.

However using the PowerShell Select-String CmdLet I was able to scan all the resultant .XML files (Several hundred) in a matter of seconds for a “String” of the users ‘cn’ (Common Name). If found the Pipeline would output the text string where it found the “Search String” and also the file name and path of the file.

Using the creation date of the file I have an approximate date/time of the mailbox move.

1
Select-String "usercn" "\\ExchangeServer\c$\Documents and Settings\%UserProfile%\My Documents\Exchange Task Wizard Logs\*.xml" | Format-List *

Hope this helps.

All information is provided on an AS-IS basis, with no warranties and confers no rights.

Written by Paul Brice

April 30th, 2009 at 2:19 pm

All Exchange Server Objects from Active Directory

without comments

Many of the PowerShell scripts that I write are for Exchange 2003. To keep the scripts as dynamic as possible I like to enumerate my servers from AD. The server objects for Exchange are held in the Configuration partition of the AD Schema.

All information is provided on an AS-IS basis, with no warranties and confers no rights.

Written by Paul Brice

April 8th, 2009 at 9:41 pm