Submenu

This topic contains 0 replies, has 1 voice, and was last updated by  Forums Archives 5 years, 7 months ago.

  • Author
    Posts
  • #5989

    by vandreytrindade at 2012-12-27 09:47:42

    Hi,

    I'm trying to build a menu that contains all of my Office 365 and Exchange Online scripts.
    I've managed to make a simple one:

    cls
    $Loop = $true
    While ($Loop){
    write-host
    write-host "`tOffice 365 and Exchange Online management console"
    write-host
    write-host "`t1) Show hidden distribution lists" -ForegroundColor Yellow
    write-host "`t2) Show distribution lists with only 1 member" -ForegroundColor Yellow
    write-host "`t3) Exit" -ForegroundColor Yellow
    write-host

    $opt = Read-Host "`tChoose an option [1-3]"
    if ($opt -gt 3){
    cls
    write-host
    write-host "`tYou've entered an option that doesn't exists... Please try again." -ForegroundColor Red
    Write-Host
    pause
    cls
    $Loop = $true
    }
    switch ($opt)

    {
    1{
    cls
    Write-Host
    Write-Host "Verifying which distribution lists are hidden..." -ForegroundColor Yellow
    $listas = Get-DistributionGroup | Where-Object {($_.hiddenfromaddresslistsEnabled -eq "True")}
    Write-Host
    Write-Host "The hidden distribution lists are:" -ForegroundColor Yellow
    Write-Host
    foreach ($list in $lists){$list.DisplayName}
    Write-Host
    Write-Host
    Write-Host
    Write-Host "Finished!" -ForegroundColor Yellow
    Write-Host
    pause
    cls
    }

    2{
    cls
    Write-Host
    Function Main {
    Write-Host
    Write-Host "Starting gathering data..." -ForegroundColor Yellow
    Write-Host
    Write-Host "The distribution lists with only 1 member are:" -ForegroundColor Yellow
    Write-Host
    $objDistributionGroups = Get-DistributionGroup -ResultSize Unlimited
    Foreach ($objDistributionGroup in $objDistributionGroups){
    $objDGMembers = Get-DistributionGroupMember -Identity $($objDistributionGroup.PrimarySmtpAddress)
    if ($(@($objDGMembers).count) -eq 1){Write-Host "`t"$($objDistributionGroup.DisplayName)}
    }
    Write-Host
    Write-Host "Finished!" -ForegroundColor Yellow
    Write-Host
    pause
    cls
    }
    . Main
    }

    3{
    $Loop = $true
    cls
    exit
    }
    }
    }

    How can I add submenus to that menu?

    I'd like to do something like this:

    Menu:

    1) Manage distribution lists
    2) Manage users
    3) Exit

    If user chooses option 1, then:

    Distribution lists

    1) Show hidden distribution lists
    2) Show distribution lists with only 1 member
    3) Return to main menu

    Thx

    by nohandle at 2012-12-28 09:13:08

    I think you should go with something less hrdcoded.
    Just playing around because this is interesting concept few people mentioned recently. I am probably gonna place it in module or somthing (or maybe somebody already created a module to do just this.) But I have to really think it through before I do. Anyway I started with this:
    [xml]$mainMenu = @"
    < ?xml version="1.0"?>

    Main Menu

    get-process
    Invoke
    Get-Process | select -first 2


    Sub Menu
    Submenu

    Sub Menu 1

    Get-Item
    Invoke
    Get-Item .


    Sub Menu 2
    Submenu

    Sub Menu 2

    Get-Item
    Invoke
    Get-Item .





    "@

    Function Write-Menu ($menu)
    {
    function Write-MenuItem ($key, [string]$name, [String]$ActionType)
    {
    $item = "[{0}] {1}" -f $key, $name
    if ($ActionType -eq 'Submenu')
    {
    $item += "..."
    }
    $item
    }
    $menuRoot = $menu.menu
    Write-Output $menuRoot.name
    '=' * 20
    $items = @($menuRoot.item)
    For ($index = 0 ; $index -lt $items.length; ++$index)
    {
    #arrays are indexed from 0
    Write-MenuItem -key ($index+1) -name $items[$index].name -ActionType $items[$index].ActionType
    }
    "`nChoose from previous options or"
    if ($Script:__CurrentPosition) {"[*] Return to previous"}
    if (-not ($Script:__CurrentPosition)) {"[e] Exit"}
    }

    function Wait-KeyPress($prompt='Press a key!')
    {
    #http://powershell.com/cs/blogs/tips/archive/2009/07/08/wait-for-key-press.aspx
    Write-Host $prompt
    do {
    Start-Sleep -milliseconds 100
    } until ($Host.UI.RawUI.KeyAvailable)

    $Host.UI.RawUI.FlushInputBuffer()
    }

    function Process-Menu ($option, $menu)
    {

    $menuRoot = $menu.menu
    $items = @($menuRoot.item)
    #items are indexed from 1 but array from 0

    #to enable also non number items every nonnumber condition must exit the flow by return or similar
    if (($option -eq '*') -and ($Script:__CurrentPosition))
    {
    #navigate one level up
    $levelup = $script:__CurrentMenu.get_ParentNode().get_ParentNode().get_ParentNode()
    if ($levelUp)
    {
    $script:__CurrentMenu = $levelUp
    --$Script:__CurrentPosition
    }
    return
    }
    If (($option -eq 'e') -and (-not $Script:__CurrentPosition))
    {
    #exit
    break
    }

    try
    {

    $index = $option-1
    if ($items[$index].ActionType -eq 'Submenu')
    {
    #navigate to submenu
    $script:__CurrentMenu=$items[$index].Action
    ++$Script:__CurrentPosition
    }
    if ($items[$index].ActionType -eq 'Invoke')
    {
    Invoke-Expression $items[$index].action
    Wait-KeyPress "Press any key to continue ..."
    }
    }
    catch [System.Management.Automation.RuntimeException]
    {}

    }

    function New-Menu ($menu)
    {
    $Script:__CurrentMenu = $Menu
    $Script:__CurrentPosition = 0
    while ($True)
    {
    clear-host

    Write-Menu -menu $Script:__CurrentMenu
    Process-Menu -option (Read-Host) -menu $script:__CurrentMenu

    }
    }
    New-menu $mainMenu

    the Wait-Keypress does not work properly in PowerGui (and probably also ise)

    by vandreytrindade at 2013-01-03 08:02:54

    Hey nohandle,

    You're again trying to rescue me =p
    Sorry for taking so long to answer but, I didn't recieved any mail saying that someone posted a reply for my topic.

    Nice to know that you found it interesting...
    I use the script u gave me to check and it works... but I was not able to understand it in a level that I could modify it for my personal use... lol

    Now I'm thinking about doing some simple menu, that calls another scipt with other simple menu... will try to see if it works.

    Thx or your time!

    by nohandle at 2013-01-04 04:10:54

    Hi,
    [code2=xml]

    Main Menu

    get-process
    Invoke
    Get-Process | select -first 2

    [/code2]
    You just need to change the layout and the actions in the xml to suite your needs. You create menu space that can contain one or more items. each item specifies its name, its action type
    invoke -> the expression in action is invoked
    submenu -> that says that the action will specify another

    that follows the same principles. and adds "..." to the name to distinguish the submenu from the invoke.

    Enabling you to create one or more layers of menu in (relatively) easy manner.

    It was just quick prototype so the architecture is quite bad 🙂

You must be logged in to reply to this topic.