Powershell 获取旧版Exchange服务器上用户的Active Directory属性

Powershell 获取旧版Exchange服务器上用户的Active Directory属性,powershell,scripting,active-directory,exchange-server,Powershell,Scripting,Active Directory,Exchange Server,我想在我们的Exchange2003服务器上创建一个用户的CSV文件,并包含他们的广告帐户中的一些属性。特别是,我想为RecipientTypeDetails=LegacyMailbox的用户提取某些广告值 我尝试了几种不同的方法来定位和过滤这些用户(ldapfilter、filter、objectAttribute等),但收效甚微。Exchange 2003 PowerPack for PowerGUI非常有用,但权限问题和使用Exchange_邮箱类并不是我想要克服的挑战 我终于能够创建一个

我想在我们的Exchange2003服务器上创建一个用户的CSV文件,并包含他们的广告帐户中的一些属性。特别是,我想为RecipientTypeDetails=LegacyMailbox的用户提取某些广告值

我尝试了几种不同的方法来定位和过滤这些用户(ldapfilter、filter、objectAttribute等),但收效甚微。Exchange 2003 PowerPack for PowerGUI非常有用,但权限问题和使用Exchange_邮箱类并不是我想要克服的挑战

我终于能够创建一个工作脚本,但速度非常慢。我在下面创建的脚本目前正在运行中,尽管它预计需要4个多小时才能完成。我正在寻找提高脚本效率的建议,或者以其他方式更快地获取这些数据。以下是脚本:

$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
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"

我们将非常感谢您提供的任何帮助

我使用我已经创建的脚本解决了这个问题,该脚本将CSV文件与AD的属性合并。基本上,我使用Get-Mailbox生成所有Exchange 2003用户的CSV列表,然后使用该列表作为Get-QADuser的输入,以提取我需要的AD属性,而无法使用其他cmdlet进行提取。合并对象和导出CSV功能是从internet上的其他用户那里找到的,这两个功能都非常方便。以下是脚本的副本:

$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
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"
函数合并对象($Base,$Additional)
{
ForEach($中的属性($附加| Get成员类型属性,NoteProperty))
{
$Base |添加成员-成员类型NoteProperty-名称$Property.Name-值$Additional.$($Property.Name)-错误操作SilentlyContinue
}
返回$Base
}
函数导出CSV
{
[CmdletBinding(DefaultParameterSetName='Delimiter',
SupportsShouldProcess=$true,confirImpact='Medium')]
param(
[参数(必需=$true,ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[系统、管理、自动化、PSObject]
${InputObject},
[参数(必需=$true,位置=0)]
[别名('PSPath')]
[系统.字符串]
${Path},
#地区-附加(由Dmitry Sotnikov添加)
[开关]
${Append},
#端区
[开关]
${Force},
[开关]
${NoClobber},
[ValidateSet('Unicode','UTF7','UTF8','ASCII','UTF32','BigendiaUnicode','Default','OEM')]
[系统.字符串]
${Encoding},
[参数(ParameterSetName='Delimiter',Position=1)]
[ValidateNotNull()]
[System.Char]
${分隔符},
[参数(ParameterSetName='UseCulture')]
[开关]
${UseCulture},
[别名('NTI')]
[开关]
${NoTypeInformation})
开始
{
#这个变量将告诉我们是否确实需要追加
#到现有文件
$AppendMode=$false
试一试{
$EXPUFFER=$null
if($PSBoundParameters.TryGetValue('exputffer',[ref]$exputffer))
{
$PSBoundParameters['Exputffer']=1
}
$wrappedCmd=$ExecutionContext.InvokeCommand.GetCommand('Export-Csv',
[System.Management.Automation.CommandTypes]::Cmdlet)
#字符串变量以成为目标命令行
$scriptCmdPipeline=''
#添加新的参数处理
#region Dmitry:处理并删除Append参数(如果存在)
如果($追加){
$PSBoundParameters.Remove('Append')| Out Null
如果($Path){
if(测试路径$Path){
#需要构造新的命令行吗
$AppendMode=$true
如果($Encoding.Length-等式0){
#ASCII是导出CSV的默认编码
$Encoding='ASCII'
}
#对于Append,我们使用converttocsv而不是Export
$scriptCmdPipeline+=“转换为Csv-NoTypeInformation”
#继承其他CSV转换参数
如果($UseCulture){
$scriptCmdPipeline+='-UseCulture'
}
if($分隔符){
$scriptCmdPipeline+=“-分隔符“$Delimiter”
} 
#跳过第一行(带有属性名称的那一行)
$scriptCmdPipeline+='| Foreach对象{$start=$true}'
$scriptCmdPipeline+='{if($start){$start=$false}else{${}'
#添加文件输出
$scriptCmdPipeline+=“|输出文件-文件路径'$Path'-Encoding'$Encoding'-Append”
若有($武力){
$scriptCmdPipeline+='-Force'
}
如果($NoClobber){
$scriptCmdPipeline+='-NoClobber'
}   
}
}
} 
$scriptCmd={&$wrappedCmd@PSBoundParameters}
如果($AppendMode){
#重新定义命令行
$scriptCmd=$ExecutionContext.InvokeCommand.NewScriptBlock(
$scriptCmdPipeline
)
}否则{
#执行导出CSV,因为
#缺少-Append或文件不存在
$scriptCmd=$ExecutionContext.InvokeCommand.NewScriptBlock(
[字符串]$scriptCmd
)
}
#标准管道初始化
$steppablePipeline=$scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
$steppablePipeline.Begin($PSCmdlet)
}抓住{
扔
}
}
过程
{
试一试{
$steppablePipeline.Process($\ux)
}抓住{
扔
}
}
结束
{
试一试{
$steppablePipeline.End()
}抓住{
扔
}
}
}
###################################################################################################################################
#剧本
###################################################################################################################################
#开始时间
$startDTM=(获取日期)
$ADproperties='FirstName'、'LastName'、'userAccountControl'、'physicaldeliveryofficename'、'l'、'City'、'UserPrincipalName'、'NTAccountName'、'SamAccountName'、'ParentContainer'、'Description'、'msExchHomeServerName'
#$CSVdirectory=“C:\UserListBuilder\CSV\Exch2003\*.*”包含Exchange目录导出CSV文件的目录,包括**
$csv=“C:\UserListBuilder\csv\Exch2003\ex03.csv”
$Outputfilename=“C:\UserListBuilder\Exchange2003 ADInfo.csv”
#创建旧邮箱的文件
获取邮箱-ignoredefaultscope-ResultSize'Unlimited'|其中{$"RecipientTypeDetails'-eq[Microsoft.Exchange.Data.Directory.RecipientTypeDetails]'LegacyMailbox'}|选择'DisplayName'、'SamAccountName'、'UserPrincipalName'| epcsv$csv-NotType
$CurrentFile=导入Csv$Csv