views:

288

answers:

2

I would like to create a CSV file of the users on our Exchange 2003 servers, and include some attributes from their AD account. In particular, I would like to pull certain AD values for the users with RecipientTypeDetails = LegacyMailbox.

I have tried a few different methods for targeting and filtering (ldapfilter, filter, objectAttribute, etc.) these users, with little success. The Exchange 2003 PowerPack for PowerGUI was helpful, but permissions issues and using the Exchange_Mailbox class are not challenges I want to overcome.

I was finally able to create a working script, but it is very slow. The script I've created below is currently working, although it is on track to take about 4+ hours to complete. I'm am looking for suggestions for improving the efficiency of my script or otherwise obtaining this data in a quicker manner. Here is the script:

$ADproperties = 'City','Company','department','Description','DistinguishedName','DisplayName','FirstName','l','LastName','msExchHomeServerName','NTAccountName','ParentContainer','physicaldeliveryofficename','SamAccountName','useraccountcontrol','UserPrincipalName'
get-user -ResultSize Unlimited -ignoredefaultscope -RecipientTypeDetails LegacyMailbox | foreach {Get-QADUser $_.name -DontUseDefaultIncludedProperties -IncludedProperties $ADproperties} | select $ADproperties | epcsv C:\UserListBuilder\exchUsers.csv -notype

Any help you can provide will be greatly appreciated!

A: 

I solved this challenge using a script I already created which merges a CSV file with attributes from AD. Basically I used Get-Mailbox to generate a CSV list of all of the Exchange 2003 users, then use that list as input for Get-QADuser to pull the AD attributes I need, and couldn't pull with other cmdlets. The Merge-Object and Export-CSV functions were found from other users on the internet, both very handy functions. Below is a copy of the script:

Function Merge-Object($Base, $Additional)
{
ForEach ($Property in $($Additional | Get-Member -Type Property, NoteProperty))
{
    $Base | Add-Member -MemberType NoteProperty -Name $Property.Name -Value $Additional.$($Property.Name) -ErrorAction SilentlyContinue
}
Return $Base
}
Function Export-CSV
{
[CmdletBinding(DefaultParameterSetName='Delimiter',
SupportsShouldProcess=$true, ConfirmImpact='Medium')]
param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true)]
[System.Management.Automation.PSObject]
${InputObject},

[Parameter(Mandatory=$true, Position=0)]
[Alias('PSPath')]
[System.String]
${Path},

#region -Append (added by Dmitry Sotnikov)
[Switch]
${Append},
#endregion 

[Switch]
${Force},

[Switch]
${NoClobber},

[ValidateSet('Unicode','UTF7','UTF8','ASCII','UTF32','BigEndianUnicode','Default','OEM')]
[System.String]
${Encoding},

[Parameter(ParameterSetName='Delimiter', Position=1)]
[ValidateNotNull()]
[System.Char]
${Delimiter},

[Parameter(ParameterSetName='UseCulture')]
[Switch]
${UseCulture},

[Alias('NTI')]
[Switch]
${NoTypeInformation})

begin
{
# This variable will tell us whether we actually need to append
# to existing file
$AppendMode = $false

try {
$outBuffer = $null
if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
{
    $PSBoundParameters['OutBuffer'] = 1
}
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Export-Csv',
    [System.Management.Automation.CommandTypes]::Cmdlet)


    #String variable to become the target command line
    $scriptCmdPipeline = ''

    # Add new parameter handling
    #region Dmitry: Process and remove the Append parameter if it is present
    if ($Append) {

        $PSBoundParameters.Remove('Append') | Out-Null

if ($Path) {
if (Test-Path $Path) {        
    # Need to construct new command line
    $AppendMode = $true

    if ($Encoding.Length -eq 0) {
    # ASCII is default encoding for Export-CSV
    $Encoding = 'ASCII'
    }

    # For Append we use ConvertTo-CSV instead of Export
    $scriptCmdPipeline += 'ConvertTo-Csv -NoTypeInformation '

    # Inherit other CSV convertion parameters
    if ( $UseCulture ) {
    $scriptCmdPipeline += ' -UseCulture '
    }
    if ( $Delimiter ) {
    $scriptCmdPipeline += " -Delimiter '$Delimiter' "
    } 

    # Skip the first line (the one with the property names) 
    $scriptCmdPipeline += ' | Foreach-Object {$start=$true}'
    $scriptCmdPipeline += '{if ($start) {$start=$false} else {$_}} '

    # Add file output
    $scriptCmdPipeline += " | Out-File -FilePath '$Path' -Encoding '$Encoding' -Append "

    if ($Force) {
    $scriptCmdPipeline += ' -Force'
    }

    if ($NoClobber) {
    $scriptCmdPipeline += ' -NoClobber'
    }   
}
}
} 



$scriptCmd = {& $wrappedCmd @PSBoundParameters }

if ( $AppendMode ) {
# redefine command line
$scriptCmd = $ExecutionContext.InvokeCommand.NewScriptBlock(
    $scriptCmdPipeline
    )
} else {
# execute Export-CSV as we got it because
# either -Append is missing or file does not exist
$scriptCmd = $ExecutionContext.InvokeCommand.NewScriptBlock(
    [string]$scriptCmd
    )
}

# standard pipeline initialization
$steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
$steppablePipeline.Begin($PSCmdlet)

} catch {
throw
}

}

process
{
try {
    $steppablePipeline.Process($_)
} catch {
    throw
}
}

end
{
try {
    $steppablePipeline.End()
} catch {
    throw
}
}
<#

.ForwardHelpTargetName Export-Csv
.ForwardHelpCategory Cmdlet

#>
}
###################################################################################################################################
#   Script
###################################################################################################################################
# Get Start Time
$startDTM = (Get-Date)
$ADproperties = 'FirstName','LastName','userAccountControl','physicaldeliveryofficename','l','City','UserPrincipalName','NTAccountName','SamAccountName','ParentContainer','Description','msExchHomeServerName'
#$CSVdirectory = "C:\UserListBuilder\CSV\Exch2003\*.*"  # Directory containing Exchange directory export CSV files, include *.*
$csv = "C:\UserListBuilder\CSV\Exch2003\ex03.csv"
$Outputfilename = "C:\UserListBuilder\Exchange2003-ADInfo.csv"

# Create a file of the legacy mailboxes
Get-Mailbox -ignoredefaultscope -ResultSize 'Unlimited' | where { $_.'RecipientTypeDetails' -eq [Microsoft.Exchange.Data.Directory.Recipient.RecipientTypeDetails]'LegacyMailbox' } | select 'DisplayName','SamAccountName','UserPrincipalName' | epcsv $csv -notype

$CurrentFile = Import-Csv $csv

foreach($Row in $CurrentFile)
{
$CurrentUser = $Row.'UserPrincipalName'

$CurrentUserADinfo = Get-QADUser -identity "$CurrentUser" -DontUseDefaultIncludedProperties -IncludedProperties $ADproperties | select-object $ADproperties
Merge-Object $Row $CurrentUserADinfo
$Row | Export-CSV -Path $Outputfilename -Append -NoTypeInformation
}

# Get End Time
$endDTM = (Get-Date)

# Echo Time elapsed
"Elapsed Time: $(($endDTM-$startDTM).totalseconds) seconds"
Jason Hindson
A: 

Hi..

Good work...

can you please mention how this script can be put to work?

Seems to in c#?

Please mention the steps to run and test it.

Thanks.

Chitresh