What I Hate About PowerShell

With all the love PowerShell is getting these days one might think that the golden age of (Windows) scripting has finally begun. Maybe it has. But one man’s nirvana can be another man’s hell.

My Background

I started with programming at the age of 14 by learning GFA Basic on the Atari ST. After devouring the Kernighan and Ritchie book I quickly switched to C and I must say that understanding pointers at an early age really helps in later life!

Go away or I will replace you with a very small script

After a 10 year hiatus I returned my attentions to the world of computing, learning (and loving!) Perl which I mainly used for systems management and migration tasks. I wrote tools like SetACL (in C++), dabbled in Visual Basic (at the time not based on .NET yet), dived into the arcane syntax of Windows batch files and picked up regular expressions along the way. Later I wrote a couple of tools in C# and VB.NET (based on the .NET framwork), e.g. SetACL Studio. For my latest product, uberAgent, I went back to C++.

I am mentioning all of this so that when you decide that I am an idiot after reading this article you at least give me credit for being an idiot who has seen a bit of the programming world.

From Monad to PowerShell

I heard about PowerShell first when it was still called Monad. At the time I was thrilled by the prospect of having a powerful scripting language for Windows. I was hoping for something like VBScript turned good or Perl being included in the default install of Windows. My enthusiasm was such that I wrote a paper explaining PowerShell and presented to colleagues and customers.

However, over time my enthusiasm waned. I found more and more quirks in the language that made life unnecessarily difficult. Certain things that should be simple and intuitive are not. Perl’s slogan Easy things should be easy and hard things should be possible does not apply to PowerShell.

The remainder of this post is a list of things that, in my humble opinion, are wrong with PowerShell. Some of the points may be subjective. I might be wrong about a thing or two (in which case please correct me by commenting and I will fix the error). You have been warned.

Syntax

Operators

PowerShell’s operators are horrible. E.g. testing strings for equality:

"abc" -eq "abc"

Instead that should be something like:

"abc" == "abc"

The same applies to most other operators. E.g. comparing two numbers:

8 -gt 6

Instead of:

8 > 6

Escape Character

Having the backtick as escape character is just plain weird. Chances are if you have used other programming languages the backslash feels much more natural.

"Let's print line one`nand line two`n and a quote `""

Instead of:

"Let's print line one\nand line two\n and a quote \""

If Requires Curly Brackets

Many languages let you do away with the curly brackets if you have only a single statement in an if. Not so PowerShell. Instead of this:

if (5 -gt 3)
   "hello"

You need to write this:

if (5 -gt 3)
{
   "hello"
}

Function Definitions

Functions can only be used after they have been defined. This leads to constructions like this one where the script effectively starts at the end:

function main
{
   # do stuff
}
 
# Call main
main

Function Calls

PowerShell functions are called without parentheses, but .NET functions are called with parentheses.

E.g. calling a self-defined PowerShell function LogMessage:

LogMessage "Here's a message"

Versus calling a .NET function

[string]::IsNullOrEmpty($configFile)

Script Syntax Check

Scripts cannot be syntax-checked before they are run. If you have a syntax error in a code branch that is not executed during testing you might only find out about it after the script has been deployed to production machines.

E.g. PowerShell happily executes the following code without the slightest warning:

Set-StrictMode -Version 2
 
$variable = 10
 
if ($variable -eq 30)
{
   aslkfjlsjdf     # It probably should complain about this
}

Lack of Mandatory Variable Declarations

This (along with the next point) is by far the worst I have found while working with PowerShell.

If you want to write production-quality code you need a way to force the language to force you to declare variables before they are used. Perl has its use strict, heck, even VBScript has option explicit. Only PowerShell has nothing.

Take a look at the following code. You expect it to print “20”, but because of a stupid typo it prints “10”:

Set-StrictMode -Version 2
 
$variable = 10
 
# other code
 
$varable = 20   # Notice the typo
 
# print value
$variable

There is a Connect item on this.

Scope of Variables

This is where it gets really funky.

PowerShell uses dynamic scoping with copy on write (versus lexical scoping, which is what everybody else uses). If you have used other languages before this is totally confusing. Even if you have not this easily leads to errors that are really hard to find.

So what is this about? When a new scope is created (basically whenever you declare a function), all variables from the parent scope are copied into the new child scope. Notice the word copied. That means you now have two variables of the same name. When using the variable name in the child scope the child scope’s copy of the variable is changed. Once you leave that scope the change is gone – the parent scope’s copy of the variable remains unchanged.

Take a look at this script:

Set-StrictMode -Version 2
 
function ChangeVariable()
{
   $variable = 20
 
   # Print the value from inside the function
   "Value from INSIDE the function: " + $variable
}
 
# Set initial value
$variable = 10
 
# Print the value
"Value from OUTSIDE the function: " + $variable
 
# Call the function that supposedly changes the variable's value
ChangeVariable
 
# Print the value again
"Value from OUTSIDE the function: " + $variable

The value of $variable is printed three times. You might naively assume that the output is “10” followed by “20” and another “20”. Not quite:

Value from OUTSIDE the function: 10
Value from INSIDE the function: 20
Value from OUTSIDE the function: 10

Here is a nice blog post explaining this in more detail.

, ,

38 Responses to What I Hate About PowerShell

  1. Narkor November 5, 2014 at 18:35 #

    So a language designed to get admins scripting makes someone from a dev background pissy because it doesn’t conform to a bunch of developer expectations? Did you ever consider the reason that admins avoided scripting was because of all the Dev bullshit that went into it?

    • Samuel Legrand November 6, 2014 at 00:52 #

      Not agree with you Narkor. PowerShell isn’t easier than any other scripting language.

      Dev bullshit as you named it, could prevent from typos for example. The way the syntax is controlled is just inefficient…

      Some customers want to use PS script as logon script and ask why logon times increase…

      Vbscript still has some bright years ahead of it ;)

      • Derek Melber November 7, 2014 at 15:17 #

        I agree and disagree with each of you on this. First, Powershell is not used by many admins at this time. I find that approximately 10% use it a lot, 50% have used it for one or two specific tasks, and 40% have not used it at all. Powershell is NOT easy and really does take a developer background to understand and use. Powershell is not efficient, takes many iterations to test and perfect, and provides little to no feedback as to what is being changed or the final outcome of the command/cmdlet. I find that many want to use Powershell for tasks that are already being accomplished by other features/products (Legrand example with Vbscript in login script), which is often a mistake. Powershell is powerful and awesome, but must be understood better, marketed better by Microsoft, and more use cases created so that it is easier to “consume” by the average administrator.

      • bill August 18, 2015 at 21:06 #

        Agreed. I have programmed in 100’s of procedural/scripting and oo languages in the last 35 years and Powershell was not well thought out in regards to scope. The fact that functions() have not concept of local scope blows me away. Seems like the designers hoped that all logic would be isolated into separate ps1 files and command-lets. Have a funny feeling that this product was conceived of by either a newbie programmer at MS or by a “over seas” affiliate. Anyway, MS Powershell is just one more reason why MS can’t survive the long haul.

        • userone February 22, 2017 at 10:54 #

          Time will show, who survives :-)

      • Keith H April 8, 2017 at 09:52 #

        Also don’t agree. I develop in four different languages not including Transact-SQL which of course isn’t a “programming language” per se but still must be learned, and I also am a sysadmin and DevOps guy. I can’t stand PowerShell. It doesn’t make any sense, is far too wordy and full of arcane looking syntax, blows it completely on many MANY AWS aimed scripts, and has far too many hard to find modules and cmdlets to figure out where things are. That last part is due entirely to the leviathan that is Windows base code. But either way, I am seriously trying to find a way to feel completely confident writing in IronPython to do what I am evidently forced to to in PowerShell. Because I don’t get how to retain it and I don’t really want to try.

  2. rich siegel November 6, 2014 at 03:56 #

    My biggest problem with powershell and windows is that it is up to each application creator to provide powershell snapins modules or other functions.

    I always hear Jeffrey Snover talk about Linux having config files being a much easier solution than dealing with an api for everything. While the api approach seems nice, versus grep, awk sed and others it just falls down at every edge case. Why cant dns servers just be in resolve.conf? DSC aims to wrap a lot of this but it is just cake icing with the same underlying powershell limitations.

    It is just crazy how to config every thing on windows require a different cmdlet. Then if you want to do sonething that doesnt have a cmdlet like changing the binding order of adapters it is a massive bunkerbuster. Then think about all the apps that have nothing. Its a random registry hunting expedition. Try changing a Hkey user for everyone? Loading ntuser.dat… ugh

    As for your complaints above…eh. annoyances and gripes… What I have found assisting and maintaining the chocolatey project is that the language falls down on large code bases. You end up with so much nuance and code jerking around that just is managed nicely with modules classes and methods or gems in other languages like ruby.

    Dont even get me started on parameter and switch handling if you want complex options. Its obtuse and constraining. Environment variables and refreshing them? Its so busted.

    Lastly, cmd.exe is the worst thing about powershell. The borked intertwining of behaviors can make anyone go batty ;)

    • userone February 22, 2017 at 10:58 #

      Yes, configs are great, I admit. But scriptable configuration objects are cooler and more modern. Come out of C and Unix time finally and Think OO!

  3. Hendrik November 6, 2014 at 10:35 #

    @Helge: Nice post.

  4. Sven November 6, 2014 at 13:24 #

    Hi, nice article. As I started with PowerShell, I need to say that I really hated it and didn’t know what is so good at it. After a while, now I really spend up to 50% with PowherShell and think it is a great stuff.

    I need to say, I’m not a programmer and never was and never want be. No defense. I’m speaking from the Admin site, mostly System Center.

    Why I’m hated it is easy, PowerShell felt for me in the first look like a new program language, with so many stupid thinks like described in the article here. It also really confused me that you had to write first the function before you can call it (what obviously make sense). But anyway.

    What has changed and why I spend so many time with Powershell now? Easy as well. I see PowerShell not as a programming language and it isn’t really one. PowerShell is the next generation of Command line. And in this case it is a great next version of it. For me as an administrator it is a great tool to quick script something. Of course not multiple pages of code, but you haven’t done this with command line either, right? It is to script quick automatism and not to write new programs. To make daily task more easier.

    So for me is PowerShell a good thing, even with the small issues mentioned above. It is for daily quick requests and tasks and to script short automatism. If I would need to write a more complex program I would go with C# maybe, but not with PowerShell.

  5. Jonas November 6, 2014 at 14:26 #

    Have done quite some development in assembler, C, C++, Delphi etc. in my days and I can understand your gripes with Powershell as a programming language. But since I now days mainly do windows infrastructure management I think you’ll have to view Powershell in a different light. It is more of a windows version of bash than an alternative programing language. You can do stuff with Powershell that I wouldn’t dare to imagine the loops you had to jump thru to get bash doing the same thing.

    @ rich siegel. If you end up supporting massive amounts of code I Powershell I think your design is fundamentally flawed. Powershell is glue. Not bulk code. That should be commandlets implemented in c# or whatever. :-)

  6. Tim Dunn November 6, 2014 at 16:49 #

    Excellent article. PSH V4 Set-StrictMode -Version Latest will catch undefined variables, as well as undefined properties. I want the former, but cannot suppress the latter.

    The metacharacter escaping issue is even more complicated. With -split, -match and -replace, it uses backwhack metacharacters. With $string.Split() it uses backtick metacharacters.

    My two biggest issues are:

    – Performance can use work. It is very resource intensive compared to Perl on a *nix platform.

    – Lack of support in VisualStudio. PowerShell_ise.exe is nice, but not powerful enough. VS has hooks to *use PSH* for build automation, but no IDE support.

  7. LucD November 6, 2014 at 18:56 #

    Hi Helge,
    Let’s start by stating that I’m obviously biased on the subject ;-)
    You make some valid points, but some enter the nitpicking area IMHO. No language is perfect (as no OS is perfect), but in this case I think the most important criterium is what admins in the Windows world can do better, faster and easier thanks to PS.
    If you look at the Monad paper, where it all started, I admire how the PowerShell team was able to implement their vision in a corporate giant like Microsoft.
    Like I said earlier, nothing is perfect, but let’s not throw away the baby with the water.
    And I’m pretty sure some of your valid comments will make it to the PS team.

  8. Cookie Monster November 7, 2014 at 14:06 #

    Hi Helge!

    Good stuff. I’m assuming you know most of these, but a few thoughts:

    Operators – It sounds like this was a tough decision for the PS team. How do you merge features from shell and scripting languages without conflicts? If they went with > as an example, you would have similar complaints on the shell side for the lack of consistency with standard redirection operators.

    Escape character – Agree to an extent. That being said, we’re talking a Windows environment. From convenience perspective alone, \ would likely turn off the vast majority of admins. Can you imagine if every single path had to use C:\\Better\\Not\\Miss\\An\Escape\\Character syntax? Ouch!

    Curly brackets – yeah, that functionality would be handy.

    Function definitions, Script Syntax Check – If you don’t want a quirky language that behaves one way when at the shell, another way when scripting (even if the quirks are ever so slight), this seems like the best approach. That being said, I’m not a developer and this is over my head : )

    Function calls – This seems aimed at making PowerShell appear more like a scripting language than a low level language. I don’t mind the more formal syntax, but many, many administrators out there would struggle and potentially give up the language if it forced that syntax.

    Lack of Mandatory Variable Declarations – Agreed.

    Scope of variables – Agreed to a certain extent. I’m assuming this decision was to make the lives of admins easier, who may be less familiar with scope (who would still likely be confused by dynamic scoping…)

    Ultimately, I think the first paragraph of Microsoft’s TechNet article on PowerShell explains this… Windows PowerShell® is a task-based command-line shell and scripting language designed especially for system administration. Built on the .NET Framework, Windows PowerShell helps IT professionals and power users control and automate the administration of the Windows operating system and applications that run on Windows.

    Cheers!

  9. Jeffrey Snover[MSFT] November 7, 2014 at 14:28 #

    Helge

    Thank you so much for taking the time to write up the things you don’t like about PowerShell in such a clear and coherent way. The PowerShell team considers information like this pure gold.

    > I am mentioning all of this so that when you decide that I am an idiot after reading this article you at least give me credit for being an idiot who has seen a bit of the programming world.

    Absolutely not! Many of the things you articulate here are things we struggled with/are struggling with. For instance, the biggest on this list is the operators. You won’t find anyone on the PS team that disagrees with you here. This is an area that goes against my explicit goal to be as closely aligned with C# as possible. The issue is that our highest priority was to be a tool for admins and to support the admin development model – interactive shell -> simple scripting -> production scripting -> systems programming. The need to be both interactive and programmatic lead to the decision on operators. I can’t tell you how many times and how many hours we spendt trying to find a way around this. Bruce Payette’s book PowerShell In Action goes into all the details. Anyway – the point is you are on solid ground here. That said, as much as I disllike those operators, I am actually extremely happy about how we balanced an interactive vs a programmatic shell. Of course if that is not the development model you use, then this brings you no benefit.

    Many of the other things in this article I would put into the bucket of needing to better support a developer mindset (except for the required {}s for if statements which falls into the category of – we are just going to be buttheads on this because it is a bug farm and responsible for so many wasted man-centuries of grief). From the very beginning of PowerShell I was clear that we wanted a single tool to span the needs of both developers and operators (we were devops before devops was cool :-)). The reality is that we started out heavily skewed towards operators (e.g. the importance of the admind development model) and then release after release, we are expanding to better address developer sensibilities. This is one of the primary focuses of PowerShell V5 which is in preview and provides support for classes and a new developer-oriented language mode (must declare outputs, returns are the only way to emit objects, no dynamic scoping, etc. etc). I talked about the shift to focus on developers and devops scenarios at my recent talk at the PowerShell Summit in Amsterdam. Check out https://www.youtube.com/watch?v=j0EX5R2nnRI&index=1&list=PLfeA8kIs7Coehjg9cB6foPjBojLHYQGb_ around the 1:07 mark.

    Many of those changes came because of other people that where kind enough to be honest and clear about what they hated about PowerShell so again – thank you for the gift on honesty and clarity. I really appreciate it and we do really take these messages to heart. It would be great if you could check out the new language mode in PS V5 preview (used when you code classes) and let us know what you think about it. I would hold off a couple of weeks and use the PS V5 Nov preview as the Sept preview classes had a number of issues.

    Cheers!
    Jeffrey Snover[MSFT]
    Distinguished Engineer and Lead Architect for Windows Server and System Center.

    • Kevin December 30, 2016 at 21:27 #

      So this thread essentially breaks down to:

      Powershell uses poor design because it needs to support the poor design of it’s predecessors….

      Seriously, it’s this mentality that makes me hate nearly all things MS….

      • God January 12, 2017 at 16:54 #

        Kevin, when you mentioned poor design… to which language do you compare it with?

        honestly, powershell is by far the best language designed for its purpose…

  10. Jeffrey Snover[MSFT] November 7, 2014 at 14:38 #

    @cookieMonster – it looks like you must have read Bruce Payette’s PowerShell in Action because your analysis is spot-on!

    I was particularly impressed by your insight into why functions have to be declared before they can be used – that is exactly correct – we wanted to ensure that you could take any script and paste it into the interactive shell and have it work.

    Cheers!
    Jeffrey Snover[MSFT]
    Distinguished Engineer and Lead Architect for Windows Server and System Center.

  11. Stephen Owen November 7, 2014 at 16:29 #

    Hi,

    About the comparison operators. According to Bruce Payette– head developer of PowerShell– in his book PowerShell in Action, the reason they choose not to use equal-symbol symbols is that PowerShell is a shell. Pretty much every MS shell for 20 years used the symbols for output redirection, and there are all sorts of usages through cmd.exe and elsewhere that depend on redirecting output like this.

    For instance, you currently redirect error level output using the following: Get-Process none, Powershell 2>&1

    Anyway, I believe the logic was to base the decisions for PowerShell off of a similar Unix command, rather than contemporary scripting languages like Perl or Ruby.

    • Thomas Lee November 10, 2014 at 15:57 #

      Another reason that comparison operators are like they are is consistency. Even if msft had used >, < etc in the set of valid operators, there would always be operators that are not easily noted using simple keyboard symbols (without the hon-transparent approach used by APL, an earlier progamming language). The way that was adopted means ALL operators begin with a '-'; a bit of consistency that some find useful. It certainly aids discovery, IMHO.

  12. Martin Pětvalský November 8, 2014 at 18:04 #

    Besides lacking the already mentioned one line IFs “if (condition) action” I would also love to have ternary operators support, it would really simplify and shorten the condition notation.

    And here is the thing I hate most and can’t understand what was the reason for this:

    “In Windows PowerShell, the results of each statement are returned as output, even without a statement that contains the Return keyword. Languages like C or C# return only the value or values that are specified by the Return keyword.”
    ^ from http://technet.microsoft.com/en-us/library/hh847760.aspx

    To give you an example:

    function test($a)
    {
    write “Text in function”
    return ($a * 2)
    }

    $result = test 5
    write (“Result in main: ” + $result)

    OUTPUT:
    Result in main: Text in function 10

    but reasonable output for developers would be this:
    Result in main: Text 10

    I can’t understand the logic behind this. We must design functions in our scripts to be very quiet or use other channels like verbose or debug. Hopefully Jeffrey Snover can explain the reason why this decision was taken :)

  13. Jeffrey Snover[MSFT] November 10, 2014 at 14:33 #

    @Martin

    That is one of the things we address with the new language mode found in classes. There you have to declare your return type, use a return statement and write-output goes nowhere.

    The historical reason for this is PowerShell’s footing as an interactive shell. Ignore the “return” statement and that is exactly the semantics of interactive shells. We added the return statement to make it more friendly to developers but this one of those situations where when you add something, you make it dramatically weaker. Like:

    I’m loyal to my spouse.
    is made weaker when you add:
    …on Tuesdays.

    Having made the mistake of adding it, removing it (or ignoring any write-output if a return statement is used) would be a breaking change. That is why we waited until we had a new language mode to address it.

    Jeffrey Snover[MSFT]
    Distinguished Engineer and Lead Architect for Windows Server and System Center.

  14. James O'Neill November 10, 2014 at 22:47 #

    It does amaze me how developers expect things to be like they are in a compiled programming language

    PowerShell functions are just a kind of command like ping. ping() makes no sense. But when you have a Method of an object it’s arguments are bracketed…

    Operators: yes of course it should be ping > file.txt and it and get-date > $mybirthday good luck sorting those out.

    {} round script blocks, seriously ? Yes C style lets you out of including them sometimes, although it can create so brilliant bugs …
    But PS gives you the same syntax for
    begin, process & end block in loops, where conditions [if script block returns true, pass object along the pipe line], do/while bodies, function bodies, even in parameters consider this:
    dir | ren -newname {$_.name -replace “foo”,”bar”}
    So the syntax of if () round the expression to be evaluated {} round the code to run isn’t that hard. And how can someone complain that variables don’t have to be declared but the ends of an IF block don’t have to be ?

    Not using \ for the escape character … so you have a path in a string, and you’re on windows “C:\really\simple\problem” if you have \ as the escape character : whatever you use instead is going to feel wrong.

    Mandatory variables declarations make ZERO sense in a typeless language
    If I have to declare VAR: $foo
    but I can the write $foo = ping (foo holds an array of strings) or $foo = get-date (foo holds a dateTime object) declaring the variable didn’t enforce anything except extra work

    Naming variables before you use them isn’t declaring : declaring is saying I have a variable of this type and it has this name.

    So when I was working on exchange earlier today and I did $u = get-umserver , you have me devote time to finding out what type of object get-umserver returns and then declare U as that type first ?

    You want to declare variables before you use them, but not functions ? Why ? It’s a scripting language it’s interpreted . if it were compiled it might make sense to parse the whole thing to find named script blocks (functions) and save them but it’s not. Yes I grind my teeth when I alter a bit of code and introduce a syntax error which only comes to light when a lot of script has run. But that’s what the ISE is for.

    • Dmitri R June 3, 2016 at 15:13 #

      I disagree that PS should be treated only as a glue. It is certainly more than that and is more than a scripting gateway to .NET. Why would PS need modules, invocations, functions, objects etc if it were only a glue? Command prompt did not need them. Even bash leaves most of this to be implemented elsewhere. PS has definitely aimed at the big league. Not quite there yet, is it?

      @James,

      Variable declaration is a welcome feature. No need to specify type. Take javascript as an example.
      For PS it is double important because of dynamic scoping. Frankly, I am struggling to understand why they introduced that thing. To save on look-ups?
      Anyway, dynamic scoping is quite a bug breeder. At present, the only safe practice is to explicitly initialize all local variables before any use. You’d say, this is a good practice anyway. Well, the thing is, in some situations it comes at the cost of code clarity (e.g. recursion). For some reason they introduced default values in PS… Alternatively you may use explicit scope prefix for every instance of the local variable. That would be a little bit more expensive than just initialization :)

      Whether to put function definitions on top or not, it is a preference. The problem is PS is throwing a run time error when the function is not defined; the error can be silenced. So if code calls ahead and fails first time, the missing function maybe added after recovery from the rte. I guess on next run the behavior might be a bit different. Good luck catching this!

  15. Eric January 13, 2015 at 09:01 #

    I pretty much have a similar background, and the article is spot-on!

    There are a lot more annoyances, mostly minor ones. But you forgot one important one (at least for me ;-) ). Inconsistency, this one really bugs me. Let me give an example:

    why does the given example:

    dir | ren -newname {$_.name -replace “foo”,”bar”}

    work, but:

    dir | echo $_.name

    doesn’t work, it’s an issue I see a lot and when using the the pipe. I know that the second command needs a foreach to work: dir | % { echo $_.name} does work. And I get why, but I have a programming background, but for people with no programming knowledge, it’s a deal breaker.
    The second inconsistency example is in variables, the idea was that powershell could decide what kind of variable/object type a variable should be, this is good for admins who try scripting. I’ve encountered several cases in which regular cmdlets sometimes pass the object as an array when actually, it’s only a single object. This obviously results in an error when trying to use the result in another function. The annoying part, it doesn’t do it every time. And when it happens, it’s really time consuming. Defining [string]$variable helps in this case.

    I think it would have been better for powershell to be good at 1 thing, instead trying to be good at scripting and trying to be shell-like. In the current form, it doesn’t really excel in either.

    • Dave Wyatt July 17, 2015 at 13:49 #

      Eric,

      dir | ren -newname {$_.name -replace “foo”,”bar”}

      This is an example of what’s generally referred to as a “ScriptBlock Parameter”. The reason it doesn’t work with Write-Output (or echo, which is an alias), is that Write-Output’s parameters don’t accept pipeline input.

      When a parameter does accept pipeline input, you can assign a ScriptBlock to that parameter instead, and PowerShell will evaluate the script block for each input object in the pipeline (setting the $_ variable to that input object). You can see this in action with Trace-Command:

      trace-command -Expression { dir | ren -newname {$_.name -replace ?foo?,?bar?} -WhatIf } -PSHost -Name ParameterBinding

      … snip

      DEBUG: ParameterBinding Information: 0 : BIND PIPELINE object to parameters: [Rename-Item]
      DEBUG: ParameterBinding Information: 0 : Invoking delay-bind ScriptBlock

  16. Keith Hill July 17, 2015 at 16:40 #

    dir | ren -newname {$_.name -replace “foo”,”bar”}

    Works because the FileInfo or DirectoryInfo objects passed into Rename-Item (aliased to ren) get bound to the LiteralPath parameter and you are specifying $_.Name for the -NewName parameter.

    dir | echo $_.name

    Those same objects, when piped to Write-Object (aliased to echo), are bound to the InputObject parameter. No other parameters on Write-Object are “positional” i.e. you have to specify the parameter name. But given your example it is clear that you wanted $_.Name as the argument to the -InputObject parameter. In this case, what you want to use the Foreach-Object command (aliased to foreach) which allows you to execute arbitrary script on any object passed to it e.g.

    dir | foreach {$_.Name}

    In PowerShell v3 this has been further simplified for scenarios when you just want to access a property to:

    dir | Foreach Name

    And if you really want to keep the typing short (only recommended for interactive/command line usage due to readability) you can use another Foreach alias – %:

    dir | % Name

    >> I think it would have been better for powershell to be good at 1 thing, instead trying to be good at
    >> scripting and trying to be shell-like. In the current form, it doesn’t really excel in either.

    Hmm, never used Korn shell or Bash eh? :-) Unfortunately this is a problem of Microsoft’s own making by waiting so late to provide a decent shell on Windows. Windows users just aren’t used to what a powerful shell can do in conjunction with a powerful scripting language. That said, Windows has the batch language but not many folks use it. If you think PowerShell syntax is funky, trying iterating through files in a for loop in a .BAT file.

    I think folks need to be a bit careful comparing PowerShell to scripting languages like Python and Ruby. PowerShell is a “shell” scripting languages and that has specific semantics like not having to quote every argument and being able to execute exes directly. For example typing:

    import os
    dirlist = os.listdir(“c:\\temp\\foo”)

    from pprint import pprint
    pprint(dirlist)

    at the prompt would kind of suck compared to:

    dir c:\temp\foo

  17. Commenter July 17, 2015 at 23:02 #

    >Script syntax check

    Your example script is valid syntax; “aslkfjlsjdf” might be you running “c:\windows\system32\aslkfjlsjdf.exe”, or it might be a CommandLet alias defined by something else.

  18. Vince Yuma July 28, 2015 at 08:25 #

    My background is FORTH and LISP. When the “C’s” became the standard I hated the ‘black-box’ compiling and especially the strict type casting.

    The language I learned first was FORTH and FORTH’s best features were:

    — it became the operating system
    — it could be compiled
    — it could be interpreted
    — it could interpret while compiling
    — parentheses ARE the comment character (just as regular English)

    Windows PowerShell is a scripting language and as such is, of course only interpreted. While it is not the operating system, it is a shell and command language, like BASH and others. Windows PowerShell, however, returns everything in object form automatically — putting it head and shoulders above the others.

    Windows PowerShell is verbose, verbose, and sometimes is strange when trying to mesh with ‘pure’ .NET operations; but overall, PowerShell rocks.

  19. bb May 14, 2016 at 13:07 #

    PowerShell is just beautiful! It`s not a programming language it`s a task automation and configuration management framework built on top of .NET. It contains a scripting language and interactive shell. If you want to build applications and services use C#, if you want to automate your infrastructure, OS and applications use PowerShell, why compare powershell to compiled programming languages?

  20. Kamarey November 10, 2016 at 08:57 #

    You just read my mind!
    It’s very ugly and hard to understand/troubleshoot language (I have ~20 years of developer experience, so I can compare things). Microsoft, as always, tried to re-invent a wheel. Why not make something similar to C# or javascript? Especially if Powershell use .NET. Or at least no need for these ‘very special syntax’ described in you post.Suspect it will be replaced in very near future by more friendly scripting language (even by Node.js, why not?)

  21. Johnathan H. March 24, 2017 at 17:52 #

    Interesting read. I do share some of these sentiments, however, I still no less think that PS is by in large a huge leap forward for DevOps, Devs, SysAdmins that used to rely on the kluge of VBScripts, BAT files, and god help you a set of JScripts. From the time you wrote this, I wonder now if you still share the same notion especially since you now have Bash on Windows and PowerShell on Linux. Bash also would seem to follow several of these complaints as well as Python. This begs the question: What do you feel would be a more authoritative scripting language?

  22. [OvO]wl August 1, 2017 at 11:29 #

    Here’s some REAL reasons why powershell is crap:

    1) Powershell-ISE, the intellisense doesn’t work inside functions, only when you are running things from global scopes. If that’s not broken enough, you need to run things first in order to “see” variables in com objects. Unfortunately with Com you need intellisense.

    2) DLL contents appear and disappear randomly. Yes that’s right sometimes a script works sometimes it does not, depends on whether powershell can see the things you need inside the DLLs. if you can’t then you’re screwed.

    3) Autoloading of modules. Autoloading of anything whatsoever in any language is a terrible idea, but dozens of people have complained about powershell sometimes loading modules and sometimes not.

  23. Matt Irwin August 17, 2017 at 16:55 #

    I find that the module and manifest creation can be quite powerful and easy to produce once you learn to use it. (Granted this learning curve took awhile to overcome) However, I now find it quite easy to create large robust structured modules that I can import to my various programs. For instance I have made several powershell wrappers around various API from all over the place and I can now create insane GUI based applications just by importing the right set of modules. This makes powershell 100% worth it.

    Pretty much everything in powershell follows this pattern: Supper clunky and hard to use – 2 months of struggling – how did I live without this?

  24. Richard Givis October 10, 2017 at 20:31 #

    Brilliant blog – with a vibrant and impressive collection of feedback comments! I am a developer, and I too feel your pain. I would have to agree with most of your PowerShell complaints. I was highly entertained by the Microsoft MVPs that hopped on-board to defend their product. I would just like to log my opinion. Being a C++, C#, Ada software developer, we often need to do administrative things. For example, with chocolatey there is often a need to write installation/uninstall scripts. So we are forced to follow the industry standard, which clearly seems to be leaning towards PowerShell. It IS a powerful, elegant, and cleverly designed scripting language. But it does indeed have its shortcomings, most of which you have already mentioned. It is just unfortunate that Microsoft failed to adopt many of the things that Perl got right. Like logical operators, pattern-matching, and function calls. For my scripting needs, I have been a fan of Perl for many years. It even had CPAN modules, which tried to accomplish what the new Cmdlets do. But Perl was difficult to tame. Scripts could easily get massively complicated and difficult to maintain, almost to the point of becoming cryptic.

    PowerShell has the programmability of a developer’s language, but the feel of an admin’s scripting tool. The Object-oriented nature of its functions and Cmdlets greatly contributes to its upward scalability. Now that the wheel has been re-invented, and it is now backed by the awesome power of .NET, let’s just keep moving forward. I will swallow the PowerShell pill, but not without a pinch of salt.

  25. tmunro55 November 9, 2017 at 04:36 #

    A lot of good discussion here, and a lot of points of view. So, I’ll add my own. Over the years I’ve programmed in many languages on Mainframes, Minis and PCs. High level and machine code and everything in between. It’s just syntax/grammar. Just like spoken languages, just syntax and grammar. You get get to know it as you use it. Some are similar, some are wildly different. Java, Pascal, C, Python, Basic, Forth, APL, Lisp… you get the idea. PowerShell is VERY powerful. It took me three separate attempts before I felt comfortable enough to forge ahead. I now quite happily use it daily.

    My only real complaint with PowerShell is that it’s slow. If speed is not an issue for the completion of a task PowerShell is my friend. If speed IS an issue and I don’t “need” PowerShell, I use VBScript. Lightning fast but more verbose to write.

    Please Microsoft, speed up PowerShell. It’s a slug. A very strong, versatile, slick slug, but a slug none the less.

Leave a Reply