Category Archive: Rant
One of the things that struck me whilst developing Grrr as a snapin is: what do you do when you have a cmdlet with the same verb-noun pair as an existing cmdlet?
If someone else had a cmdlet called, say, out-banner, and that cmdlet was already loaded in a snap-in (perhaps mandated by site policy), would I be able to register and add the Grrr snapin, which also defines it?
I’ve scanned the available documentation and the language grammar, used introspection in the shell and so on, but could not find anything to deal with this problem.
With projects like PowerShell Community Extensions seemingly laying claim to hundreds of common nouns and verbs, I was concerned that the scope for writing unique cmdlets would dry up real fast.
Read on »
In the unix world, we’re used to being able to run the different commands in a pipeline in different threads/processes. This is usually a lot more efficient when the producer/consumer rates vary, and makes use of multiple cores/cpus.
For example, cmd1 | cmd2 will run the two commands in separate processes.
PowerShell doesn’t do this. Everything runs in one thread, and pipelined objects are processed in batches, one bit at a time. You can control the batch size with the -outBuffer parameter, but things are still done sequentially, with one command in the pipe being busy whilst all others are sitting idle.
Even the venerable CMD.exe will put these two commands tree | more into separate processes.
This aside, what about simply running an arbitrary command (or scriptblock) in the background whilst doing something else?
Read on »
NTFS has the ability to associate multiple data streams (aka forks) to a file. It’s not very well supported in most Microsoft tools and not very well known, but I use them quite a bit for associating metadata with files.
Unfortunately, PowerShell (or rather .NET) doesn’t support them very well.
Read on »
09 Jan 2007 01:00 pm//
Rant
PowerShell is now my default Windows shell, but every now and then, little things crop up that make me want to go back to CMD.exe, or better cygwin/zsh.
Someone gave me an example of filtering an ASCII text file, stripping out the first 3 characters of each line.
On a Mac/UNIX box, you’d simply do:
cut -c4- infile.txt > outfile.txt
With PowerShell, you do:
gc infile.txt | % { $_.remove(0,3) } | sc outfile.txt
As an asside, on my machine, the latter takes 80 times longer to do the job on a 8MB text file than the former , but we’ll skip over that
So, to the gotchas.
Gotcha 1 - text gets recoded
You might be tempted to do this instead:
gc infile.txt | % { $_.remove(0,3) } > outfile.txt
If you did, the resulting outfile.txt would be UTF16 and so be double the size of the original (less the cut 3 chars per line).
You might not notice this at first, as PS1 handles all this sort of thing transparently, but at some point, something might choke on it. You can be specific about output encoding, but that’s not something you might think about.
Gotcha 2 - path weirdness
My working area is: c:\Documents and Settings\adrian\My Documents\proj\top. That’s quite a lot to deal with, so I usually make it shorter by doing this:
new-psdrive -name doc: -psprovider filesystem -root "c:\Documents and Settings\adrian\My Documents"
so my working directory is actually doc:\proj\top. Much shorter, however, when I run the first command above, I get this:
PS doc:\\proj\\top> gc infile.txt | % { $_.remove(0,3) } | sc outfile.txt
Set-Content : The given path's format is not supported.
At line:1 char:42
+ gc infile.txt | % { $_.remove(0,3) } | sc ﹤﹤﹤﹤ outfile.txt
The pipeline has been stopped.
At line:1 char:30
+ gc 100.txt | % { $_.remove( ﹤﹤﹤﹤ 0,3) } | sc outfile.txt
Set-Content : The given path's format is not supported.
At line:1 char:42
Odd that gc didn’t mind, but sc did.
You can’t even use resolve-path to fix it because if outfile.txt didn’t already exist, you’d get an error… maybe you need to use new-item -type file or something first?
To be honest, I gave up. PowerShell should really be making things easier, not throwing up barriers at every turn.
04 Jan 2007 12:09 pm//
Rant
A number of little things bother me about PowerShell, and I’d just like to outline them here.
Adding to arrays
According to get-help about_array :
“You can append an element to an existing array by using the += operator. When the operator is used on the array itself, it appends the value.”
This isn’t completely true. If the right hand side of the += is also an array, then the elements of that array are added, not the array itself. This makes it very difficult to build up an array of arrays:
$a = @() # start with an empty array
$a += 1,2 # this doesn't work - it adds 1 and 2
so you need to do:
$a += 1
$a[-1] = 1,2
I think that either a) the documentation be updated to make this clear or b) fix += so it really does add the RHS as a new element. Otherwise, I’m going to have to use something like this, which is a bit ugly (but actually much more efficient):
$a = new-object collections.ArrayList
$a.add( @(1,2) )
Update: I’ve since discovered you can do this instead with the unary comma operator followed by a parenthesised list. The syntax is a bit weird (and hard to guess) but I believe the next version of PowerShell will get better documentation in this area.
$a=@()
$a += ,(1,2)
Integer division
Many languages support integer division, yielding an integer result. Many languages compliment this by offering a modulus division aswell. This is great, because one often has an index into a pseudo-2d array and you want to get the row and column values. Notionally:
width=10
offset = 17
row = offset DIV width
column = offset MOD width
This should yield row=1, column=7
In PowerShell:
[int]$width = 10
[int]$offset = 17
[int]$row = $offset / $width
[int]$column = $offset % $width
This yields a row of 2. The division, even though both sides are [int] is done using floating point and rounded up.
To work around it, we have to do this:
[int]$row = [Math]::Floor($offset/$width)
Not sure of a sensible fix for this… maybe a new operator like -idiv ? or the pythonesque //
Oh dear, it seems that even though this is 2007, the most popular web browser on the planet (IE
Will change it over to olde worlde JPEGs later, but in the mean time, if you’re using Windows, do yourself a favour and install Firefox or IE7.
Update: I’m not entirely sure what the problem is here… this site looks fine with IE6 on Win2k, but not on IE6 on my Wife’s XP. IE7 looks fine. There appear to be known problems with IE and PNG alpha, and overlapping PNGs, but I don’t know.
I was going to start the new year with a positive note, but then I thought, lets get a PS1 pet hate out of the way first.
PowerShell is slow.
There are many ways to demonstrate this, but for this case I’m going to use a small snippet of code I found to render the mandelbrot set to the console window. It’s not my code and don’t know where it came from, but algorithm is fairly well known.
The code to demonstrate this is in a zip file here.
If you run ./mandel2.ps1 you get this pretty picture.
There is a Windows Scripting Host version. Run this with cscript mandel2.wsf.
There is a JScript.NET version. Compile it with JSC and or run the supplied one with ./mandel2.js.exe.
There is even a javascript-embedded-in-a-HTML-page version, just click on mandel2.html.
Now on my machine (a 2.66ghz quad core MacPro running XP in Parallels Desktop), I get these results:
| PowerShell |
1510 ms |
| Windows Scripting Host |
90 ms |
| JScript.NET |
160 ms |
| HTML (IE7) |
110 ms |
| HTML (Firefox 2) |
140 ms |
| HTML (Safari on OSX) |
103 ms |
OK, so the existing javascript engine in Windows (used by IE and WSF) are pretty good at this. Safari’s is pretty good (using KJS). So why is this brand spanking new language, PowerShell, so very poor?
It’s more than an order of magnitude slower than Microsoft’s previous attempt at a scripting environment!
This tardiness really shows itself in other inappropriate projects I’m working on in PS1. I really hope the PowerShell team at Microsoft address this for version 1.1 - maybe they should go speak to the jscript team.