IT:AD:PowerShell:HowTo:Gotchas

Summary

No question about it – Powershell's idiosyncrasies are so infuriating that there are days that I want to take the creators of PowerShell out back and beat them to a pulp for the amount of time I've lost debugging.

Prefer void returns, unless the function's point is to return a variable.

Powershell is a pipe mechanism where any unused variable created in one module is put made available to the next Module. This can drive you nuts.

function Foo1(){
  return "Foo";
}
# Invoke it, and you get back "Foo", as one would expect from any language:
c:>Foo1
Foo

Let's chain two processors together, and try again:

function Bar2(){
  return "Bar";
}
function Foo2(){
  $x = Bar2;
  return "Foo";
}
# Invoke it, and you get back "Foo", as one would expect from any language:
c:>Foo2
Foo

This time, let's be totally flummoxed:
function Bar3(){
  return "Bar";
}
function Foo3(){
  Bar3;
  return "Foo";
}
# Invoke it, and you get back "Foo", as one would expect from any language:
c:>Foo3
Foo
Bar
# say what?!? Two outputs?!?!!

That combined with the second fact that if the return value of an invoked method only has one item (eg: as string) the return value will be a single value, but if it finds more than one, the string will be wrapped in an array…and you quickly go nuts:

Write-Host Foo2
Write-Host Foo3
#shit, that's not right...maybe it's the second item I want
Write-Host Foo3[1]
# but that stinks...and is going to sooner or later trip up.

The reason is that Powershell is trying to be helpful (like a kick in the head!) and is packing the output with everything that was created, that you may need, further down the pipeline.

I'm sure it could be very useful. Except I haven't found a use for it.

Instead, just ensure that if your function is either an Action or a Function, and vigorously don't return a value if it is not going to be used. In other words:

  void Ensure-Directory($path){
     ...check the directory...and make it if not...
     
     #Do NOT do this. 
     #a) the value is already known by the invoker
     #b) as invoker already has it, it's not guaranteed
     #   it will use it. And if the response is not used
     #   (ie, put into a variable) 
     #   it will pack the pipeline uneccessariy, and turn
     #   the response of the invoker into an array...
     #NO!!!! return $path
  }
  void Get-DirectoryPAth($args){
     $result = ....calc something the invoker doesn't know...
     
     # on the other hand this will always be used
     # so go right ahead
     return $result;
  }

  • /home/skysigal/public_html/data/pages/it/ad/powershell/howto/gotchas/home.txt
  • Last modified: 2023/11/04 02:26
  • by 127.0.0.1