Tuesday, January 13, 2009

Smoking PowerShell Pipes

Everybody likes pipes. Starting from 1972 on when Douglas McIlroy introduced the concept, pipes have been an unreplacable tool for hooking programs together. Pipes just work. Well... at least in UNIX. But you know, this is a blog about me being stuck in Windows.

Real Pipes in UNIX

The main idea of a pipe is that you take the output of one program and connect it to the input of another program. The pipe itself does nothing more than just forwards data. When the output of one program does not fit into the input of another program, then you can pipe it first through a filter program, that transforms the data as needed. But the pipes themselves remain only as a transport layer, carefully carrying data from one program to another and not changing a bit on the way.

The same holds true for real-world pipes. A good pipe is one that doesn't change the aroma on its way from bowl to your mouth. It's the tobacco you want to smoke, not the pipe.

I had a PHP script that generated test data for MySQL database. In UNIX I would have used it as follows:

php create-test-data.php | mysql dbname

I thought that this should also work with PowerShell.

Water Pipes in PowerShell

PowerShell pipes work more like water pipes. The smoke that comes in is sucked through water, changing it's aroma, softening the bitter taste. Water pipes are great, but you shouldn't try to sell them labeled as normal pipes.

When I ran the above code in PowerShell, the data generated by the script wasn't exactly the same that MySQL database received. If it even received it, because the thing crashed along its way.

Actually I didn't even had to pipe it to another program, just redirecting the output to a file changed it considerably:

php create-test-data.php > test-data.sql
Let Me Encode This for You

The first problem was encoding. The output of the script was in UTF-8 encoding. PowerShell wanted to convert the text into his internal UTF-16 representation and then convert it to another encoding when saving to file, because for PowerShell the > operator is equivalent of piping your output to Out-File cmdlet:

php create-test-data.php | Out-File test-data.sql

Luckily Out-File takes -Encoding parameter, which can have the following values: unicode, utf7, utf8, utf32, ascii, bigendianunicode, default and oem. I tried all of them, and the only one that preserved my encoding was oem – which designates single-byte encoding.

Let Me Correct Those Lines

The philosophy of UNIX has been: it's all text. The input of every program is text and the output of every program is text. Except when it's not, and when it's not, then you can't use all the common UNIX text-processing tools on it. Instead you have to use separate tools specific to your binary format. For example you can use ImageMagick to apply all kinds of transformations for images.

This philosophy was recognized by the PowerShell team as one of the great weaknesses of UNIX pipeline. And therefore the mantra of PowerShell has been: it's not all text. It has been the great promise of PowerShell, that it will enable you to work more easily with all kinds of data, not just text.

And this all works out fine, when your program outputs .NET objects. But when it doesn't, the output is treated as text. But it's a water pipe as you remember, so the text isn't just left alone, it's transformed into .NET array, array of lines.

Doesn't look that bad, does it. But the trick is that when the text is split to lines, the line separators are discarded. And when it is put back together, all lines are joined with \r\n. For example this input:

Hello,\n
my name is Rene.\r\n
I'm the author of this blog.\n

...will be converted to this output:

Hello,\r\n
my name is Rene.\r\n
I'm the author of this blog.\r\n

First of all it's dosification - all your nice UNIX file endings will be converted to ugly DOS line endings. Really annoying. Not just annoying – terrible. I think you already know where this is going: binary data.

The SQL generated by my script also included binary data. And you can imagine what this kind of conversion can do to binary data.

There is no built-in mechanism in PowerShell to overcome this problem, although the problem is well known and there exist some ugly workarounds.

Conclusion

At the end of the day PowerShell had failed me. It was the first real job I wanted to do with PowerShell and it failed completely.

If PowerShell really wants to succeed, this behavior has to be corrected. Please, PowerShell, no water inside my pipe.

Thanks to paws22 for sharing the above photo in Flickr under Creative Commons Attribution Noncommercial Share-Alike license.

Sunday, January 11, 2009

Powerless Completion in PowerShell

PowerShell has command line completion. It can complete cmdlets, arguments, methods, properties and probably many more things. Which is great. But because this is Windows, there just has to be something terribly wrong with it...

Command Line Completion Essentials

Completion can be provided for a lot of things, but there are two for which I consider completion to be essential:

  • commands (programs)
  • files and directories

Lets look how the completion of these two essential things is handled in PowerShell.

Program Name Completion

It seems natural, that when we have a command line completion, then we should be able to complete commands. PowerShell doesn't think so. Completion is only provided for the PowerShell-native cmdlets. But simple executable programs are not worthy to receive the mighty PowerShell completion. Completion also doesn't work with aliases.

Actually the completion doesn't even work well with PowerShell cmdlets. For example there is cmdlet Join-Path, which is the only cmdlet starting with letter J. One would think that you just type "J", press TAB and have it completed to "Join-Path". Yeah... but not in PowerShell. Instead you have to type "Join-" and only after that you can press TAB to have it completed.

But as I said in my previous post, in Windows real programs aren't available from command line anyway - so I guess it makes sense to not have completion for these things also.

Filename Completion

But what about filename completion. It did work reasonably well in cmd.exe. It clearly must also work in PowerShell. Well... sort of.

Suppose that you open cmd.exe and want to go to your Desktop directory. You are already in your home directory, so you just type cd and the letter d:

C:\Documents and Settings\Rene>cd d

Then you press TAB and it will be completed to:

C:\Documents and Settings\Rene>cd Desktop

This works the same way in PowerShell. But suppose you want to go two directories with a one step. Suppose you want to go to Desktop\MyDir. So you just type backslash and letter m:

C:\Documents and Settings\Rene>cd Desktop\m

Then you press TAB again and in cmd.exe it will be completed to:

C:\Documents and Settings\Rene>cd Desktop\MyDir

But in PowerShell this will be completed to:

PS C:\Documents and Settings\Rene> cd 'C:\Documents and Settings\Rene\Desktop\MyDir'

PowerShell might call this a feature, but I would certainly call this a regression.

Just Another Day in Windows

PowerShell is nice. In fact it's even quite cool. But like always with Microsoft, they managed to screw up the essentials.

Tuesday, January 6, 2009

Windows from Command Line

In Linux I used command line every day. It was my filesystem explorer. It was my administration interface. It was my programs lauchpad. It was everything.

But in Windows I haven't really made use of the command line so far. Why so? Why do I spend my time clicking around the filesystem? Why do I hunt programs from Start-menu? Have I lost the spirit of command line?

I think not. Actually I really want to use the command line. But there is something really wrong with the whole command line thing in Windows.

The Default Powerless Shell

First I though that the problem is in power, that the default cmd.exe gives you so few possibilities in combining different programs together. So I installed Windows PowerShell.

PowerShell gives you a neat programming environment where you have access to the whole functionality of .NET framework. The command set is well designed and quite easy to learn with the aid of reflection capabilities it provides. It's a lot more UNIX-like than cmd.exe – it even greets you with the familiar UNIX commands like ls, rm, cp, mv, cat, ps and kill.

So the power problem was now solved, and I spent quite a bit of time playing with my new powerful toy, but I still didn't use command line for everyday tasks like I did in Linux.

Command Line Without Commands

The real problem is that in Windows you don't have any commands to run from command line.

I mean, you don't have any interesting commands to run.

Let me explain...

Of course you have commands. Powershell has a lot of built-in commands. But you can't do a whole lot with these commands alone. You really want to invoke real programs (.exe files) to do some hard work.

Again, executables are also available from command line. There are actually a whole bunch of them available. In my system I have 372 programs available from command line:

accwizfcntvdmsort
actmoviefindodbcad32spdwnwxp
AEJUninstall40findstrodbcconfspider
ahuifingeroskspnpinst
algfixmapiosuninstspoolsv
appendfltmcpackagersprestrt
arpfontviewpathpingspupdsvc
atforcedospentntspupdwxp
ati2evxxfreecellperfmonstimon
Ati2mdxxfsquirtpingsubst
atiadaxxfsutilping6svchost
atiiprxxftppowercfgsyncapp
atiphexxgdipowershellsysedit
atiprbxxgrpconvprintsyskey
atiptaxxhelpprogmansysocmgr
atmadmhhproquotasystray
attribhostnameproxycfgZyDelReg
auditusrie4uinitputtytaskman
autochkieudinitpxcpya64taskmgr
autoconviexpresspxcpyi64tcmsetup
autofmtimapipxhpinsttcpsvcs
autolfnipconfigpxinsa64telnet
blastclnipsec6pxinsi64tftp
bootokipv6qappsrvtourstart
bootvrfyipxrouteqprocesstracert
caclsirftpQuickTimeUpdateHelpertracert6
calcIsUninstqwinstatscon
charmapjavarasautoutscupgrd
chkdskjavawrasdialtsdiscon
chkntfsjavawsrasphonetskill
cidaemonjdbgmgrrcimlbytsshutdn
cisvcjviewrcptzchange
ckcnvkrnl386rdpcliptwunk_16
cleanmgrlabelrdsaddintwunk_32
cliconfglightsrdshostunins000
clipbrdlnkstubrecoveruninst_Zyxel
clipsrvlocatorredirunlodctr
clspacklodctrregunsecapp
cmdlogagentregeditupnpcont
cmdl32logmanregedt32ups
cmmon32logoffreginiuser
cmstplogonuiregsvr32userinit
complpqregwizusrmlnka
compactlprreplaceusrprbda
conimelsassresetusrshuta
controlmagnifyrexecutilman
convertmakecabrouteuwdf
cscriptmdmroutemonw32tm
csrssmemrshwbemtest
ctfmonmigpwdrsmwdfmgr
dcomcnfgmmcrsmsinkverclsid
ddesharemmcperfrsmuiverifier
debugmnmsrvcrsvpwextract
defragmobsyncrtcshareWgaTray
dfrgfatmofcomprunaswiaacmgr
dfrgntfsmountvolrundll32winchat
diantzmplay32runonceWinFXDocObj
diskpartmpnotifyrwinstawinhelp
diskperfmrinfosavedumpwinhlp32
DivXCodecVersionCheckerMRTscwinhlp32
dllhostmscdexntscardsvrwinlogon
dllhst3gmsdtcscrconswinmgmt
dmadminmsfeedssyncsdbinstwinmine
dmremotemsgserviceswinmsd
doskeymsheartssessmgrWinSCP3
dosxmshtasetdebugwinspool
dplaysvrmsiexecsethcwinver
dpnsvrmspaintsetupwjview
dpvsetupmsswchxsetupnwmiadap
drmupgdsmstinitsetverwmiapsrv
drwatsonmstscsfcwmiprvse
drwtsn32napstatshadowwowdeb
dumprepnarratorsharewowexec
dvdplaynbtstatsherlock2wpabaln
dvdupgrdnddeapirshmgratewpdshextautoplay
dwwinnetshrpubwwpnpinst
dxdiagnet1shutdownwrite
edlinnetddesigverifwscntfy
esentutlnetsetupskeyswscript
eudceditnetshslrundllvssadmin
eventvwrnetstatslrundllvssvc
exe2binnlsfuncslservwuauclt
expandnotepadsmbinstwuauclt1
explorernotepadsmlogsvcWudfHost
ExportControllernslookupsmsswupdmgr
extrac32ntkrnlpasndrec32xcopy
fastopenntoskrnlsndvol32
faxpatchntsdsol

But these aren't interesting programs. Most of them are used by Windows internally and I have no idea what for, and the ones I know about (like notepad, mspaint, explorer, ping) are of very minimal use.

Most of the programs I actually use every day aren't available from command line. Programs like Opera, Emacs, Skype and Windows Media Player.

In Linux all programs are available from command line. If you aren't on command line – you don't exist. While in Windows the command line seems to be for suckers. Real programs are available from Start-menu.

The Problem With C:\Program Files

All this is not the fault of the programs. It's the architecture of Windows that makes adding command line programs so cumbersome that you really want to avoid it if you can.

The locations for command line programs are defined by the PATH variable. In UNIX the PATH contains directories like /bin, /usr/bin, /usr/local/bin and maybe a few more. When new program is installed the executable is placed into one of these /bin-directories and through this becomes naturally available in command line.

But when a new program is installed on a Windows machine, it is placed inside a folder of its own. opera.exe goes inside C:\Program Files\Opera and firefox.exe inside C:\Program Files\Mozilla Firefox. To make a program available from command line its location needs to be added to the PATH, making it longer and longer and even longer.

I have about 80 folders under C:\Program Files. To make all these programs available from command line, I would have to add 80 new paths to the PATH variable. And the PATH is quite long already.

Imagine a PATH like this:

C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Fil
es\ATI Technologies\ATI Control Panel;C:\ProgramFiles\QuickTime\QTSyst
em\;C:\Program Files\WinSCP3\;C:\Program Files\Smart Projects\IsoBuste
r;C:\WINDOWS\system32\WindowsPowerShell\v1.0;C:\Program Files\7-Zip;C:
\Program Files\Acro Software;C:\Program Files\Adobe;C:\Program Files\A
ltiris;C:\Program Files\AMD;C:\Program Files\ArcGIS;C:\Program Files\A
TI Technologies;C:\Program Files\AuthenTec;C:\Program Files\Avira;C:\P
rogram Files\Bentley;C:\Program Files\BitTorrent;C:\Program Files\CCle
aner;C:\Program Files\Common Files;C:\Program Files\ComPlus Applicatio
ns;C:\Program Files\CONEXANT;C:\Program Files\DIFX;C:\Program Files\Di
giDoc;C:\Program Files\DivX;C:\Program Files\DNA;C:\Program Files\Easy
Internet signup;C:\Program Files\emacs;C:\Program Files\eMule;C:\Prog
ram Files\Fingerprint Sensor;C:\Program Files\foobar2000;C:\Program Fi
les\GIMP-2.0;C:\Program Files\Google;C:\Program Files\GPLGS;C:\Program
Files\Hewlett-Packard;C:\Program Files\HPQ;C:\Program Files\Ideelabor
;C:\Program Files\Internet Explorer;C:\Program Files\Internet Explorer
Developer Toolbar;C:\Program Files\InterVideo;C:\Program Files\IT Are
ndus;C:\Program Files\Java;C:\Program Files\jEdit;C:\Program Files\Kar
en's Power Tools;C:\Program Files\KONICA MINOLTA;C:\Program Files\Logi
tech;C:\Program Files\Messenger;C:\Program Files\microsoft frontpage;C
:\Program Files\Microsoft Office;C:\Program Files\Microsoft Script Deb
ugger;C:\Program Files\Microsoft Visual Studio;C:\Program Files\Movie
Maker;C:\Program Files\Mozilla Firefox;C:\Program Files\Mozilla Thunde
rbird;C:\Program Files\Mozilla Thunderbird_new;C:\Program Files\mplaye
r;C:\Program Files\MSN;C:\Program Files\MSN Gaming Zone;C:\Program Fil
es\MSN Messenger;C:\Program Files\MSXML 4.0;C:\Program Files\MySQL;C:\
Program Files\NetDrive;C:\Program Files\NetMeeting;C:\Program Files\No
rton AntiVirus;C:\Program Files\Notepad++;C:\Program Files\Omnikey;C:\
Program Files\Online Services;C:\Program Files\Opera;C:\Program Files\
Outlook Express;C:\Program Files\pgAdmin III;C:\Program Files\Power Ar
chitect;C:\Program Files\Program Shortcuts;C:\Program Files\PuTTY;C:\P
rogram Files\Quest Software;C:\Program Files\QuickTime;C:\Program File
s\RegCure;C:\Program Files\Skype;C:\Program Files\Synaptics;C:\Program
Files\TortoiseCVS;C:\Program Files\TortoiseSVN;C:\Program Files\Visua
lSubSync;C:\Program Files\Winamp;C:\Program Files\Windows Media Connec
t;C:\Program Files\Windows Media Connect 2;C:\Program Files\Windows Me
dia Player;C:\Program Files\Windows NT;C:\Program Files\WinLemm;C:\Pro
gram Files\WinMerge;C:\Program Files\WinSCP3;C:\Program Files\xerox;C:
\Program Files\XP Codec Pack;C:\Program Files\ZTE EV-DO;C:\Program Fil
es\ZyXEL Communications Corporation

This is scary...

So I guess this finally explains why you can't make full use of Windows from command line alone.

Monday, January 5, 2009

Update in 0 Minutes

Another day I was again watching a movie, and when it ended a popup appeared asking, do I want to perform Windows Media Update. I had no reason to say no, so I agreed. The next window informed me, that the update will take approximately zero minutes. I was happy to press "next". Again I forgot, that I was stuck in Windows.

The Fast Ride Begins

Now I have two windows open. One says: "Windows is being upgraded with Windows Media Player 10". Another one says: "Installing Windows Media Player 11". So which one is it. Still running. Zero minutes as predicted...

Now it finally finished saying that I have to restart my computer for the changes to take effect. WTF! This is one hell of a zero-minute upgrade.

And We Shall Continue After a Reboot

After Restart I open Media Player to see the new upgraded version. But instead I get a window asking me again to validate my Windows installation. (I just did it yesterday!)

I click the validate button. Then I get a screen asking me to agree with some license terms, which I probably don't agree with, but click the accept button anyway.

Then I get to choose between Express Settings and Custom Setting. As Express Settings are recommended I choose those and click Finish.

Another progress bar flashes and suddenly I'm confronted with a new Media Player which clearly looks different than the one I had before.

Memories

Actually my Media Player with its new skin looks utterly familiar. I have certainly seen it before. I'm pretty sure, I have seen it running inside another XP machine before.

I check Windows Media Player 11 entry in Wikipedia and find out, that its latest release was on 30th of October 2006. That's over two years ago!

How can it be, that my computer was just upgraded with software released two years ago? I have been using this Windows machine over two weeks for now – why didn't the upgrade happen earlier? Actually, why didn't it happen two years ago? I'm pretty sure, this machine didn't just sat in the corner picking up dust for two years – somebody certainly used it, but for some strange reason he did not get the upgrade.

This leaves me to wonder whether I was magically chosen to receive this holy upgrade given only to the few of us.

Sunday, January 4, 2009

Installing Windows PowerHell

As every child knows, the command prompt Windows provides is a total piece of crap. cmd.exe is to Bash as MS Paint is to Gimp.

But I had heard that Microsoft has another shell to offer: Windows PowerShell. The name itself sounded promising and so I decided to give it a try. But you know... I was stunk in Windows.

Downloading from Microsoft.com

I read a bit of the Wikipedia entry about PowerShell and from there went to the PowerShell homepage.

I clicked on the download link and was presented with a page explaining How to Download Windows PowerShell 1.0. (Although the text on this page didn't really explain anything and sounded more like some marketing gibberish.) I decided that although I have no idea what RTW means, Windows PowerShell 1.0 RTW is probably the version that I need. I chose x86 and English language Package for Windows XP.

On the next page I was informed that the download requires validation that Microsoft has received money for my Windows installation. They really wanted to make the process painful... after all I was running Windows XP (eXtra Painful).

I downloaded GenuineCheck.exe. Ran it. Copied the generated code to the web page. Submitted it. And was finally able to click the download button.

After I had ignored the advice of installer to close all my programs and back up my system, the PowerShell was in my machine.

We'll See What Happens

So now I'm going to use this shell for a while and we shall see what kind of surprises it will bring to our table.

Friday, January 2, 2009

Firefox Annoyances

I have been Opera user for years, long before Firefox came to be. But Opera is a piece of proprietary software, and this keeps bothering me. So time after time I try out the free browsers out there, to see if some of them could replace Opera. This time when I got stuck with Windows I decided, that I will give Firefox another chance.

I spent two weeks using only Firefox, but today I'm leaving it again and going back to Opera. So, what went wrong?

Little Things Count the Most

I don't have any serious issues with Firefox, it's a decent browser, in fact it's a truly great browser. But some small things in Opera are just better:

  • Restoring recently closed tabs. Every now and then I accidentally close a tab, which is perfectly normal, because people make mistakes. In Opera I just press Ctrl-Z like I would when I want to undo any other accidential action. But in Firefox it's Ctrl-Shift-T. I didn't manage to learn this shortcut and always ended up going to History –> Recently closed tabs.
  • Duplicating tabs. Opera allows you to clone a tab along with its history and everything. Every now and then I go from page A to B and discover that actually I want to have both A and B open as separate tabs, so I clone the tab and in the cloned tab press back to get to page A. Haven't found this functionality in Firefox. Sure, I can go back and click on the link so that it opens in another tab, but it's not that convenient.
  • Spatial navigation. Because I have laptop in bed with me, there is no way to use a mouse and using the touchpad is pain, therefore I prefer keyboard wherever I can. But tabbing through the links of a web page is one of the least effective ways to navigate. Opera has spacial navigation, which allows you to move through the links of a page using arrow keys - go to the link below, go to the link at right, etc. Firefox doesn't have it (they have it implemented in CVS, but it's been there for ages).
  • Switching between tabs. I usually have more than two applications open, but most of the time I spend switching between two of them (e.g. from Emacs to browser and back) and Alt-Tab does exactly what I need. Similarly when inside browser I usually have more than two tabs open, but a lot of time is spent switching back and forward between two tabs. In Opera I just press Ctrl-Tab, which behaves like Alt-Tab outside the browser. But in Firefox Ctrl-Tab cycles through all the tabs currently open – rarely useful.
  • Downloads. Every time I download something the nagging Downloads window pops up. There isn't a direct way to disable it, although the download progress is displayed at the status bar and I could click on it instead to pop up the Downloads window when I really need it. In Opera the downloads tab (not window) also appears, but you can easily disable it, and access all your downloads through sidebar.

I'm sure there are more, but these are the ones, that manage to piss me off nearly every day.

Don't get me wrong, I really like Firefox. I would like to have the same kind of extensibility in Opera. And Firebug is a hell of a better than Opera Dragonfly. But I just can't get over those small annoyances.

Firefox is Mainstream

Not IE. At least in the circle of computer-literates Firefox is the actual mainstream browser.

But I am not mainstream. I use a niche operating system. I use a niche editor. I also like programming in niche languages like Lisp. So maybe I'm also better off with a niche browser.

Thursday, January 1, 2009

The Only Good Thing In Windows

To start new year in a positive tone, lets talk about the only good thing in Windows.

As it should be clear from my previous posts, Windows clearly fails as an operating system. When you live with Windows it constantly tries to drive you insane. But of course you want to keep your sanity, because there are other operating systems out there worth living for. But how do you keep your mind sane when everything seems to be against you?

When a programmer is faced with an API that is absolutely awful to work with, then the classical solution is to build another API on top of it, that hides away the ugliness of the bad API and makes it pleasant and maybe even fun to work with. You just create a better abstraction of the same problem.

So how do you hide Windows? Because of the law of leaky abstractions you can't hide it completely – something will always leak out. Even when you run another operating system inside Windows using virtualization, but I don't really want to go there today – one could argue, that then you aren't really running Windows any more.

Another choice is to spend most of your time inside apps that hide Windows away from you. For me, the best app for this is Emacs. And well, it is pretty darn close to an operating system.

So to answer to the question stated: the only good thing in Windows is that you can run Emacs in it.