This post also be published in English: http://www.cnblogs.com/LarryAtCNBlog/p/3923882.html
稱之爲bug真得好嗎?不過想想也沒錯呀,因爲QADProxyAddress相關的命令基本上都不能用了都。
事情大概是這樣,
我們公司因爲業務以前有很多smtp address,現在大統一要清除AD裏面一些SMTP domain,公司用的是Quest ARServer管理權限,因此實際上我本人雖然身爲管理員,其實權限對AD本身就是一個普通user,所有的操作都必須通過Quest console來實現,很高興的是Quest公司出品了powershell版的console,讓我可以通過命令行來做batch job。
當然,這次的smtp domain清理大行動又落在了我身上,咦~~我爲什麼要說又~
打開ISE,開始碼代碼,其實寫腳本,或者說編程,核心幹活的代碼絕不能排在第一位,logging至少是與其並列,log是當事情幹完之後一旦出問題,唯一能夠拯救世界的東西。
扯遠了,代碼並不複雜,根據project team每次所給我的batch job,我只需要讀該文本,取出user名字,用Get-QADUser的方法從AD裏把該user抓到,然後判斷其ProxyAddresses屬性有沒有匹配到目標domain就好了,沒有匹配到的話,則跳過該user,匹配到的話就提取出匹配項,然後執行Remove-QADProxyAddress命令就行了。這麼簡單想想都有點小激動呢。
代碼寫一半,打算用自己的賬號測試一下Remove-QADProxyAddress這個cmdlet的用法及錯誤返回。
喲,果然what the hell了,心涼一截,這錯兒是怎麼事兒?感覺要被坑呢?
明明通過console UI界面操作,不用每一個type的address都要有一個primary纔對呀,可以直接做纔對呀,果斷搜了一搜,發現如下某人給Dell (沒錯Quest被Dell收購啦) report了同樣的問題,話說Dell沒人管是怎麼事兒?這都快2年了!
http://en.community.dell.com/techcenter/powergui/f/4834/t/19574623.aspx
我公司用的還是ARS 6.7.0, ARS powershell module的相應版本是1.5.1,最新的是ARS 6.8.0,不清楚該bug修復了沒有,無論怎麼樣服務器端要有對應的版本,不然光下載個最近的客戶端也連接不上服務器,會被拒絕。
怎麼辦呢?其實問題很簡單,QADProxyAddress相關的幾個cmdlet在運行的時候都會檢查每個proxy address的type,每種type都要有一個primary,沒設置的話是不行的。而且,就算爲了修正該問題,想對每個type都設一個primary,也是不行。困爲如果同時存在兩種以上的type沒有primary,在糾正其中一個type的時候,會報另外的type沒有primary的錯誤,比如同時有sip和x500兩個type沒有primary,在運行如下命令糾正sip的時候,就會報x500沒有primary,稱爲被坑不爲過呀
怎麼辦怎麼辦,都不要臉地答應人project manager了,現在說做不到不是要丟死人了嗎?
AD賬號本身又沒權限,通過ARS又有該bug,最後想到exchange 2010,我的賬號是有修改mailbox的權限的,看看mailbox上有沒有同樣的屬性先。
於是果斷登上exchange,打開powershell,Get-Mailbox | fl * 一瞅果斷有同樣的屬性。這就是傳說中的救命稻草,趕緊把Y按地上。用Set-Mailbox果然能無視primary修改proxy address,於是腳本改成用exchange powershell執行。於是有了下面的腳本,會讀取Process.list.txt裏的user list,然後從user的address找smtp地址的匹配,找到的話就刪掉,沒有找到就跳過。
. 'D:\Program Files\Microsoft\Exchange Server\v14\bin\RemoteExchange.ps1' Connect-ExchangeServer -auto $users = cat '.\Process.list.txt' | ?{$_} | %{$_.Trim()} $addressToRemove = 'regular expression' $Date = Get-Date $strDate = $Date.ToString('yyyy-MM-dd') $strLogFile = "$strDate.log" function Add-Log{ PARAM( [String]$Path, [String]$Value, [String]$Type ) $Type = $Type.ToUpper() Write-Host "$((Get-Date).ToString('[HH:mm:ss] '))[$Type] $Value" if($Path){ Add-Content -Path $Path -Value "$((Get-Date).ToString('[HH:mm:ss] '))[$Type] $Value" } } $Total = $users.Count Add-Log -Path $strLogFile -Value "Users count: [$Total]" -Type Info $users | %{$Processed = 0}{ $Processed++ Add-Log -Path $strLogFile -Value "Processing: [$Processed/$Total][$_]" -Type Info $mailbox = $null $mailbox = Get-Mailbox -Identity $_ if(!$mailbox) { Add-Log -Path $strLogFile -Value "Failed to get user's mailbox" -Type Error return } Add-Log -Path $strLogFile -Value "All 1: [$(($mailbox.EmailAddresses | %{$_.ProxyAddressString}) -join '], [')]" -Type Info $addresses = $mailbox.EmailAddresses | ?{$_.Prefix.DisplayName -eq 'SMTP'} | %{$_.SmtpAddress} $addressMatch = $null $addressMatch = $addresses -imatch $addressToRemove if($addressMatch) { Add-Log -Path $strLogFile -Value "Matched: [$($addressMatch -join '], [')]" -Type Info $mailbox | Set-Mailbox -EmailAddresses @{remove=$addressMatch} -ErrorAction:SilentlyContinue if(!$?) { Add-Log -Path $strLogFile -Value 'Remove address failed, cause:' -Type Error Add-Log -Path $strLogFile -Value $Error[0] -Type Error } $mailbox = Get-Mailbox -Identity $_ Add-Log -Path $strLogFile -Value "All 2: [$(($mailbox.EmailAddresses | %{$_.ProxyAddressString}) -join '], [')]" -Type Info } else { Add-Log -Path $strLogFile -Value "No SMTP address matched, move to next." -Type Info return } }