none
Exchange mailboxes, corporate AD, forest trust, arrays, Can you look this over? RRS feed

  • Question

  • This is my first script, it took a while to figure some things out, but it is working. I wanted to know if it is overkill, or if there is something that sticks out that would be an easier way of accomplishing something with this script.

    Background info:

    Company was bought out, forest trust set up between corp network and ours (years ago). So what we wanted was to compare exchange mailboxes with linked mailboxes array, to be compared to corporate AD array with user accounts that are disabled. a list is created in another script which shows linked mailboxes and disabled corp AD accounts, helpdesk looks these through to make sure there are no exceptions. Exceptions are entered into PS cmdline, those are pulled out of the array. Then the left objects in the array are PST backed up to network share, and then mailboxes removed. Admin trust across corp allows Exchange admin to search through Corp AD through search-AdAccount cmdlet. The script is run from a VM with exchange server tools installed and running 32-bit os of Windows 7 and 32-bit Office (Because that's how great... Exchange 2007 is for exporting mailboxes to PST). 

    Not sure of this, though it works: 

    <#Clear variables so they are not retaining any old values#>
    Get-Variable -Exclude PWD,*Preference | Remove-Variable -EA 0

    Wanted to clear variables before running script, data was being held over each run before adding this in

    Here is the code "xxxxx" used in lieu of server names:

    <#Import in modules, if statement for PSSnapin so that it doesn't throw an error if it is already loaded.#>
    Import-Module ActiveDirectory
    if ( (Get-PSSnapin -Name Microsoft.Exchange.Management.PowerShell.Admin -ErrorAction SilentlyContinue) -eq $null )
    {
        add-pssnapin Microsoft.Exchange.Management.PowerShell.Admin
    }

    <#Clear variables so they are not retaining any old values#>
    Get-Variable -Exclude PWD,*Preference | Remove-Variable -EA 0

    <#Variables needed to complete script. $testIteration shows the number of times nested for loop happens, $exUserCorpMatch=@() is an empty array that will have objects added to it
    when linked mailboxes on Exchange are compared to disabled corp accounts, the $adminUser and $adPW are the login credentials so that anyone can enter admin login credentials to run script#>
    $errorLogPath = "c:\scripts\logs\exchangeADerror.txt"
    $testIteration=0
    $exUserCorpMatch=@()
    $adminUser = whoami
    $exceptionUsers=@()
    $exceptionArray=@()

    <#Create an Array from Get-mailbox cmdlet that has the value "LinkedMailbox" tying it to a Corporate account, .count value used to check results against expected#>
    $mailboxes = Get-Mailbox -resultSize unlimited -RecipientTypeDetails LinkedMailbox
    $mailboxes.count

    <#Create an array of objects from Corp server of user only dissabled accounts, .count value used to check results against expected#>
    $corpAccDis = Search-ADAccount -ResultSetSize $null -Server xxxxx -AccountDisabled -UsersOnly
    $corpAccDis.count

    <#Read in a list of users whose mailboxes shouldn't be removed#>
    while ($var -ne "q"){
        $var = Read-Host "Enter user exception linked mailbox name, or press q to quit entering names:"
        if ($var -ne "q"){
        $exceptionUsers += $var
        }
    }    
    $exceptionUsers.count

    <#Create an Array with the usernames that were supplied by the Read-Host Cmdlet#>
    foreach ($name in $exceptionUsers){ 
    $exceptionArray += Get-Mailbox -Identity $name
    }
    $exceptionArray

    <#Compare the two arrays on the value of name from the "Linked Master Account" and the Corp server "Sam Account Name" and insert the matching objects into an Array#>
    For ($a=0 ; $a -le $mailboxes.count -1 ; $a++){ 
        For ($b=0 ; $b -le $corpAccDis.count -1 ; $b++){
        $testIteration++
                            if ($mailboxes[$a].LinkedMasterAccount.Split("\")[-1] -eq $corpAccDis[$b].SamAccountName){
                                $exUserCorpMatch += $mailboxes[$a]
                                break
                            }
         }      
                              
     }
    $testIteration  #Test value checking nember of times the loop took place
    $exUserCorpMatch.count

    <#For loop to take exception users mailboxes out of the script#>
    For ($d=0;$d -lt $exceptionArray.Count; $d++){
        $exUserCorpMatch = $exUserCorpMatch| ? {$_.alias -ne $exceptionArray[$d].alias}
    }
    $exUserCorpMatch.count
    $exUserCorpMatch | sort

    <#Taking the newly created array from the comparison and running the bulk of decisions, gives full access rights to the before entered admin account, then exports the mailbox to a PST
    file on the network share, and produces a txt file of the users properties, attributes, etc.. Then removes-mailbox, this is cmdlet is currently commented out until testing is done and 
    confirmed removal is ready to take place. #>
    for ($c = 0 ; $c -le $exUserCorpMatch.count -1; $c++){
        $fileCreationTime = Get-Date -UFormat "%Y%m%d%H%M%S"
        $displayName = $exUserCorpMatch[$c].DisplayName
        $pstFolderPath = Join-Path "\\xxxxx\exchangePST\" $fileCreationTime$displayName.PST
        $txtFolderPath = Join-Path "\\xxxxx\exchangePST\" $fileCreationTime$displayName.txt
        
        try {
            $everythingIsOk = $true
            Add-MailboxPermission -Identity $exUserCorpMatch[$c] -User $adminUser -AccessRights FullAccess -ErrorAction Stop -Verbose
        } catch {
            $everythingIsOk = $false
            Write-Warning "Permission add problem, logging error to $errorLogPath!"
            Write-Warning $error[0]
            $error[0] | Out-File $errorLogPath -Append
        }
        if ($everythingIsOk){
            try{
            Export-Mailbox -Identity $exUserCorpMatch[$c] -PSTFolderPath $pstFolderPath -ErrorAction Stop -Verbose
            }catch{
            $everythingIsOk = $false
            Write-Warning "Export problem!"
            Write-Warning $error[0]
            $error[0] | Out-File $errorLogPath -Append
            }
        }
        if ($everythingIsOk){
            try {
            Get-Mailbox -Identity $exUserCorpMatch[$c] | FL | Out-File $txtFolderPath -ErrorAction Stop -Verbose
            } catch {
            $everythingIsOk = $false
            Write-Warning "Problem writing to txt"
            Write-Warning $error[0]
            $error[0] | Out-File $errorLogPath -Append
            }
        }
        if ($everythingIsOk){
            try{
            Write-Verbose "!!!!!!!!!!!!!!!!!!"
            <#Remove-Mailbox -Identity $exUserCorpMatch[$c] -Permanent $true -ErrorAction Stop -Verbose#>
            } catch {
             Write-Warning $error[0]
             $error[0] | Out-File $errorLogPath -Append
            }
        }
    }

    Monday, March 10, 2014 6:08 PM

Answers

  • Half of you code appears to be doing nothing.

    This does nothing:
    if ($everythingIsOk){
            try{
            Write-Verbose "!!!!!!!!!!!!!!!!!!"
            <#Remove-Mailbox -Identity $exUserCorpMatch[$c] -Permanent $true -ErrorAction Stop -Verbose#>
            } catch {
             Write-Warning $error[0]
             $error[0] | Out-File $errorLogPath -Append
            }
        }

    The way we do a limiting Try/Catch is to just use a single "try/catch".

    $fileCreationTime = Get-Date -UFormat "%Y%m%d%H%M%S"
    for ($c = 0 ; $c -lt $exUserCorpMatch.count; $c++){
         $displayName = $exUserCorpMatch[$c].DisplayName
         $pstFolderPath = Join-Path "\\xxxxx\exchangePST\" $fileCreationTime$displayName.PST
         $txtFolderPath = Join-Path "\\xxxxx\exchangePST\" $fileCreationTime$displayName.txt
         
            try {
                Add-MailboxPermission -Identity $exUserCorpMatch[$c] -User $adminUser -AccessRights FullAccess -ErrorAction Stop -Verbose
                Get-Mailbox -Identity $exUserCorpMatch[$c] | FL | Out-File $txtFolderPath -ErrorAction Stop -Verbose
                <#Remove-Mailbox -Identity $exUserCorpMatch[$c] -Permanent $true -ErrorAction Stop -Verbose#>
            }catch
              Write-Warning $error[0]
              $error[0] | Out-File $errorLogPath -Append
            }
        }
    } 

    The following does the same thing your code did.  It executes but aborts further execution on an exception.


    ¯\_(ツ)_/¯


    • Edited by jrv Monday, March 10, 2014 7:26 PM
    • Marked as answer by sweatshop Monday, March 10, 2014 9:25 PM
    Monday, March 10, 2014 7:25 PM

All replies

  • Half of you code appears to be doing nothing.

    This does nothing:
    if ($everythingIsOk){
            try{
            Write-Verbose "!!!!!!!!!!!!!!!!!!"
            <#Remove-Mailbox -Identity $exUserCorpMatch[$c] -Permanent $true -ErrorAction Stop -Verbose#>
            } catch {
             Write-Warning $error[0]
             $error[0] | Out-File $errorLogPath -Append
            }
        }

    The way we do a limiting Try/Catch is to just use a single "try/catch".

    $fileCreationTime = Get-Date -UFormat "%Y%m%d%H%M%S"
    for ($c = 0 ; $c -lt $exUserCorpMatch.count; $c++){
         $displayName = $exUserCorpMatch[$c].DisplayName
         $pstFolderPath = Join-Path "\\xxxxx\exchangePST\" $fileCreationTime$displayName.PST
         $txtFolderPath = Join-Path "\\xxxxx\exchangePST\" $fileCreationTime$displayName.txt
         
            try {
                Add-MailboxPermission -Identity $exUserCorpMatch[$c] -User $adminUser -AccessRights FullAccess -ErrorAction Stop -Verbose
                Get-Mailbox -Identity $exUserCorpMatch[$c] | FL | Out-File $txtFolderPath -ErrorAction Stop -Verbose
                <#Remove-Mailbox -Identity $exUserCorpMatch[$c] -Permanent $true -ErrorAction Stop -Verbose#>
            }catch
              Write-Warning $error[0]
              $error[0] | Out-File $errorLogPath -Append
            }
        }
    } 

    The following does the same thing your code did.  It executes but aborts further execution on an exception.


    ¯\_(ツ)_/¯


    • Edited by jrv Monday, March 10, 2014 7:26 PM
    • Marked as answer by sweatshop Monday, March 10, 2014 9:25 PM
    Monday, March 10, 2014 7:25 PM
  • Ahh I see, I thought multiple try catch like that was probably not a good construct, so being able to drop them all together in this manner will allow the following, just to be clear?

    The next command will not run if the first command does not finish? I don't want to remove a mailbox if the first two did not take place. 

    Thanks!

    Monday, March 10, 2014 9:25 PM
  • That is what try/catch is for.  It exits to "Catch" on any error.  You can restart but, in this case that is not what you want to do.


    ¯\_(ツ)_/¯

    Monday, March 10, 2014 10:13 PM