Author Posts

January 1, 2012 at 12:00 am

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 🙂