Search code examples
powershellactive-directoryoffice365powershell-4.0powershell-remoting

Creating Powershell menu Item and calling functions in the menu item


I am trying to combine the below snippets into the existing code for updating user AD attributes.

Add-Type -AssemblyName 'Microsoft.VisualBasic'

Do
{
    Write-Host -Object 'Enter a sAMAccountName / Alias "First.Lastname", or nothing (Press Enter) to leave; wildcards and a space separated list are NOT supported.' -ForegroundColor Yellow
    
    $UserInput = [Microsoft.VisualBasic.Interaction]::InputBox('Enter the User AD account to check', 'sAMAccountName / Alias "First.Lastname"', $UserInput)
    
    If ($UserInput)
    {
        $(ForEach ($Username in $UserInput.Split(' ', [StringSplitOptions]::RemoveEmptyEntries))
            {
                If ($ADUser = Get-ADUser -Filter { samAccountName -like $UserName } -Properties DisplayName)
                {
                    Write-Verbose -Message "Processing $($ADUser.DisplayName)"
                    Write-Host "The sAMAccountName $($UserInput) matching to the AD account '$($ADUser.DisplayName)'" -ForegroundColor Green
                    
                    
                    
                }
                Else
                {
                    Write-Host "Could not find a user with a sAMAccountName matching '$($UserName)' !" -ForegroundColor Red | Write-Warning
                }
            })
    }
}
Until (-not $UserInput)

The snippets above are working for validating user input against the Active Directory user account, to see if the AD account is valid or not.

This is the main menu item code which is used for updating the AD attributes based on the https://answers.microsoft.com/en-us/msoffice/forum/msoffice_o365admin-mso_exchon-mso_o365b/recipient-type-values/7c2620e5-9870-48ba-b5c2-7772c739c651

# Set The attributes value for Remote Regular User Mailboxes
$replace = @{
      msExchRemoteRecipientType = 4
      msExchRecipientDisplayType = -2147483642
      msExchRecipientTypeDetails = 2147483648
}

# Set The attributes value for Remote Shared Mailboxes
$replace = @{
      msExchRemoteRecipientType = 100
      msExchRecipientDisplayType = -2147483642
      msExchRecipientTypeDetails = 34359738368
}
Set-ADUser -Identity $ADUser -Replace $replace -WhatIf 

This is the main menu item code, but without the input check validation section:

If (!(Get-Module "*ActiveDirectory*")) {
    Try { Import-Module ActiveDirectory -ErrorAction Stop }
    Catch { Write-Warning "Unable to load Active Directory module because $($Error[0])"; Exit }
}

Add-Type -AssemblyName 'Microsoft.VisualBasic'
$Input = [Microsoft.VisualBasic.Interaction]::InputBox('Enter the User AD account to check', 'sAMAccountName / Alias "First.Lastname"', $Input)

$properties = 'Name,msExchRemoteRecipientType,msExchRecipientDisplayType,msExchRecipientTypeDetails,proxyAddresses' -split ','
$ADUserAttributesValues = Get-ADUser -identity $Input -Properties $properties |
                            Select-Object Name,
                                          msExchRemoteRecipientType,
                                          msExchRecipientDisplayType,
                                          msExchRecipientTypeDetails

$menuCaption = "Hybrid AD User account Exchange attribute modification"
$menuMessage = "Please select the action to be applied to the user $($Input) `n $($ADUserAttributesValues)"
        ## Format: "Menu Text" = "Help Text"
        ## "Menu Text" must match the options in the Switch statement below
        ## "&" marks the character to use as hotkey

$menu = [ordered]@{
    'Remote &Shared Mailbox' = "Convert $($Input) as Remote Shared Mailbox"
    'Remote &User Mailbox'   = "Convert $($Input) as Remote User Mailbox"
    '&Quit'                  = 'Leave without changes'
}

$menuChoices = @()
$menu.Keys | ForEach-Object {
    $choice = [System.Management.Automation.Host.ChoiceDescription]$_
    $choice.HelpMessage = $menu[$_]
    $menuChoices += $choice
}

$answer = $host.UI.PromptForChoice($menuCaption , $menuMessage , $menuChoices, ($menu.Count - 1))
Switch ($menuChoices[$answer].Label) {
    'Remote &Shared Mailbox' {
        Clear-Host
        Write-Host "You selected to convert $($Input) as Remote Shared Mailbox" -ForegroundColor Yellow
        
        # Set The attributes value for Remote Shared Mailboxes
        $replace = @{
            msExchRemoteRecipientType = 100
            msExchRecipientDisplayType = -2147483642
            msExchRecipientTypeDetails = 34359738368
        }
        Set-ADUser -Identity $ADUserAttributesValues.Name -Replace $replace -WhatIf
        
        # Check the attributes value
        Get-ADUser -identity $Input -Properties $properties |
            Select-Object Name,
                          msExchRemoteRecipientType,
                          msExchRecipientDisplayType,
                          msExchRecipientTypeDetails,
                          (@{Label = 'Email Address'; Expression = {($_.proxyAddresses | Where-Object {($_ -like 'SMTP*') -and ($_ -notlike '*onmicrosoft.com') } | Sort-Object -CaseSensitive -Descending | ForEach-Object {$_.Split(':')[1]}) -join ', ' }})
    }
    'Remote &User Mailbox' {
        Clear-Host
        Write-Host "You selected to convert $($Input) as Remote User Mailbox" -ForegroundColor Yellow
        
        # Set The attributes value for Remote Regular User Mailboxes
        $replace = @{
            msExchRemoteRecipientType = 4
            msExchRecipientDisplayType = -2147483642
            msExchRecipientTypeDetails = 2147483648
        }
        Set-ADUser -Identity $ADUserAttributesValues.Name -Replace $replace -WhatIf
        
        # Check the attributes value
        Get-ADUser -identity $Input -Properties $properties |
            Select-Object Name,
                          msExchRemoteRecipientType,
                          msExchRecipientDisplayType,
                          msExchRecipientTypeDetails,
                          (@{Label = 'Email Address'; Expression = {($_.proxyAddresses | Where-Object {($_ -like 'SMTP*') -and ($_ -notlike '*onmicrosoft.com') } | Sort-Object -CaseSensitive -Descending | ForEach-Object {$_.Split(':')[1]}) -join ', ' }})
    }
    default {
        Write-Host 'Goodbye' -ForegroundColor Green
        Exit
    }
}

So how to combine it to the above?

The code above was created as a rough menu item with lots of repetitions, but it works. I believe it can be optimized by creating functions, but not sure how since the attributes are different.


Solution

  • If you want to combine the code snippets using helper functions, here's an idea for you:

    if (!(Get-Module "*ActiveDirectory*")) {
        Try { Import-Module ActiveDirectory -ErrorAction Stop }
        Catch { Write-Warning "Unable to load Active Directory module because $($Error[0])"; Exit }
    }
    
    # function to ask the user which user to update.
    # returns either a valid AD including mailbox attributes user or nothing at all
    function Prompt-User {
        Add-Type -AssemblyName 'Microsoft.VisualBasic'
        # enter an endless loop
        while ($true) {
            Clear-Host
            $msg = "Enter the User AD account to check.`r`n`r`nWildcards and a space separated list are NOT supported."
            Write-Host $msg -ForegroundColor Yellow
    
            $account = [Microsoft.VisualBasic.Interaction]::InputBox($msg, 'sAMAccountName / Alias "First.Lastname"')
    
            # exit the function if the user entered nothing or whitespace only
            if ([string]::IsNullOrWhiteSpace($account)) { return }
    
            $properties = 'DisplayName','msExchRemoteRecipientType','msExchRecipientDisplayType','msExchRecipientTypeDetails'
    
            $ADUser = Get-ADUser -Filter "samAccountName -like '$account'" -Properties $properties -ErrorAction SilentlyContinue
            if ($ADUser) {
                Write-Host "The sAMAccountName $($account) matches the AD account '$($ADUser.DisplayName)'" -ForegroundColor Green
                return $ADUser
            }
            else {
                Write-Warning "Could not find a user with a sAMAccountName matching '$($account)' ! Please try again."
            }
        }
    }
    
    # function to ask the user what action to undertake
    function Prompt-Action ([Microsoft.ActiveDirectory.Management.ADUser]$ADUser) {
        $menuCaption = "Hybrid AD User account Exchange attribute modification"
        $menuMessage = "Please select the action to be applied to the user $($ADUser.Name)"
                ## Format: "Menu Text" = "Help Text"
                ## "Menu Text" must match the options in the Switch statement below
                ## "&" marks the character to use as hotkey
    
        $menu = [ordered]@{
            'Remote &Shared Mailbox' = "Convert $($Input) as Remote Shared Mailbox"
            'Remote &User Mailbox'   = "Convert $($Input) as Remote User Mailbox"
            '&Quit'                  = 'Leave without changes'
        }
    
        $menuChoices = $menu.Keys | ForEach-Object {
            $choice = [System.Management.Automation.Host.ChoiceDescription]$_
            $choice.HelpMessage = $menu[$_]
            $choice
        }
    
        $answer = $host.UI.PromptForChoice($menuCaption , $menuMessage , $menuChoices, ($menu.Count - 1))
    
        return ($menuChoices[$answer].Label -replace '&')  # removing the '&' makes processing later easier
    }
    
    # function to display users Mailbox attributes
    function Get-UserMailboxDetails ([string]$DistinguishedName) {
        $properties = 'msExchRemoteRecipientType','msExchRecipientDisplayType','msExchRecipientTypeDetails','proxyAddresses'
        Get-ADUser -Identity $DistinguishedName -Properties $properties -ErrorAction SilentlyContinue |
        Select-Object msExchRemoteRecipientType,
                      msExchRecipientDisplayType,
                      msExchRecipientTypeDetails,
                      @{Label = 'Email Address'; Expression = {
                        ($_.proxyAddresses | Where-Object {($_ -like 'SMTP*') -and ($_ -notlike '*onmicrosoft.com') } | 
                        Sort-Object -CaseSensitive -Descending | ForEach-Object {$_.Split(':')[1]}) -join ', ' }}
    }
    
    # checks the current user mailbox type
    # returns 'Remote User Mailbox', 'Remote Shared Mailbox' or 'Other'
    function Check-MailboxAttributes ([Microsoft.ActiveDirectory.Management.ADUser]$ADUser) {
        if ($ADUser.msExchRemoteRecipientType -eq 4 -and 
            $ADUser.msExchRecipientDisplayType -eq -2147483642 -and 
            $ADUser.msExchRecipientTypeDetails -eq 2147483648) { 'Remote User Mailbox' }
        elseif (
            $ADUser.msExchRemoteRecipientType -eq 100 -and
            $ADUser.msExchRecipientDisplayType -eq -2147483642 -and
            $ADUser.msExchRecipientTypeDetails -eq 34359738368) { 'Remote Shared Mailbox' }
        else { 'Other' }
    }
    
    # this is your main code
    do {
        $ADUser = Prompt-User
        if ($ADUser) {
            Clear-Host
            # here is where you process the user
            $action = Prompt-Action $ADUser
            if ($action -like 'Remote*') {  # either 'Remote Shared Mailbox' or 'Remote User Mailbox'
                # do we need to convert the user mailbox type?
                if ((Check-MailboxAttributes $ADUser) -eq $action) {
                    Write-Host "$($ADUser.DisplayName) is already a $action" -ForegroundColor Yellow
                }
                else {
                    Write-Host "You selected to convert $($ADUser.DisplayName) as $action" -ForegroundColor Yellow
                    if ($action -match 'User') { 
                        # create hashtable for Remote Regular User Mailboxes
                        $newProperties = @{ 
                            msExchRemoteRecipientType  = 4
                            msExchRecipientDisplayType = -2147483642
                            msExchRecipientTypeDetails = 2147483648
                        }
                    } 
                    else { 
                        # create hashtable for Remote Shared Mailboxes
                        $newProperties = @{
                            msExchRemoteRecipientType  = 100
                            msExchRecipientDisplayType = -2147483642
                            msExchRecipientTypeDetails = 34359738368
                        }
                    }
                    $ADUser | Set-ADUser -Replace $newProperties
                    # reload the user and show the resulting mailbox properties
                    Get-UserMailboxDetails $ADUser.DistinguishedName
                }
            }
        }
    } until (-not $ADUser)
    
    # all done
    Write-Host 'Goodbye' -ForegroundColor Green
    

    I agree with postanote that I would create a proper GUI for this rather than using Write-Host stuff in the console