Wednesday, April 8, 2015

PowerShell: Needs a Little Help from its Friends

Poor little PowerShell… It just doesn’t get any love.

It has been around for a decade now and I still find that it has not penetrated the consciousness of .NET developers. It’s sad. There’s this huge cohort of devs that don’t know anything outside of Windows and have this very powerful tool at their disposal, but tend to be oblivious to it.

There are a multitude of crazy one-offs that you can do to improve your efficiency on Windows. But the real Power comes from its two-way integration with .NET. By two-way, I mean that you can both load .NET objects in your scripts and write script components in .NET (binary cmdlets).

The real Power comes from its two-way integration with .NET.

I know some people are not terribly happy with the programming language, but I don’t have any problems with it. Yeah it isn’t the most beautiful, but after working with it for awhile, the syntax melts away and you won’t find it any better or worse than any other programming language. Well… expect Perl and Python. Nothing’s better than Python and nothing’s worse that Perl ;-)

On the other hand, the pipeline of objects vs. text is a crazy awesome advancement from the existing paradigm. The drawback is that it increases the learning curve. I know when I first started with PowerShell I found the objects frustrating when I just wanted text. It requires you to learn all these selectors and formatting tricks to get a display of what you’re looking for.

But, at the end of the day, any scripting language is only as good a the environment it lives in. At that, sadly, is where PowerShell falls down. In fact, it really does not have much to do with PowerShell. All scripting languages suffer on Windows. Be it Perl, Python or PowerShell, Windows just doesn’t have the tooling for these “glue languages” to glue together.

Be it Perl, Python or PowerShell, Windows just doesn’t have the tooling for these “glue languages” to glue together.

In fact, PowerShell does have the most, because it can leverage .NET, COM, WMI and all the other things Microsoft has thrown at its devs over the years. But it still lives in a land of GUIs, where everything is done with mouse clicks. Here are a few examples:

  1. Add the Log on as a service right to an account. Unix admins, read that and weep. It’s a fact! You can’t script what isn’t scriptable. If you search hard enough, you will find that, yeah, it can be done. But your eyes will have to bleed in the process.
  2. You can’t even work with NTFS permissions without installing a module. That’s right, simple basic sys admin stuff. Fundamental sysadmin stuff! Just changing the ACLs on Windows is not supported out-of-the-box. It is 2015 and Microsoft still struggles to match the basic functionality that Unix has had for 40 years (see chmod).

These examples reveal the truth from Microsoft. It’s not just the .NET devs in the wild that haven’t adopted PowerShell. Remarkably, not even the developers inside Microsoft have. As long as they are stuck in the 90s do-everything-by-the-gui mentality nothing will improve. PowerShell, as a whole, will stay inferior to much more modest shells like Bash.

Hammers never show their true value in the absense of nails.


  1. "... your eyes will have to bleed in the process." - good line. I enjoy reading your blog, keep on posting.

    I assume that using cacls.exe to change NTFS permissions from a script doesn't count, right?


    1. Francois, you raise a good point.

      I seem to imply that there is absolutely no way to control ACLs from PowerShell, but you are right, cacls.exe is available. Does it count? Sort of. I actually came across the module in the post when searching for an alternative to cacls.exe. Maybe I'm just too much of a purist, but I feel fundamental sys admin tasks should be available as native cmdlets. Honestly, I try to avoid WMI, .NET assemblies and EXEs where possible.

      In the specific case of cacls.exe, there are a few issues. First, the parameters are very un-powershell. Second, the output is text not objects. Lastly, errors are not PowerShell exceptions, so you have to jump through hoops collecting return codes and parsing stderr.

      All in all, this is sort of makes my point. If they're going to give us a nice new clean and powerful shell, they shouldn't make us deal with the old clunky one half the time. If it can be done more easily with Batch, why does PowerShell exist?