Making The Code Neater

Hello All,

Thanks so much for help so far, its helped me an awful lot. I hope I can add value into he forum myself as I gain more experience.

Ok so I am wanting to tidy up my script and I think its too long. Sections have repeats in which I was wondering if I could shorten.

So various functions through the script add members to an Array. Here is an example:

$obj|add-member -membertype NoteProperty -name "ObjectGuid" -value $_.Guid
$obj|add-member -membertype NoteProperty -name "ExchangeGuid" -value $_.ExchangeGuid
$obj|add-member -membertype NoteProperty -name "SamAccountName" -value $_.SamAccountName
$obj|add-member -membertype NoteProperty -name "UserPrincipalName" -value $_.UserPrincipalName
$obj|add-member -membertype NoteProperty -name "DisplayName" -value $_.DisplayName

Later the array is sent to a function for export to CSV

Build-Report -Obj $obj

Sometimes various attributes are not available and I’ve found that if say there are 20 attributes I want in the CSV report at the end, then I must ensure that each time I pass the $OBJ array to Build-Report function that all the columns are the same.

So if pass one has only 18 attributes (or members) in the $OBJ array that gets commited to CSV no problem. However if then on the 2nd run all 20 get populated, I get an error message saying:

The appended object does not have a property that corresponds to the following column: ItemCount

So the way I got around this was that for each function, I list an entire set of attributes, even if they are going to be blank. That way I ensure when it comes to exporting to CSV the columns all match up.

This kind of works but its messy. I end up with lots of repetition.

I tried to fix this by only passing when was present from each Function (so much less code repetition) and then have the Build-Report function to pad out ‘blanks’ before Exporting to CSV. However that didnt work. Seems that once a function has passed in the $OBJ array to the Build-Report function, its fixed and new members CANNOT be added. At least not when I tried.

Here is an example of that failed attempt:

 #*** Building Report ***


            if(!$obj.objectGuid){ $obj|add-member -membertype NoteProperty -name "ObjectGuid" -value ""}
            if(!$obj.ExchangeGuid){$0bj |add-member -membertype NoteProperty -name "ExchangeGuid" -value ""}
            if(!$obj.ArchiveGuid){$0bj |add-member -membertype NoteProperty -name "ArchiveGuid" -value ""}
            if(!$obj.SamAccountName){$0bj |add-member -membertype NoteProperty -name "SamAccountName" -value ""}
            if(!$obj.UserPrincipalName){$0bj |add-member -membertype NoteProperty -name "UserPrincipalName" -value ""}
            if(!$obj.DisplayName){$0bj |add-member -membertype NoteProperty -name "DisplayName" -value ""}
            if(!$obj.Company){$0bj |add-member -membertype NoteProperty -name "Company" -value ""}
            if(!$obj.Department){$0bj |add-member -membertype NoteProperty -name "Department" -value ""}
            if(!$obj.JobTitle){$0bj |add-member -membertype NoteProperty -name "JobTitle" -value ""}
            if(!$obj.PrimarySmtpAddress){$0bj |add-member -membertype NoteProperty -name "PrimarySmtpAddress" -value ""}
            if(!$obj.Database){$0bj |add-member -membertype NoteProperty -name "Database" -value ""}
            if(!$obj.ItemCount){$0bj |add-member -membertype NoteProperty -name "ItemCount" -value ""}
            if(!$obj.TotalItemSize){$0bj |add-member -membertype NoteProperty -name "TotalItemSize" -value ""}
            if(!$obj.ArchiveItemCount){$0bj |add-member -membertype NoteProperty -name "ArchiveItemCount" -value ""}
            if(!$obj.ArchiveTotalItemSize){$0bj |add-member -membertype NoteProperty -name "ArchiveTotalItemSize" -value ""}
            if(!$obj.CombinedTotalSize){$0bj |add-member -membertype NoteProperty -name "CombinedTotalSize" -value ""}
            if(!$obj.EA1){$0bj |add-member -membertype NoteProperty -name "EA1" -value ""}
            if(!$obj.EA2){$0bj |add-member -membertype NoteProperty -name "EA2" -value ""}
            if(!$obj.EA3){$0bj |add-member -membertype NoteProperty -name "EA3" -value ""}
            if(!$obj.EA4){$0bj |add-member -membertype NoteProperty -name "EA4" -value ""}
            if(!$obj.EA5){$0bj |add-member -membertype NoteProperty -name "EA5" -value ""}
            if(!$obj.LastLogonDate){$0bj |add-member -membertype NoteProperty -name "LastLogonDate" -value ""}
            if(!$obj.RecipientType){$0bj |add-member -membertype NoteProperty -name "RecipientType" -value ""}
            if(!$obj.RecipientTypeDetails){$0bj |add-member -membertype NoteProperty -name "RecipientTypeDetails" -value ""}
            if(!$obj.DelegateName){$0bj |add-member -membertype NoteProperty -name "DelegateName" -value ""}
            if(!$obj.DelegateEmail){$0bj |add-member -membertype NoteProperty -name "DelegateEmail" -value ""}
            if(!$obj.DelegateAccess){$0bj |add-member -membertype NoteProperty -name "DelegateAccess" -value ""}
            if(!$obj.FolderPath){$0bj |add-member -membertype NoteProperty -name "FolderPath" -value ""}
            if(!$obj.GroupExists){$0bj |add-member -membertype NoteProperty -name "GroupExists" -value ""}
            if(!$obj.LitigationHoldEnabled){$0bj |add-member -membertype NoteProperty -name "LitigationHoldEnabled" -value ""}
            if(!$obj.SingleItemRecoveryEnabled){$0bj |add-member -membertype NoteProperty -name "SingleItemRecoveryEnabled" -value ""}
            if(!$obj.LitigationHoldDate){$0bj |add-member -membertype NoteProperty -name "LitigationHoldDate" -value ""}
            if(!$obj.LitigationHoldOwner){$0bj |add-member -membertype NoteProperty -name "LitigationHoldOwner" -value ""}
            if(!$obj.LitigationHoldDuration){$0bj |add-member -membertype NoteProperty -name "LitigationHoldDuration" -value ""}
            if(!$obj.RetainDeletedItemsFor){$0bj |add-member -membertype NoteProperty -name "RetainDeletedItemsFor" -value ""}
            if(!$obj.UMEnabled){$0bj |add-member -membertype NoteProperty -name "UMEnabled" -value ""}
            if(!$obj.BatchName){$0bj |add-member -membertype NoteProperty -name "BatchName" -value ""}
            if(!$obj.CurrentStatus){$0bj |add-member -membertype NoteProperty -name "CurrentStatus" -value ""}
            if(!$obj.EEComments1){$0bj |add-member -membertype NoteProperty -name "EEComments1" -value ""}
            if(!$obj.EEComments2){$0bj |add-member -membertype NoteProperty -name "EEComments2" -value ""}
            if(!$obj.BDOComments1){$0bj |add-member -membertype NoteProperty -name "BDOComments1" -value "."}
            if(!$obj.BDOComments2){$0bj |add-member -membertype NoteProperty -name "BDOComments2" -value "."}


            $obj|export-csv c:\O365Reports\$report.csv -Append

The idea is, it checks if the array contains that member, and if its not present it adds in a blank, just so that its consistent before export-csv.

So now I have to revert back to this mess in each function (this is just one function):

Function Process-Mailboxes { #FN-PM

[cmdletbinding()]
param([string]$Name)

        Get-Mailbox -ResultSize unlimited |?{!($_.DisplayName -like "*Discovery S*")} | select identity,DisplayName,DistinguishedName,guid,ExchangeGuid,ArchiveGuid,SamAccountName,UserprincipalName,DisplayName,PrimarySmtpAddress,Database,ServerName,RecipientType,RecipientTypeDetails,UMEnabled,LitigationHoldEnabled,SingleItemRecoveryEnabled,LitigationHoldDate,LitigationHoldOwner,LitigationHoldDuration,RetainDeletedItemsFor| foreach-object{
        #Begin ForLoop

            #*** Increment Counters and Write to Screen
            $i++
            Write-Host "$($i) Mailbox(s) processed . . ."

            #*** Gather AD and Mailbox Attributes and send to reporting function ***

            $ADUser=(Get-ADUser $_.guid -Properties department,company,title,lastlogondate,extensionAttribute1,extensionAttribute2,extensionAttribute3,extensionAttribute4,extensionAttribute5)
            $Department=$Aduser.department
            $Company=$ADUser.company
            $JobTitle=$aduser.title
            $LastLogonDate=$Aduser.LastLogonDate
            $EA1=$Aduser.extensionAttribute1
            $EA2=$Aduser.extensionAttribute2
            $EA3=$Aduser.extensionAttribute3
            $EA4=$Aduser.extensionAttribute4
            $EA5=$Aduser.extensionAttribute5
            
            #*** Start Hash System Object for Report ***

            $obj=new-object System.Object
            $obj|add-member -membertype NoteProperty -name "ObjectGuid" -value $_.Guid
            $obj|add-member -membertype NoteProperty -name "ExchangeGuid" -value $_.ExchangeGuid
            $obj|add-member -membertype NoteProperty -name "SamAccountName" -value $_.SamAccountName
            $obj|add-member -membertype NoteProperty -name "UserPrincipalName" -value $_.UserPrincipalName
            $obj|add-member -membertype NoteProperty -name "DisplayName" -value $_.DisplayName
            $obj|add-member -membertype NoteProperty -name "Company" -value $Company
            $obj|add-member -membertype NoteProperty -name "Department" -value $Department
            $obj|add-member -membertype NoteProperty -name "JobTitle" -value $JobTitle
            $obj|add-member -membertype NoteProperty -name "PrimarySmtpAddress" -value $_.PrimarySMTPAddress
            $obj|add-member -membertype NoteProperty -name "Database" -value $_.Database
            $obj|add-member -membertype NoteProperty -name "EA1" -value $EA1
            $obj|add-member -membertype NoteProperty -name "EA2" -value $EA2
            $obj|add-member -membertype NoteProperty -name "EA3" -value $EA3
            $obj|add-member -membertype NoteProperty -name "EA4" -value $EA4
            $obj|add-member -membertype NoteProperty -name "EA5" -value $EA5
            $obj|add-member -membertype NoteProperty -name "LastLogonDate" -value $LastLogonDate
            $obj|add-member -membertype NoteProperty -name "RecipientType" -value $_.RecipientType
            $obj|add-member -membertype NoteProperty -name "RecipientTypeDetails" -value $_.RecipientTypeDetails
            $obj|add-member -membertype NoteProperty -name "LitigationHoldEnabled" -value $_.LitigationHoldEnabled
            $obj|add-member -membertype NoteProperty -name "SingleItemRecoveryEnabled" -value $_.SingleItemRecoveryEnabled
            $obj|add-member -membertype NoteProperty -name "LitigationHoldDate" -value $_.LitigationHoldDate
            $obj|add-member -membertype NoteProperty -name "LitigationHoldOwner" -value $_.LitigationHoldOwner
            $obj|add-member -membertype NoteProperty -name "LitigationHoldDuration" -value $_.LitigationHoldDuration
            $obj|add-member -membertype NoteProperty -name "RetainDeletedItemsFor" -value $_.RetainDeletedItemsFor
            $obj|add-member -membertype NoteProperty -name "UMEnabled" -value $_.UMEnabled

            #*** Gather Mailbox Statistics Attributes ***

                Try{ #TRY002 FN-PM


                    
                    $ItemCount=(Get-MailboxStatistics -Identity $_.DisplayName).ItemCount
                    $TotalItemSize=(Get-MailboxStatistics –identity $_.DisplayName).totalitemsize.value.ToMB()

                    $obj|add-member -membertype NoteProperty -name "ItemCount" -value $ItemCount
                    $obj|add-member -membertype NoteProperty -name "TotalItemSize" -value $TotalItemSize

                    }
                    catch
                    { #CATCH002 FN-PM

                    $LogData =
                    @{

                        Name = $ADUser.name
                        GUID = $ADuser.ObjectGUID
                        DN = $ADuser.DistinguishedName
                        TargetName = $_.CategoryInfo.TargetName
                        Exception= $_.Exception.Message
                        Error0=$Error[0]
                        Error1=$Error[1]
                        Error2=$Error[2]
                        Code = 'Error'
                        TryIndex = '002 FN-PM'

                    }#End Splat

                    [Array]$Invocation= $_.InvocationInfo
                    Write-Log -LogData $LogData -InvocationError $Invocation
                    } #END #CATCH 002 FN-PM
                

            #Check if the mailbox has an archive & Gather stats if exists

            if(($_.ArchiveGuid -ne "00000000-0000-0000-0000-000000000000")){

                Try{ #TRY003 FN-PM

                    $ArchiveItemCount=(Get-MailboxStatistics -Identity $_.DisplayName -Archive).ItemCount
                    $ArchiveTotalItemSize=(Get-MailboxStatistics –identity $_.DisplayName -Archive).totalitemsize.value.ToMB()
                    $obj|add-member -membertype NoteProperty -name "ArchiveItemCount" -value $ArchiveItemCount
                    $obj|add-member -membertype NoteProperty -name "ArchiveTotalItemSize" -value $ArchiveTotalItemSize

                    }
                    catch
                    { #CATCH003 FN-PM

                    $LogData = #Begin Splat
                    @{

                        Name = $ADUser.name
                        GUID = $ADuser.ObjectGUID
                        DN = $ADuser.DistinguishedName
                        TargetName = $_.CategoryInfo.TargetName
                        Exception= $_.Exception.Message
                        Error0=$Error[0]
                        Error1=$Error[1]
                        Error2=$Error[2]
                        Code = 'Error'
                        TryIndex = '003 FN-PM'

                    } #End Splat

                    [Array]$Invocation= $_.InvocationInfo
                    Write-Log -LogData $LogData -InvocationError $Invocation

                    } #END Catch003 FN-PM

            } #END IF (ArchiveGUID)
            
            # *** If the 1st user doesnt have an archive these members need adding to the hash object before its commited to CSV in Build-Report ***
            else
                {
                 $obj|add-member -membertype NoteProperty -name "ArchiveItemCount" -value ""
                 $obj|add-member -membertype NoteProperty -name "ArchiveTotalItemSize" -value ""
            }

            $CombinedTotal=$TotalItemSize+$ArchiveTotalItemSize
            $obj|add-member -membertype NoteProperty -name "CombinedTotalSize" -value $CombinedTotal

            # *** These are added so that the $obj template first committed to the log file report
            # *** by Build-Report has all headings added.  Later the Check-Delegates function will add these
            # *** headings.  If they werent first added here then Check-Delegates could not subsequently 
            # *** add them in. 
            
            $obj|add-member -membertype NoteProperty -name "DelegateName" -value ""
            $obj|add-member -membertype NoteProperty -name "DelegateEmail" -value ""
            $obj|add-member -membertype NoteProperty -name "DelegateAccess" -value ""
            $obj|add-member -membertype NoteProperty -name "FolderPath" -value ""
            $obj|add-member -membertype NoteProperty -name "GroupExists" -value ""
            $obj|add-member -membertype NoteProperty -name "FolderPath" -value ""
            $obj|add-member -membertype NoteProperty -name "CurrentStatus" -value ""
            $obj|add-member -membertype NoteProperty -name "EEComments1" -value ""
            $obj|add-member -membertype NoteProperty -name "EEComments2" -value ""
            $obj|add-member -membertype NoteProperty -name "BDOComments1" -value ""
            $obj|add-member -membertype NoteProperty -name "BDOComments2" -value ""

            #*** Sends $OBJ array to the Build-Report function**

            Build-Report -Obj $obj


             # *** Send to Log Function ***

            If ($IncludeMailboxAccess -eq $true) {

                $LogData=
                @{
                    Code="SUCCESS"
                    GUID=$_.Guid
                    DisplayName=$_.displayname
                    FriendlyText="Interrogating Mailbox:"

                 } #END Splat

               
                # *** Find mailbox access permissions and log ***

                Write-Log -LogData $LogData
                
                $Delegates = @()
                $Delegates = (Get-MailboxPermission $_.DistinguishedName | Where { $DelegatesToSkip -notcontains $_.User -and $_.IsInherited -eq $false })
                    If ($Delegates -ne $null) {
                        ForEach ($Delegate in $Delegates) {
                            $DelegateAccess = $Delegate.AccessRights
                            Check-Delegates -DelegateID $Delegate.User -objectguid $_.guid -DisplayName $_.Displayname -DelegateAccess $DelegateAccess -PriSMTP $_.PrimarySMTPAddress}}}

                # *** Find SendAs permissions and log ***

                If ($IncludeSendAs -eq $true) {
                    $Delegates = @()
                    $Delegates = Get-ADPermission $_.DistinguishedName | Where { $DelegatesToSkip -notcontains $_.User -and $_.ExtendedRights -like "*send-as*" }
                If ($Delegates -ne $null) {
                    ForEach ($Delegate in $Delegates) {
                    $DelegateAccess = "SendAs" 
                    Check-Delegates -DelegateID $Delegate.User -objectguid $_.guid -DisplayName $_.Displayname -DelegateAccess $DelegateAccess -PriSMTP $_.PrimarySMTPAddress} } }

                 # *** Find SendOnBehalf permissions ***

                If ($IncludeSendOnBehalf -eq $true) {
                    $Delegates = @()
                    $Delegates = (Get-Mailbox $_.DistinguishedName).GrantSendOnBehalfTo
                    If ($Delegates -ne $null) {
                        ForEach ($Delegate in $Delegates) {
                            $DelegateAccess = "SendOnBehalfOf"
                            Check-Delegates -DelegateID $Delegate -objectguid $_.guid -DisplayName $_.Displayname -DelegateAccess $DelegateAccess -PriSMTP $_.PrimarySMTPAddress} } } 

                   # *** Export folder permissions ***
            Try{
                If ($IncludeFolderDelegates -eq $true) {
                    If ($IncludeCommonFoldersOnly -eq $true) { $Folders = Get-MailboxFolderStatistics $_.DistinguishedName | Where { $_.FolderPath -eq "/Top of Information Store" -or $_.FolderPath -eq "/Inbox" -or $_.FolderPath -eq "/Calendar" } }
                    Else { $Folders = Get-MailboxFolderStatistics $_.DistinguishedName }
                    ForEach ($Folder in $Folders) {
                        $FolderPath = $Folder.FolderPath.Replace("/","\")
                        If ($FolderPath -eq "\Top of Information Store") { $FolderPath = "\" }
                        [String]$PrimaryEmail=$_.PrimarySMTPAddress
                        $FolderLocation = $PrimaryEmail + ":" + $FolderPath
                        $FolderPermissions = Get-MailboxFolderPermission $FolderLocation -ErrorAction SilentlyContinue
                        If ($FolderPermissions -ne $null) {
                            ForEach ($Permission in $FolderPermissions) {
                                [string]$FolderDelegate = $Permission.User
                                If ($FolderDelegate -ne "Default" -and $FolderDelegate -ne "Anonymous") {
                                       $CheckDelegate = Get-Recipient $FolderDelegate -ErrorAction SilentlyContinue
                                    If ($CheckDelegate -ne $null) {
                                        $DelegateName = $CheckDelegate.Name
                                        $DelegateEmail = $CheckDelegate.PrimarySmtpAddress
                                        [String]$DelegateAccess = $Permission.AccessRights
                                        If ($DelegateName -ne $_.DisplayName) { 
                                                        $obj=new-object System.Object
                                                        $obj|add-member -membertype NoteProperty -name "ObjectGuid" -value $_.guid
                                                        $obj|add-member -membertype NoteProperty -name "ExchangeGuid" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "ArchiveGuid" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "SamAccountName" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "UserPrincipalName" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "DisplayName" -value $_.DisplayName
                                                        $obj|add-member -membertype NoteProperty -name "Company" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "Department" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "JobTitle" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "PrimarySmtpAddress" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "Database" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "ItemCount" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "TotalItemSize" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "ArchiveItemCount" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "ArchiveTotalItemSize" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "CombinedTotalSize" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "EA1" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "EA2" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "EA3" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "EA4" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "EA5" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "LastLogonDate" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "RecipientType" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "RecipientTypeDetails" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "DelegateName" -value $DelegateName
                                                        $obj|add-member -membertype NoteProperty -name "DelegateEmail" -value $DelegateEmail
                                                        $obj|add-member -membertype NoteProperty -name "DelegateAccess" -value $DelegateAccess
                                                        $obj|add-member -membertype NoteProperty -name "FolderPath" -value $FolderPath
                                                        $obj|add-member -membertype NoteProperty -name "GroupExists" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "LitigationHoldEnabled" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "SingleItemRecoveryEnabled" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "LitigationHoldDate" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "LitigationHoldOwner" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "LitigationHoldDuration" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "RetainDeletedItemsFor" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "UMEnabled" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "BatchName" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "CurrentStatus" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "EEComments1" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "EEComments2" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "BDOComments1" -value ""
                                                        $obj|add-member -membertype NoteProperty -name "BDOComments2" -value ""
                                                        

                                                        #*** Send data to log and screen ***

                                                        $LogData=
                                                        @{
                                                             DelegateName=$DelegateName
                                                             DelegateAccess=$DelegateAccess
                                                             Mailbox=$_.PrimarySMTPAddress
                                                             Folder=$FolderPath
                                                             Code="FolderAccess"

                                                        } #END Splat

                                                        #*** Send to Log Function ***

                                                        Write-Log -LogData $LogData

                                                        #*** Send Array to report function ***

                                                        Build-Report -obj $obj
                                                        
                                                        # *** Closes for all IFs from Export Folder Permissions ***
                                                         } } } } } }}
}
                    catch
                    { #CATCH003 FN-PM

                    $LogData =
                    @{

                        Name = $ADUser.name
                        GUID = $ADuser.ObjectGUID
                        DN = $ADuser.DistinguishedName
                        TargetName = $_.CategoryInfo.TargetName
                        Exception= $_.Exception.Message
                        Error0=$Error[0]
                        Error1=$Error[1]
                        Error2=$Error[2]
                        Code = 'Error'
                        TryIndex = '003 FN-PM'

                    }#End Splat

                    [Array]$Invocation= $_.InvocationInfo
                    Write-Log -LogData $LogData -InvocationError $Invocation
                    } #END #CATCH 003 FN-PM
 
              
            } #END IF (MailboxAccess Check)
      
        } #END Function

Would be nice to do it more efficiently, any ideas very welcomed :slight_smile:

Thanks

Stuart

Good Lord that is an awful lot of Add-Member! Also, you’re not creating arrays. You’re creating hashtables. Important difference. Arrays look like this:

$array = 1, $val2, "val3"
#or
$array = @(1, $val2, "val3")

They’re just a list of values. You’d access each value by index number:

$array[0] = 1
$array[1] = $val2
$array[2] = "val3"

Hashtables let you assign names to each value. Technically they’re called keys, because you access them like this:

$hashtable = @{Key = "value"}
$hashtable['key'] = "value"

But for most purposes they’re so similar to standard objects in PS, although they work much quicker.

Okay, so you can do something very simple about that (using the first example from your post):

$obj = [PsCustomObject] @{
    ObjectGuid        = $_.Guid
    ExchangeGuid      = $_.ExchangeGuid
    SamAccountName    = $_.SamAccountName
    UserPrincipalName = $_.UserPrincipalName
    DisplayName       = $_.DisplayName
}

Basically, this is pretty straightforward. It takes the hashtable as input to create an object with those same properties. It is significantly faster than repeatedly using Add-Member. Additionally, it’s generally recommended to use PsCustomObject over System.Object or PsObject. For the vast majority of cases, you’ll have a much easier time dealing with the PsCustomObject types than the other alternatives, and they have this neat use case as well.

Additionally, any object that is given to Add-Member, Select-Object, etc. will typically be transformed into the PsCustomObject type – it’s just part of how it works – so you may as well have it be that to start with to save the processor from having to bother converting it each time. :slight_smile:

great advice thank you. Its so heavy it kills my Exchange EMS session after about 3000 mailboxes!

I will try to incorporate PSCustomObject in the way you suggested, thanks again.

Have a nice Easter (if yr in the UK!)

Haven’t reviewed it all but just from a quick glance, yes definately start using hashtables for the attributes rather than doing add-member.

From a general code perspective it’s a good time to start breaking up the code into seperate functions.
The Process-Mailboxes function could most likely (from my quick check) be broken up into 7 or 8 seperate functions rather than one huge function.
E.g. all the seperate tests could be their own functions.

There is also quite a few places where you have code duplications, e.g. in the “Find SendAs”, “Find Onbehalf” etc.
You should try to avoid duplications as far as you can since it may catch you later down the road.

Also try to avoid using nested IF statements as far as possible.
I try to have a single IF level at all times, in rare cases one level more.
If it goes beyond that then I’m asking the wrong question or I need to do more work before that IF (e.g. seperate function).
Reason is that it’s really difficult to maintain and read nested IF’s.
In some cases what you thought you were checking became something completely different because of the data returned/used in the IF statement.

I’ve done the misstakes above and most likely everyone else at some point.
But if you want it to look better, work better and be easier to maintain, you need to break the code down into smaller pieces.

Give yourself a challange, e.g. a function can not have more than 30 lines of code.
Don’t use it as a rule but just something to strive for.

Don’t use ? in scripts as an alias foreach-object

A quick glance at your code suggests that a lot of the object creation could be done with select-object

? is an alias for Where-Object, but yes in general aliases like this tend to obscure your script a bit much. Stick to full names unless you want to spend three times as long trying to read through your script when you need to debug it! :slight_smile:

THanks very much for all the comments. I am going to use hash tables and also try to split it up into smaller functions.