Giving up. I really wanted this to work

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</CODE>

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.

Sorry it didn’t work for you. In this case, immediately an obvious thing is that you are using PSRemoting, so is your Powershell Universal running as Local System service? If so then it’s different privs and obviously it will fail, and you may have second hop issues as well. Maybe establishing a pssession with explicit credentials saved as a secret might make it a bit easier. Maybe try get-ciminstance to grab a simple WMI result to make sure the remoting part is working as expected. You can also change the Powershell Universal service to run as your account or as a service account to help avoid this kind of thing.

I did some remoting stuff on mine and it worked just fine, but in this case my Powershell universal runs as a domain service account and not LOCAL SYSTEM.

Leveraging the VSCode debugging can go a long measure to helping sort out why things are different. This same frustration isn’t unique to Powershell Universal, you see it in Azure Automation, Azure Functions, AWS Lambda, containers, anywhere that your dev environment and your run environment arent 1:1.

-Justin, a happy PSUniversal user, not an employee of Ironman Software.

Thanks for getting back to me Justin,

I’m running Universal as a domain service account as well. I can even launch PowerShell as that user and run these scripts so I know there’s no issue with permissions.

I’m interested in your idea of debugging the script in VSCode. I’m not sure if I know how that’s done when the script is running remotely under the context of a service account when using VSCode. I’ve attached to processes before in Visual studio. But I don’t think the same approach applies here. I’m interested though.

If you go back to my point that I found that for some scripts, I found that changing the environment between default, PS5 and PS7 resulted in different outcomes. So it’s very unlikely a result of the permissions and more likely something in the way that Universal is processing these scripts in it’s custom environment.