Saturday, August 2, 2008

Returning values from Fuctions in PowerShell... Tricky :(

First let me explain something: I LOVE POWERSHELL...

No, I really do. After 3 years working every day with batches, vbscript & .NET I can see huge huge potential in PowerShell and more and more I use it I think it is genius shell.

However I am always trying to be skeptical about everything I do - and about every product I love.

I don't want to end up like some people that think their favorite product is PERFECT - and when there is new version, they suddenly realized that something that was PERFECT is more PERFECT ;)

 

I worked with Monad\PowerShell a lot 3 years ago, then I stopped and returned to batches (because of my work). It was quite fun and it turned out that with good imagination you can still achieve a lot with batches (script blocks, complex scopes, private variables, subroutines, functions etc ;)), however it was always just about building some workarounds. 1 month ago I returned to PowerShell and now I am working with it on daily basis - and of course I already encountered some things I don't really like. 

Working with function output

If you are familiar with programming, following code should be easy to understand for you:

Function bar {
$MyVariable = "Foo"
Return $MyVariable
}



Function bar returns MyVariable. So using $X = bar should be equivalent to $X = $MyVariable in fact.



Not in PowerShell. $X will get output from WHOLE function. That means that following function is equivalent to one above:



Function bar {
$MyVariable = "Foo"
$MyVariable
Return
}



I really, really don't like this behavior. Creating complex scripts is getting much more complicated. Consider example where you run into some problems in bar function. Most primitive debugging is always to use Echo (Write-Host) and just see value itself.



If I would have enough time, I would change it as follows:



Function bar {
$MyVariable = "Foo"
Write-Host "DEBUG: $MyVariable"
Return $MyVariable
}



Result would be as expected - if I will use $X = bar, $X will be Foo. However what if I try following:



Function bar {
$MyVariable = "Foo"
"DEBUG: $MyVariable"
Return $MyVariable
}


Looks fine? But doesn't work - $X in this case is Foo Foo and you will never see "DEBUG: Foo" output in console. I really think this is against object-oriented principle of PowerShell and it reminds me of 'For /f' behavior in batches.



You probably won't run into this problem - however you will run into it if you will start creating really complex scripts with XML handling, adding new elements etc. Usually (in .NET), if you for example add something to array, index is returned.



Look at following function. Variable $MyVariable is created, two numbers are added (1 and 2) and then it is returned:



Function bar {
[System.Collections.ArrayList]$MyVariable = @()
$MyVariable.Add("a")
$MyVariable.Add("b")
Return $MyVariable
}



Normally you would expect to get array that contains 'a' and 'b'. But because of PowerShell way of returning object, instead you will get array with 4 (!) entries: 0 1 a b.



0 and 1 in this case is index of added array elements. 



To make this function work as expected, you will need to redirect output to null:



Function bar {
[System.Collections.ArrayList]$MyVariable = @()
$MyVariable.Add("a") | Out-Null
$MyVariable.Add("b") | Out-Null
Return $MyVariable
}



Usually I try to write all my functions in following format:



Function <Name> {
<initial checks>
...
<final checks before return>
Return
}



With PowerShell this is usually not possible, because even if you check if $MyVariable is correct type with correct values etc, it is quite hard to know if something "leaked" before. 



For me ideal solution would be that PowerShell would support BOTH methods for returning:



Function bar {
$MyVariable = "Foo"
Return $MyVariable
}



Would return object $MyVariable



Function bar {
$MyVariable = "Foo"
$MyVariable
Return
}


Would return whole output from function



Friday, August 1, 2008

How to manage your small development projects??

Some of you are maybe hobby developers as I am... I am partially developing for my company and also I have few free public projects like Elevator.

There are 3 tools that I always must have when I work with my projects:

  • Subversion - used for versioning, very easy to setup and use, available for free, no need for database, integrated to shell.
  • Visual Studio - well, of course :)
  • PowerGUI - it contains very nice PowerShell script editor

If you have however some professional projects (that means projects with fixed deadline for me ;)) and you are not working for professional developer company, it can be pretty tough to keep project on track and not spend days implementing small features and tweaks. It is very important to organize your time and keep track of everything you have to do.

At beginning I was "wild" developer - that means no versioning system, all notes in txt files and backups and rollbacks implemented by copy&paste (or popular ".old", ".bak", ".backup", ".001" etc..). Of course this was long time ago.

Later on I started working with Subversion and storing my notes in Visio. Still, that was not ideal solution.

Few days ago I discovered Unfuddle webpage. Unfuddle is project that is used for hosting - it provides you with basic bug tracking system (that meets all my needs), subversion hosting, notes taking system...

And best of all - they have also free edition. In free edition you are limited to 1 project and 2 people, however still it is great way to discover Unfuddle.