CommandCentral.psm1
<# .DESCRIPTION Provides a easy to use and customizable menu to launch scripts with repetitve parameters (i.e. passwords, hostnames, options), additionally provides automation capabilities for running jobs. .NOTES Version: 1.0 Author: Admiral-AI Portfolio: https://github.com/Admiral-AI Creation Date: January 4, 2024 #> function Start-CCMain { # Set script location variable (removes ambiguity and makes testing easier) Set-Variable -Name scriptLocation -Scope Script $scriptLocation = $PSScriptRoot # Set starting location (should'nt be an issue but I wanted peace of mind) Set-Location $scriptLocation # Import settings file and set the variable to script access (indicates that all scripts run from this one can access the variable when passed) Set-Variable -Name settingsFile -Scope Script try { $settingsFile = Get-Content .\etc\settings.json -ErrorAction Stop | ConvertFrom-Json } catch { Write-Host "Setting file is unreadable, please re-download the script or fix your setting file" Start-Sleep 2 exit } # Set transcript log path based on json setting file parameter Start-Transcript -Path $($settingsFile.CCScriptSettings.Logging.Log_Path) -Append -Force # Set the debug prefrence based on the logging setting $DebugPreference = $($settingsFile.CCScriptSettings.Logging.DebugPreference) # Clear the console Clear-Host # Start the domino effect of functions: $continueChainHop1_Boolean = Update-CCDependencies if ($continueChainHop1_Boolean -eq $true) { $returnHashTable = Enable-CCVault Set-Variable -Name userVaultPassword -Scope Script $userVaultPassword = $returnHashTable.userInputPassword $continueChainBoolean_Hop2 = $returnHashTable.continueChainBoolean_Hop2 } if ($continueChainBoolean_Hop2 -eq $true) { $continueChainBoolean_Hop3 = Start-CCJobs } if ($continueChainBoolean_Hop3 -eq $true) { Out-CCMenu | Out-Null } # Script will return here when you quit the menu function at the end of the script # Reset location before exiting Set-Location $scriptLocation # Stop Transcript when finished with script Stop-Transcript } function Update-CCDependencies { $restartScriptBoolean = $false # Command Central script updater if ($settingsFile.CCScriptSettings.Updates.CC_UpdatesOptIn -eq $true) { # Initialize some settings into variables for cleanliness $selectedRepo = $settingsFile.CCScriptSettings.Updates.CC_UpdateSettings.SelectedRepo $repoUriToPullFrom = $settingsFile.CCScriptSettings.Updates.CC_UpdateSettings.Repositories.$($selectedRepo).CCScriptUri $repoAccessToken = $settingsFile.CCScriptSettings.Updates.CC_UpdateSettings.Repositories.$($selectedRepo).AuthToken $repoUriType = $settingsFile.CCScriptSettings.Updates.CC_UpdateSettings.Repositories.$($selectedRepo).UriType $repoAccessAPI = $settingsFile.CCScriptSettings.Updates.CC_UpdateSettings.Repositories.$($selectedRepo).AccessAPI if ($true -eq $false) { # Catch-22 } elseif ($repoUriType -match "HTTPS") { # Used for matching against HTTP(S) URLs if (($repoAccessAPI -match 'GitHub')) { # Actions to take if Repository API is github if ($null -ne $repoAccessToken) { $webHeadersForRepo = @{ "Accept" = "application/vnd.github.raw+json" "Authorization" = "Bearer $($repoAccessToken)" "X-GitHub-Api-Version" = "2022-11-28" } } else { $webHeadersForRepo = @{ "Accept" = "application/vnd.github.raw+json" "X-GitHub-Api-Version" = "2022-11-28" } } try { $returnedCCScriptData = Invoke-RestMethod -Method Get -Uri $repoUriToPullFrom -Headers $webHeadersForRepo -ErrorAction Stop } catch { Write-Error "Could not access the Url provided, check that the file exists and the token is valid" } # Do a plain Get request if no supported domain is matched or auth token is found } else { $returnedCCScriptData = Invoke-RestMethod -Method Get -Uri $repoUriToPullFrom } } elseif ($repoUriType -match "SMB") { # Used for matching against SMB URLs try { $returnedCCScriptData = Get-Content -Path $repoUriToPullFrom -Raw } catch { Write-Error "Could not access the Url provided, check that the file and/or share exists" } } # Take the retrieved data and check if different from local copy if ($null -ne $returnedCCScriptData) { $currentCCScriptData = Get-Content -Path $($PSCommandPath) -Raw # Use Compare-Object to compare the contents of the two variables $comparisonResults = Compare-Object -ReferenceObject ($currentCCScriptData) -DifferenceObject ($returnedCCScriptData) if ($null -eq $comparisonResults) { Write-Host "No updates found." # If the variable is not null then the comparison found differences, the else statement will run updates } else { Write-Host "Update found! Updating local script." try { $returnedCCScriptData | Out-File -FilePath $($PSCommandPath) -NoNewline -ErrorAction Stop $restartScriptBoolean = $true } catch { Write-Error "Could not write update to file, check the log for details" $restartScriptBoolean = $false } } } else { # Update script variable was empty indicating a problem Write-Error "Updates failed, check the log for details." } } else { Write-Debug "Script updates are not enabled..." } # PowerShell module dependency installer and updater if ($settingsFile.CCScriptSettings.Updates.PSModules_UpdatesOptIn -eq $true) { # Initialize some settings into variables for cleanliness $modulePropertiesFromSettings = $settingsFile.CCScriptSettings.Updates.PSModules_UpdateSettings.Modules $modulePropertyNamesFromSettings = $modulePropertiesFromSettings | Get-Member -MemberType Properties $modulePropertyNamesFromSettings.Name | ForEach-Object { # Make sure to save the version number as a [System.Version] object for proper boolean results $moduleUpdateParams = @{ Name = $($modulePropertiesFromSettings.$($_).Name) MinimumVersion = [System.Version]$($modulePropertiesFromSettings.$($_).MinimumVersion) MaximumVersion = [System.Version]$($modulePropertiesFromSettings.$($_).MaximumVersion) RequiredVersion = [System.Version]$($modulePropertiesFromSettings.$($_).RequiredVersion) Repository = $($modulePropertiesFromSettings.$($_).Repository) Credential = $($modulePropertiesFromSettings.$($_).Credential) Scope = $($modulePropertiesFromSettings.$($_).Scope) SkipPublisherCheck = $($modulePropertiesFromSettings.$($_).SkipPublisherCheck) Force = $($modulePropertiesFromSettings.$($_).Force) AllowPrerelease = $($modulePropertiesFromSettings.$($_).AllowPrerelease) AcceptLicense = $($modulePropertiesFromSettings.$($_).AcceptLicense) Confirm = $($modulePropertiesFromSettings.$($_).Confirm) } # Install-Module does not play nicely with null values when splatting, remove null values @($moduleUpdateParams.Keys) | ForEach-Object { if ($null -eq $moduleUpdateParams[$_]) { $moduleUpdateParams.Remove($_) } } $currentlyInstalledModule = Get-InstalledModule | Where-Object {($_.Name -eq $($moduleUpdateParams.Name)) -and ($_.Repository -eq $($moduleUpdateParams.Repository))} if ($null -ne $currentlyInstalledModule) { if ($true -eq $false) { } elseif ($null -ne $moduleUpdateParams.RequiredVersion) { if ([System.Version]$currentlyInstalledModule.Version -eq $moduleUpdateParams.RequiredVersion) { Write-Debug "$($moduleUpdateParams.Name) is installed with the correct version, skipping update" $updateCurrentModule = $false } else { Write-Debug "$($moduleUpdateParams.Name) is installed without the correct version, updating module" $updateCurrentModule = $true $removeCurrentModule = $true } } elseif (($null -ne $moduleUpdateParams.MinimumVersion) -or ($null -ne $moduleUpdateParams.MaximumVersion)) { if ($true -eq $false) { } elseif (($null -ne $moduleUpdateParams.MinimumVersion) -and ($null -ne $moduleUpdateParams.MaximumVersion)) { $minimumBoolean = ([System.Version]$currentlyInstalledModule.Version -ge $moduleUpdateParams.MinimumVersion) $maximumBoolean = ([System.Version]$currentlyInstalledModule.Version -le $moduleUpdateParams.MaximumVersion) if (($minimumBoolean -eq $true) -and ($maximumBoolean -eq $true)) { $updateCurrentModule = $false } else { $updateCurrentModule = $true } } elseif (($null -ne $moduleUpdateParams.MinimumVersion) -and ($null -eq $moduleUpdateParams.MaximumVersion)) { if ([System.Version]$currentlyInstalledModule.Version -ge $moduleUpdateParams.MinimumVersion) { $updateCurrentModule = $false } else { $updateCurrentModule = $true } } elseif (($null -ne $moduleUpdateParams.MaximumVersion) -and ($null -eq $moduleUpdateParams.MinimumVersion)) { if ([System.Version]$currentlyInstalledModule.Version -le $moduleUpdateParams.MaximumVersion) { $updateCurrentModule = $false } else { $updateCurrentModule = $true } } } elseif (($null -eq $moduleUpdateParams.MinimumVersion) -and ($null -eq $moduleUpdateParams.MaximumVersion) -and ($null -eq $moduleUpdateParams.RequiredVersion)) { Write-Debug "Module: $($moduleUpdateParams.Name) is installed as evidenced by Get-InstalledModule but no version is specified, no further work needed" $updateCurrentModule = $false } else { Write-Debug "You shouldn't end up here, check the log, `$moduleUpdateParams variable, and Get-InstalledModule cmdlet for issues" } } else { Write-Host "Module: $($moduleUpdateParams.Name) not found, installing..." $updateCurrentModule = $true } if ($updateCurrentModule -eq $true) { try { if ($removeCurrentModule -eq $true) { Uninstall-Module -Name $moduleUpdateParams.Name -AllVersions -ErrorAction SilentlyContinue } Install-Module @moduleUpdateParams -ErrorAction Stop Write-Host "Updated/Installed Module: $($moduleUpdateParams.Name)" } catch { Write-Error "Updating/Installing module: $($moduleUpdateParams.Name); Failed, check the log for details" } } else { Write-Debug "Module not updated: $($moduleUpdateParams.Name)" } } } else { Write-Debug "Powershell module updates are not enabled..." } # Custom dependency installer and updater (AD, Keepass app, e.t.c.) if ($settingsFile.CCScriptSettings.Updates.Custom_UpdatesOptIn -eq $true) { } else { Write-Debug "App updates are not enabled..." } # Script restarter (uses $restartScriptBoolean) if ($restartScriptBoolean -eq $true) { if (($PSVersionTable.PSEdition -like "Core") -and ($IsWindows -eq $true)) { Write-Host "Automatic script restart is broken at this time, please restart the script manually." Start-Sleep .75 # Write-Host "The script will now restart to apply updates..." # Start-Process pwsh -ArgumentList "-File `"$($PSCommandPath)`"" } elseif (($PSVersionTable.PSEdition -like "Core") -and ($IsWindows -ne $true)) { # Start-Process pwsh is broken in powershell Core on non-windows platforms # To-do: Find a workaround Write-Host "Automatic script restart is not supported for Linux & MacOS, please restart the script manually." Start-Sleep .75 } Write-Host "CommandCentral will now exit" exit } else { # No updates were found, return true in order to head to vault setup return $true } } function Enable-CCVault { # Initialize vault reset function function Reset-CCVault { if ($true -eq $false) { # Keepass secret vault provider is selected (default): } elseif ($settingsFile.CCScriptSettings.PasswordVault.ExtensionProvider -eq "KeePass") { $vaultPath = Join-Path -Path $scriptLocation -ChildPath "var/PasswordVault.kdbx" if ($settingsFile.CCScriptSettings.PasswordVault.Provider_KeePass.VaultAuthMethod -eq "Password") { # Request and validate a password $requestPasswordLoopControlBoolean = $true while ($requestPasswordLoopControlBoolean -eq $true) { $userInputPassword = Read-Host -Prompt "Enter a password for the database" -MaskInput # To-do: Validate the password based on the setting file requirements if ($true -eq $true) { $userInputPassword = ConvertTo-SecureString -String $userInputPassword -AsPlainText $requestPasswordLoopControlBoolean = $false } } } # If the path test returns true then there is a vault there already, rename it to prevent an error when creating a new one. if ((Test-Path -Path $vaultPath) -eq $true) { # Format: MM = month; dd = day; yy = 2 digit year; HH = hour; mm = minute; tt = AM/PM Move-Item $vaultPath "./var/ResetVault_$(Get-Date -Format MMddyy_HHmmtt).kdbx" } $installedVaults = Get-SecretVault | Where-Object { $_.Name -eq "CommandCentral_PasswordVault"} if ($null -ne $installedVaults) { Unregister-SecretVault -Name "CommandCentral_PasswordVault" } if ($settingsFile.CCScriptSettings.PasswordVault.Provider_KeePass.VaultAuthMethod -eq "Password") { Register-KeePassSecretVault -Name "CommandCentral_PasswordVault" -Path $vaultPath -UseMasterPassword -MasterPassword $userInputPassword -Create } elseif (($settingsFile.CCScriptSettings.PasswordVault.Provider_KeePass.VaultAuthMethod -eq "WindowsAccount")) { Register-KeePassSecretVault -Name "CommandCentral_PasswordVault" -Path $vaultPath -UseWindowsAccount -Create } Write-Host "We will now test the vault functions, please re-input the password if needed" $vaultTestBoolean = Test-SecretVault -Name CommandCentral_PasswordVault if ($vaultTestBoolean -eq $true) { Write-Host "Vault is ready for use" } else { Write-Error "There shouldn't be an error here" Write-Error "Something is critically wrong with the vault and/or module" Write-Host "Exiting Script..." Start-Sleep 2 exit } return $userInputPassword } } # Set vault password to script scope Set-Variable -Name userInputPassword -Scope Script # Validate vault setup $installedVaults = Get-SecretVault | Where-Object { $_.Name -eq "CommandCentral_PasswordVault"} if ($null -eq $installedVaults) { $userInputPassword = Reset-CCVault } else { $vaultTestBoolean = $true while ($vaultTestBoolean -eq $true) { # Statement block for keepass vault providers if ($settingsFile.CCScriptSettings.PasswordVault.ExtensionProvider -ne "KeePass") { $vaultTestBoolean = Test-Path $installedVaults.VaultParameters.Path if ($true -eq $false) { } elseif ($settingsFile.CCScriptSettings.PasswordVault.Provider_KeePass.VaultAuthMethod -eq "Password") { Write-Host "We will now test the vault functions, please input your vault password." $userInputPassword = Read-Host -Prompt "-->" -AsSecureString Unlock-SecretVault -Name CommandCentral_PasswordVault -Password $userInputPassword } elseif ($settingsFile.CCScriptSettings.PasswordVault.Provider_KeePass.VaultAuthMethod -eq "WindowsAccount") { # No need for testing, windows account auth will unlock the vault automatically Write-Host "We will now test the vault functions using your windows account." } } # All vault providers continue here by testing the vault if ($vaultTestBoolean -eq $true) { $vaultTestBoolean = Test-SecretVault -Name CommandCentral_PasswordVault } # If the test is succesful, continue here if ($vaultTestBoolean -eq $true) { Write-Host "Vault is ready for use" $vaultTestBoolean = $false } else { Start-Sleep 2 Clear-Host Write-Host "Vault failed the function test" Write-Host "Do you want to retry your password?" Write-Host "Or do you want to reset the vault?" Write-Host "Options: Reset or Retry. (Retry is default)" Write-Host "" $userInputChoice = Read-Host "[retry]-->" if ($userInputChoice -like "reset") { $userInputPassword = Reset-CCVault $vaultTestBoolean = $false } } } } $returnHashTable = @{ continueChainBoolean_Hop2 = $true userInputPassword = $userInputPassword } return $returnHashTable } function Start-CCJobs { if ($settingsFile.CCScriptSettings.CCJobs.CCJobs_OptIn -eq $true) { # Initialize settings for cleanliness $jobListPropertiesFromSettings = $settingsFile.CCScriptSettings.CCJobs.JobsList $sessionThreads = $settingsFile.CCScriptSettings.CCJobs.ThrottleLimit # Get each job name from the properties $jobNamesFromSettings = $jobListPropertiesFromSettings | Get-Member -Type Properties # Run each job in the setting file in parallel $jobNamesFromSettings.Name | ForEach-Object { $currentJobParams = @{ Name = $jobListPropertiesFromSettings.$($_).Name ScriptBlock = [Scriptblock]::Create($jobListPropertiesFromSettings.$($_).ScriptBlock) FilePath = $jobListPropertiesFromSettings.$($_).FilePath ArgumentList = $jobListPropertiesFromSettings.$($_).ArgumentList StreamingHost = $jobListPropertiesFromSettings.$($_).StreamingHost Authentication = $jobListPropertiesFromSettings.$($_).Authentication CCVault_Credential = $jobListPropertiesFromSettings.$($_).CCVault_Credential PSVersion = $jobListPropertiesFromSettings.$($_).PSVersion RunAs32 = $jobListPropertiesFromSettings.$($_).RunAs32 WorkingDirectory = $jobListPropertiesFromSettings.$($_).WorkingDirectory } # Start-Job does not play nicely with null values when splatting, remove null values @($currentJobParams.Keys) | ForEach-Object { if ($null -eq $currentJobParams[$_]) { $currentJobParams.Remove($_) } } try { if ($jobListPropertiesFromSettings.$($_).ThreadJob -eq $true) { Start-ThreadJob @currentJobParams -ThrottleLimit $sessionThreads -ErrorAction Stop | Out-Null } else { Start-Job @currentJobParams -ErrorAction Stop | Out-Null } } catch { Write-Error "CCJob: $($jobNamesFromSettings.Name) threw an error, please check the job configuration and test before re-running it" } } } else { Write-Debug "Jobs are not enabled..." } return $true } function Out-CCMenu { if ($settingsFile.CCScriptSettings.Menu.Menu_OptIn -eq $true) { ## Initial retrieval & setup of settings ## # Check settings if we should use ASCII only when displaying menu options if ($settingsFile.CCScriptSettings.Menu.Menu_GridGUIEnable -eq $true) { $forceMenuGUI_Enable = $true } else { $forceMenuGUI_Enable = $false } # Set the starting directory to the location of the 'bin' directory $workingDirectory = Join-Path -Path $scriptLocation -ChildPath $settingsFile.CCScriptSettings.FolderPaths.bin $startingDirectory = $workingDirectory ## Clear screen and display logo from file or simple logo, then wait for input ## Clear-Host $firstLogo = Get-Content -Path "$($scriptLocation)\etc\logo" $logoLength = $firstLogo[0].Length if (($host.UI.RawUI.WindowSize.Width -ge $logoLength)-and ($host.UI.RawUI.WindowSize.Height -ge $firstLogo.Length)) { $firstLogo | ForEach-Object { Write-Host "$($_)" } } else { Write-Host "*Command*Central*" } Write-Host -NoNewLine 'Press any key to continue...'; $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown'); Write-Host "" $menuLoopControlBoolean = $true while ($menuLoopControlBoolean -eq $true) { Clear-Host # Nullify values so previous menus wont be brought into the next one $childItems_Folders = $null $childItems_PS1Files = $null $childItems_AllItems = $null $csvItems_AllItems = $null $menuEntriesRecords = $null # Set location Set-Location $workingDirectory ## Get storage contents and menu csv to build menu hashtable ## $childItems_Folders = Get-ChildItem -Directory $childItems_PS1Files = Get-ChildItem -Filter "*.ps1" # Combine all storage files into a single array $childItems_AllItems = @() foreach ($folderEntry in $childItems_Folders) { $childItems_AllItems += $folderEntry } foreach ($ps1FileEntry in $childItems_PS1Files) { $childItems_AllItems += $ps1FileEntry } # Attempt to find menu csv file try { $csvItems_AllItems = Import-Csv -Path ./MenuStructure.csv -ErrorAction Stop # Cast the position column to interger format from string $csvItems_AllItems | ForEach-Object { $_.Position = [int]$_.Position } $csvItems_AllItems = $csvItems_AllItems | Sort-Object -Property Position -Descending } catch { Write-Debug "Menu structure csv file was not found for the following directory: $($workingDirectory)" } $menuEntriesRecords = @() # Build the menu entries from the postive (first) positions in the csv foreach ($entry in $csvItems_AllItems) { if (($entry.Position) -gt 0) { $pathTest = Test-Path -Path $($entry.FileName) if ($pathTest -eq $true ) { $menuEntriesRecords += [pscustomobject] @{ Position = $($entry.Position) Option = $($entry.Option) FileName = $($entry.FileName) Description = $($entry.Description) } } else { Write-Debug "" Write-Error "Menu csv contains invalid entry:" Write-Debug "Path: $($workingDirectory)" Write-Debug "Entry: $($entry)" } } } # Now add entries that arent in the csv from the disk contents foreach ($diskEntry in $childItems_AllItems) { $skipDiskAdd_Boolean = $false foreach ($csvEntry in $csvItems_AllItems) { if ($csvEntry.FileName -clike $diskEntry.Name) { $skipDiskAdd_Boolean = $true break } } if ($skipDiskAdd_Boolean -eq $false) { $menuEntriesRecords += [pscustomobject] @{ Position = 0 Option = $($diskEntry.Name) FileName = $($diskEntry.Name) Description = "N/A" } } } # Finally, add the entries with negative (last) positions foreach ($entry in $csvItems_AllItems) { if (($entry.Position) -lt 0) { $pathTest = Test-Path -Path $($entry.FileName) if ($pathTest -eq $true ) { $menuEntriesRecords += [pscustomobject] @{ Position = $($entry.Position) Option = $($entry.Option) FileName = $($entry.FileName) Description = $($entry.Description) } } else { Write-Debug "" Write-Error "Menu csv contains invalid entry:" Write-Debug "Path: $($workingDirectory)" Write-Debug "Entry: $($entry)" } } } # Add in the quit option if the starting and working directories match if ($startingDirectory -eq $workingDirectory) { $menuEntriesRecords += [pscustomobject] @{ Position = $null Option = "Quit" FileName = $null Description = $null } } else { $menuEntriesRecords += [pscustomobject] @{ Position = $null Option = "Go Back" FileName = $null Description = $null } } if ($forceMenuGUI_Enable -eq $true) { try { $ccMenuSelectedOption = $menuEntriesRecords | Select-Object Option, Description | Out-ConsoleGridView -Title "CommandCentral GUI" -OutputMode Single -ErrorAction Stop if ($null -eq $ccMenuSelectedOption) { $ccMenuSelectedOption = "Refresh" } else { $ccMenuSelectedOption = $menuEntriesRecords | Where-Object { ($_.Option -eq $ccMenuSelectedOption.Option) -and ($_.Description -eq $ccMenuSelectedOption.Description) } } } catch { Write-Debug "Current terminal does not support Microsoft.PowerShell.ConsoleGuiTools, or the module is not installed, or it ran into an error" $forceMenuGUI_Enable = $false $ccMenuSelectedOption = "Refresh" } } else { $loopNum = 1 Write-Host "Key: #) Name, Description" Write-Host "" foreach ($menuOption in $menuEntriesRecords) { if (($null -eq $($menuOption.Description)) -or ($($menuOption.Description) -like "")) { Write-Host "$($loopNum)) $($menuOption.Option)" } else { Write-Host "$($loopNum)) $($menuOption.Option), $($menuOption.Description)" } $loopNum++ } Write-Host "" $ccMenuSelectedOption = Read-Host -Prompt "Select an option" # Convert the number/letter back into a option that can be used (same as the console grid view output) if ($ccMenuSelectedOption -like "") { $ccMenuSelectedOption = "Refresh" } elseif (($ccMenuSelectedOption -like "Quit") -or ($ccMenuSelectedOption -like "Q")) { if ($startingDirectory -eq $workingDirectory) { $ccMenuSelectedOption = $menuEntriesRecords | Where-Object { $_.Option -like "Quit" } } else { $ccMenuSelectedOption = "Refresh" Write-Host "" Write-Host "Invalid Choice" Start-Sleep 1.5 } } elseif (($ccMenuSelectedOption -like "Go Back") -or ($ccMenuSelectedOption -like "Back") -or ($ccMenuSelectedOption -like "B")) { if ($startingDirectory -ne $workingDirectory) { $ccMenuSelectedOption = $menuEntriesRecords | Where-Object { $_.Option -like "Go Back" } } else { $ccMenuSelectedOption = "Refresh" Write-Host "" Write-Host "Invalid Choice" Start-Sleep .75 } } elseif ( ($([int]$ccMenuSelectedOption) -le $($menuEntriesRecords.Count)) -and ([int]$ccMenuSelectedOption -ge 1)) { $ccMenuSelectedOption = $menuEntriesRecords[(($ccMenuSelectedOption) - 1)] } else { $ccMenuSelectedOption = "Refresh" Write-Host "" Write-Host "Invalid Choice" Start-Sleep .75 } } # Special test for folders if ($null -ne $($ccMenuSelectedOption.FileName)) { $isFolder_Boolean = Test-Path -Path $($ccMenuSelectedOption.FileName) -PathType Container } # After menu selection, begin determining what to do (switch directories, execute, or simply do nothing) if ($ccMenuSelectedOption -like "Refresh") { # Do nothing } elseif ($ccMenuSelectedOption.Option -like "Quit") { Write-Host "" Write-Host "Quiting..." Start-Sleep .5 $menuLoopControlBoolean = $false } elseif ($ccMenuSelectedOption.Option -like "Go Back") { $workingDirectory = $workingDirectory | Split-Path -Parent } elseif ($($isFolder_Boolean) -eq $true) { # Matched on folder $workingDirectory = Join-Path -Path $workingDirectory -ChildPath $($ccMenuSelectedOption.FileName) } elseif ($($ccMenuSelectedOption.FileName) -like "*.ps1") { # Matched on ps1 file . ".\$($ccMenuSelectedOption.FileName)" } } } else { Write-Debug "Menu is not enabled..." } } |