General setup and configuration questions

Product: PowerShell Universal
Version: 1.4.6

Hello,

Like most IT departments, we have a number of scheduled tasks that check various things that then end up as an email report. Looking to replace those tasks with PSU and provide a way to give people the ability to run adhoc scripts etc.

I’ve just started using PowerShell Universal (PSU) however I’m struggling to understand a few things and was wondering if someone could point me in the right direction.

So far I’ve been able to create some basic scripts and get the output on a page by setting the “Portal output” to a table in the script settings. However how do I do the same for scheduled tasks?

Also, when the results from a script are outputted to the page, the object’s property names are changed, i.e. if my results has a property called “ComputerName”, it shows as “Computer Name”. It seems to do this for all property names. Is there any way to stop this or adjust the behavior?

The default Portal page is set to “Services”. Is there any way to customize this page? or set a different page as default?

Widets, what are they and how do I use them? How do they differ from scripts? When I create a page there is an option to add a widget but everything I try just results in nothing being saved and a blank page.

APIs - I understand what an API is but I’m not understanding why I would use them in the context of PSU? If I can run scripts and scheduled tasks why do I need an API? Is this just to allow an external service to trigger a script / code? I’d be curious to know how are people are using them and under what context?

I’m finding the documentation a challenge. I’ve been watching videos etc, however, everything seems to be out of date. I watched one video from about 12 months ago talking about setting up a Dashboard but when I look at my PSU, there are no dashboards?!

How do I go about having pages appear in the left hand menu as links to pages? I’d like to organise pages / dashboards based on their services; AD, Azure, Exchange, etc is this possible?

What is everyone doing for your naming conventions to organise scripts, pages, etc?

Any help is greatly appreciated.
Thanks
Garry

Hi Garry,
There’s a lot to get your head around in PSU, but its worth the time invested in it.
It’s changed a lot of the years and months and it’s always being added to which is great, though certainly there’s lots of outdated resources out there, so stick to the official documentation here: https://docs.powershelluniversal.com/ and you should be fine. For any thing else, posts in these forums are generally answered by the community.

The ‘Portal’ is pretty much quite a basic/dumb page for giving access to others to run scripts and see output without the full back end ‘admin’ section. You can group things together with ‘Tags’ that may do what you need with grouping based on service e.g AD, Entra, Exchange… Though it sounds like if you want more customization (especially when it comes to the navigation menu) you should look into creating an ‘App’ with ‘Pages’, that way you can push your script data to a sql table, or other destination (cache, file, etc etc) and then read that data into a New-UDTable for example, which has much more customization for how the columns show, ability to filter, search, export, and so on.

API’s are used for many different things, but generally speaking it’s typically so something external can trigger scripts or code, but it doesn’t have to be. It can also be a centralized place for your Apps (previously referred to as Dashboards) to also call, rather than repeating code in multiple apps (though you can also use modules and functions for that too).

One great use for an API is if it’s completing an action and fulfiing a task, you can provide that API to other teams to use so that the action is completed in a conform way, they just have to provide the input parameters and they get output, the rest is a black box. It’s also language agnostic that way too, if someone wants to use python, powershell, or javascript etc, they can call the same API without worrying about what code the API itself is actually written in. There’s many use cases though.

As for organizing scripts and pages. I use Apps and provide teams with only the access they need so they see the pages relevant to them - same with the Portal. As an admin, who can view everything, I see it all, but it’s split by team. My scripts are tagged to each team for organization in the portal, and my apps have submenus for each team too. On the file structure side, I just split pages, and scripts into subfolders by team, and subfolders in that by service.

Hi Insomniacc,

Thanks for the feedback..lots to digest.

I’m can see the potential of PSU so excited to learn it.

Do you have any good links to examples of creating apps?

Thanks
Garry

Hi @garryo ,

This was for me the second most interesting features (besides scripts), so we do not need to change the language skills to something else to expose custom scripts very easily as APIs.
Some practical example:

  • we have a custom script doing some group management clean up stuff which has some configuration file for mappings
  • in the past this needed to be updated manually in a psd1 file - not always the best way for 1st level supporters :wink:
  • I created an App in PSU that is the Support Agent’s new web interface to manage the configuration file, where the app handles only the pure presentation logic
  • The necessary “backend” functions, like (e.g. lookup existing groups, show existing config entries, update entries, add entries) where put into HTTPS API calls, the PSU App just requests as any other application would do. This gives us the greatest flexibility and makes the functions re-usable by any other app that now needs to request e.g. groups.

I feel you, I had to go through this as well. For some stuff the documentation is also not too much detailed and you have to dig yourself still into this quite a lot…
It’s also a little scattered over this forum, Github tickets, the KB pages, Videos, …
But I think the learning curve is steep.

Best,
Matthias

Hey Matthias,

Thanks for the feedback!

Cheers
Garry

1 Like

Hi Garry,

Welcome - Powershell universal is an awesome tool, but there is a bit of a learning curve, mostly due to the many changes it has gone through. People have already given you great advice, but I’ll add a little bit extra.

Dashboards has been renamed to Apps. So anytime you see it mentioned, just know it’s called apps now. You will also see changes in code, like
New-UDDashboard is now an alias for New-UDApp. If you use AI to write code, it will mostly use the Alias - So make sure to punk it on the head and tell it to use the newest version of powershell universal (as of this writing v5+)

If you haven’t started using VScode with the Powershell universal Extension, then this would be the first step honestly. It makes developing scripts, API’s and apps a breeze.

If you are working on an app, then any change you save inside of this extension can be seen right away on the live app. Love this feature.

To get you started off with an App that uses Pages, here is a simple code for that. I created this POC for my service desk team to try and sell them on the idea. I’ve removed the majority of the bulk code, so you only have the navigation:

## Navigation menu ##
$Navigation = @(

    New-UDList -Children {

        New-UDListItem -Label "Home" -Icon $(New-UDIcon -Icon 'home' -Size 3x ) -Href "/"
        New-UDListItem -Label "User Administration" -Icon $(New-UDIcon -Icon 'user-astronaut' -Size 3x ) -Children {
            New-UDListItem -Label "Create User" -Href '/Create' 
            New-UDListItem -Label "Delete User" -Href '/Delete' 
            New-UDListItem -Label "Modify User" -Href '/Modify' 
            New-UDListItem -Label "User Overview" -Href '/Overview'
            #New-UDListItem -Label "Purchasing" -Href '/purchasing' 
        }
        New-UDListItem -Label "Devices" -Icon $(New-UDIcon -Icon 'Laptop' -Size 3x ) -Children {
            New-UDListItem -Label "Devices Compliance table" -Href "/DevicesCompliancetable"
            New-UDListItem -Label "Devices Compliance Charts" -Href "/DevicesComplianceCharts"
        }

        New-UDListItem -Label "Ad-Hoc" -Icon $(New-UDIcon -Icon 'Wrench' -Size 3x ) -Children {
            New-UDListItem -Label "Devices NetworkDrivers table" -Href "/DevicesNetworkDriversTable"
            New-UDListItem -Label "Devices NetworkDrivers Charts" -Href "/DevicesNetworkDriversCharts"
        }

    }

    
)

$Pages = @()

## All contents for the different Pages goes below ###
$Pages += New-UDPage -Name 'home' -Content {
    #New-UDTypography -Text "Home Page"

    
    New-UDGrid -Container -Content {
        # Left Panel
        New-UDGrid -Item -ExtraSmallSize 12 -SmallSize 3 -Content {
            New-UDPaper -Elevation 2 -Content {
                
                New-UDGauge -Width 300 -Height 200 -Value 20 -ValueMinimum 0 -ValueMaximum 28 -StartAngle 0 -EndAngle 180 -CornerRadius "10px" -InnerRadius "50%" -OuterRadius "100%" -ArchCenterX "50%" -ArchCenterY "50%" -Style @{ color = "blue"; 'gaugeClasses.valueText' ='40' }
                                
            }
        }

        # Center Panel (Top and Bottom)
        New-UDGrid -Item -ExtraSmallSize 12 -SmallSize 6 -Content {
            New-UDGrid -Container -Content {
                # Top Center Panel
                New-UDGrid -Item -ExtraSmallSize 12 -Content {
                    New-UDPaper -Elevation 2 -Content {
                        New-UDTypography -Text "Top Center Panel Content"


                    }
                }
                # Bottom Center Panel
                New-UDGrid -Item -ExtraSmallSize 12 -Content {
                    New-UDPaper -Elevation 2 -Content {
                        #New-UDTypography -Text "Bottom Center Panel Content"
                        $changes = @(
                            [PSCustomObject]@{ Date = [DateTime]::Parse('2025-05-13'); Title = 'Dark Mode';              Description = 'Added dark mode toggle to settings.' }
                            [PSCustomObject]@{ Date = [DateTime]::Parse('2025-04-30'); Title = 'Performance Fix';       Description = 'Faster dashboard load times. Increased by 40%.' }
                            [PSCustomObject]@{ Date = [DateTime]::Parse('2025-03-15'); Title = 'New Reporting API';    Description = 'Expose metrics endpoint for external tools.' }
                        )
                        
                        
                        New-UdTable -Title "What’s New" -Data $changes -Columns @(
                        New-UdTableColumn -Property Date        -Title 'Date'
                        New-UdTableColumn -Property Title       -Title 'Feature'
                        New-UdTableColumn -Property Description -Title 'Details'
                        ) -PageSize 5
                    }
                }
            }
        }

        # Right Panel
        New-UDGrid -Item -ExtraSmallSize 12 -SmallSize 3 -Content {
            New-UDPaper -Elevation 2 -Content {
                New-UDTypography -Text "Right Panel Content"
            }
        }
    }

} -DefaultHomePage

$Pages += New-UDPage -Name 'Create' -Content {
    New-UDTypography -Text "Create"

}

$Pages += New-UDPage -Name 'Delete' -Content {
    New-UDTypography -Text "Usage"
} 

$Pages += New-UDPage -Name 'Modify' -Content {
    New-UDTypography -Text "Modify"
} 

$Pages += New-UDPage -Name 'Overview' -Content {
    
    New-UDTypography -Text "Overview"
    
}

$Pages += New-UDPage -Name 'DevicesCompliancetable' -Content {
    
    New-UDTypography -Text "DevicesComplianceTable"

}

$Pages += New-UDPage -Name 'DevicesComplianceCharts' -Content {
    
    New-UDTypography -Text "DevicesComplianceCharts"

} 

$Pages += New-UDPage -Name 'DevicesNetworkDriversTable' -Content {

    New-UDTypography -Text "DevicesNetWrokDriversTable"

} 

$Pages += New-UDPage -Name 'DevicesNetworkDriversCharts' -Content {
    
    New-UDTypography -Text "DevicesNetWrokDriversCharts"
    
} 

## Putting all the data above inside of our app
New-UDApp -Title "Service Desk" -Pages $Pages -Navigation $Navigation -NavigationLayout Permanent

You can also lock your pages with the:

Protect-UDSection -Content {

    New-UDTypography 'Admins Only'

 } -Role @("Administrator")

But I have not played around with this one yet.

Hi Coconuts,

Thanks for the tips and the code. That is exactly the sort of thing I was looking for, appreciate you sharing

I also just installed the vscode extensions as you suggested.

As I’m just starting out there is a lot to take in. I’m just working through the doco now but I’m sort of limited to working on this in my spare time at nights so my leaning is going as fast as I’d like it :slight_smile:

Cheers
Garry

1 Like