PowerShell Universal. Why I strongly discourage you from purchasing it.

Sep 22, 2021 | Powershell, reviews, Scripting and programming, Server administration, Technology, Windows | 1 comment

PowerShell Universal should be a fantastic tool. A single language used for admin tasks, the UI, scheduling etc. I was delighted to find it!

But after a year of trying and trying again with some success but many many more failures, I’m finally giving up. I was willing to pass it off as a lack of experience with PowerShell when I started first. I’m certainly no master at it now either. But when something simply works in the console but refuses to work in PowerShell Universal over and over again, even I start to wonder if it’s not just me.

I won’t bombard you with examples. But here’s one:

$ApplicationFilter = @{
LogName = 'Application'
ID = 1000, 4005, 0
StartTime = [datetime]::Today.AddDays(-1)
EndTime = [datetime]::Today
$SystemFilter = @{
LogName = 'System'
ID = 2004, 6008
StartTime = [datetime]::Today.AddDays(-1)
EndTime = [datetime]::Today

$ServerList = Get-RDSessionHost -CollectionName mecheng -ConnectionBroker ((Servername.FQDN))
ForEach ($Server in $ServerList.SessionHost) {
try {
$Result = Get-WinEvent -ComputerName $Server -FilterHashtable $ApplicationFilter -ErrorAction Ignore | Select LogName, Level, ProviderName, TimeCreated, MachineName -ExpandProperty Properties

$Result += Get-WinEvent -ComputerName $Server -FilterHashtable $SystemFilter -ErrorAction Ignore | Select LogName, Level, ProviderName, TimeCreated, MachineName -ExpandProperty Properties
catch [Exception] {
if ($_.Exception -match "No events were found that match the specified selection criteria") {
Write-Host "No events found";
Return $Result

Simple enough. This fetches application and system events from RDS session hosts in a specific collection on a given RDS connection broker. It doesn’t use any kind of custom object. It just returns the output in a standard object. But still, although this works perfectly in PowerShell 5 and 7, it doesn’t work in PowerShell Universal. I get a completely strange error relating to the connection broker.

It’s not just this script. I have at least another dozen that work perfectly fine in the console but don’t work at all in PowerShell Universal.

Today I found that I couldn’t get any output at all from these scripts unless I configured them to use the default environment. Not PS5 or 7. That’s new.

Ironman software decided last year that they could no longer support me. Here’s the message from back then.

It’s becoming apparent that this solution is not working for you and I do not have the ability to continue to support your installation of it.

I realize that you have had lot’s of problems but that is what is making me realize that you should investigate another vendor. I apologize that we did not suite your needs.

I hate to be so negative about a small company. I have nothing against them personally. But I think the feedback I’m providing to them and to you is just the responsible thing to do. I see so many people with requests here and so many answers to the effect that there’s a bug, or something will work again in the next version. There’s no doubt in my mind that the product has improved in the past year. But I think it’s just too complicated in it’s design to be reliable. In my opinion, they should stop releasing new features for about 6 months and just focus on making things work and updating the documentation.

If I thought this had a chance of working , I would have put in more hours. I’ve already put in hundreds of hours trying to make this work for me. I see the potential. But without good support from Ironman software and with the inconsistency in so many parts of the tool, I need to just conclude that this is just a failed test.

Some of the features that drew me to this tool are:

  • Easily create API’s with PowerShell
  • Run PowerShell scripts on a schedule using various environments and credentials
  • Use centrally stored variables
  • Store the output of various jobs
  • Easily integrate with active directory for authentication
  • Quickly build UI’s

An example of where I was able to use this effectively last year was during several security sprints. I scheduled a script to go around all of our servers and collect the inbound firewall rules. It stored the job results so that I could then compare job 1 with job 50 for example to see what had changed. I then provided a UI with the number of inbound firewall rules for each server and gave people the ability to drill down to each server to specifically see what firewall rules were listed.

I missed the first two security sprints because I had problems where Universal wasn’t working as expected. But when it worked, it worked really well.

So I’m not saying that there isn’t a need for this product. If there wasn’t a need, I wouldn’t be so frustrated writing this post.

The fact is, it’s just not reliable. I have written a rather large module for me and others in my team to use. Each function produces an object. It works flawlessly. The way I usually plan out what would be nice to have in Universal is I’ll write my functions in this module, let the senior admins use them for a while then I’ll create scripts that call them in PowerShell Universal so that they can either be scripted or a UI can be wrapped around them for more junior people to use. A great example is the above script. I have that so that I can quickly check the status of these RDS session host servers. But my plan was to make a quick UI for it. I would run the script on a schedule then display the output from the last execution. This means the UI opens much faster resulting from the script running a few moments previously in the background. But then something senseless happens that throws a completely unexpected error in PowerShell Universal and what should take 15 to 20 minutes ends up taking me hours.

I urge caution if you are buying this. It’s not very expensive. But the hours I spent trying to make it work cost a lot more. It took me a long time to come to the decision to give up and longer then to decide to post this negative review in conclusion. It’s the first time I have ever felt so compelled to do so. This is a reflection of the frustration I have encountered with this product.

1 Comment

  1. Trevor

    A bit confused. I am using PS Universal and have had issues, but they have been resolved quickly. I collect many details on thousands of servers/devices. The only things I can think of for your issues:
    1) A module you need may not be loaded in the PS Universal context, but it is loaded in your normal console window. Check for the module in PS Universal script and load it if necessary. You can also pre-load modules in PS Universal.

    2) Maybe your script is not using the credential you think its using. Verify. Would be better to use a specific credential anyway and not give your PS Service account those kind of privileges. Personally, I use a CyberArk vault.

    3) This line doesn’t seem to be using an actual variable and wouldn’t supply the actual FQDN so no hosts would be returned because its looking literally for the session broker named “Servername.FQDN”:
    $ServerList = Get-RDSessionHost -CollectionName mecheng -ConnectionBroker ((Servername.FQDN)).
    Think it should be $($ServerName.FQDN), but maybe you are intending to hide the server name from this post and the correct name is actually hard-coded in your actual script. If so, okay then.

    4) This is your real issue. You aren’t using error handling properly at all and you will see no errors, ever, the way that script is written. The previous line (point #3) has no Try/Catch block and would just ignore any errors. If any happened, the $serverLIst variable would be $null, so it would loop through nothing, show you nothing, and do nothing. Maybe your console window has a default of ErrorAction Stop but that is just bad practice. Specify what you want in the script.

    Where you did surround code in a try/catch block, you set the ErrorAction to Ignore, so it will never hit the catch block. It needs to be ErrorAction Stop or it will never go to the catch block. So, whatever error(s) are happening in your script, you will never see them. All errors in that code will be swallowed. That is not the fault of PS Universal. Its your code. Once you catch errors properly, maybe you can easily fix your problem. As written, it would show zero, nada, nothing.


Submit a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.