I Have Fought the IIS… and Lost

I have fought the good fight. I have stood on the high ground and battled with the enemy. And I have lost.

It’s not that much of a battle, you know. I’m just trying to make Microsoft’s Internet Information Server to accept a new IP address. I have fought the configuration dialogs, I have wrestled in the early morning with httpcfg. I have stared down registry settings; stood face to face with knowledge-base articles; googled for many an article and bellowed with rage at the mute, silent error dialog.

“Network location cannot be reached.”

I edit the configuration; remove ip adresses at will; create new websites. I restart the website, restart the IIS, beat it with sticks and stones. I revert the configuration to the original settings, inspect the network card settings. I ipconfig, netstat and ping. I restart and restart again. And nevertheless, that impenetrable brick wall still looms in front of me. It… just… won’t… understand…!

“Network location cannot be reached.”

I am a user of Microsoft server products. I am a weary soldier on the battlefields of the Internet. I am a broken man.

Visualizing Software Design

I’m starting to use a new method to understand how to write software. It’s something I’ve starting doing just by myself, so I don’t know if it’s an established practice. I think it isn’t.

I close my eyes and imagine that I’m looking at the running software. I see the main form as it is on the screen, and then I rotate the view slightly, so I can see what’s behind… and what I see is a lot of little objects hanging beneath. Little services that dangle from the main form, and that are tied in to a complex engineering structure. Like this:

What is so cool is that when I imagine myself looking at this, I can change the little objects as much as I wish. I can see them tied in to each other, I see how all the calls are made and which lines are activated. I realize that object A must speak with object B, which in turn needs to speak to object C, and I ponder in the silence of my bedroom what software design patterns to apply.

I can also walk in between them, dragging the objects apart. I see what services they provide, and I ponder how they are tied into the main form, and what the main form needs to do to work. I examine the objects instanced by these services. I pat them quietly on their head, signing my approval. “Carry on, little objects”, I say.

I don’t know if it makes any difference that I examine the running system in my mind or not. I think that personally it’s a vast improvement from just trying to observe the class design, because now I don’t just see the classes, but I see how they run together, where they grind against each other, and if the design has any problems in running.

Imagination is powerful.

Living Systems

  • Why aren’t computer systems alive?
  • Why can’t I add fields at will to a database without also changing mapping xml, classes and other stupid definitions… and then having to recompile?
  • Why can’t I add methods to classes while the program is running?
  • Why is data so locked up in proprietary formats?
  • Why is XML the best (and saddest) alternative we have?
  • Why can’t I treat my database like a living, breathing thing… and visualize the data, make changes to it, and watch the changes affect the running system as I change it?
  • Why can’t I hand over responsibility of my application’s data to some local data storage, without first installing an 80 MB RDBMS behemoth?
  • Why can’t I move my application (code and data) to another machine without reinstalling and migrating?
  • Why is there no natural grouping of data over disparate data sources?
  • Why can’t I track ownership of data between systems, so that database just naturally belongs to one application, while another database belongs to another application, and is treated as such?
  • Why does it matter if I use Oracle or MySQL?

And more…

  • If I could make changes to a program, live, and press a button and watch my changes propagate through the code and alter it in real time, how do I know I haven’t made any syntactical errors? How can I be sure that it works?
  • How can I work with objects from different applications without also linking together an infrastructure of classes and frameworks?
  • Why is code and data so frozen? Transforming source code into binary code, and persisting objects into data tables, is like etching the fine nerves of a green, living leaf into a stone tablet, where it cannot be changed. Like putting the lifeblood of the universe into a freezer and storing it in a dead, fixed state; when actually it is the living thing we are interested in.
  • What unseen paradigms of software development and systems interaction do we have to unravel before any of this can be made reality?
  • Is it worth it?

Just questions in the night…

Behold, I Make All Things New

I wouldn’t be true to form unless I wrote a new program this year as well for the Oasis conference.

The upside of writing new software all the time is that you get to stay on the bleeding edge of features. Anything you could possibly want in a program is just a few lines of code away. (And a few bugs away.) And you have the opportunity of tailoring the program specifically for the environment where it will work.

The downside of writing new software all the time is that funny feeling in the stomach five minutes before launch time. Will the darn thing work? Have you checked and tested everything? Will it suddenly freeze up in mid-session, to the endless surprise and amusement of the entire conference public?

I found myself reciting Al Shepard’s prayer: “Dear Lord, please don’t let me f— up.”

But the program worked. It’s a huge relief to find that the program performs flawlessly under intense circumstances. In the 10am meeting today, the worship leader suddenly decided to abandon the program altogether, which caused a brief panic over here in the computer group, as we scrambled to search for the songs he played. How lucky we were to have had the foresight to build a search function into the program. (Maybe God knew we’d need it.)

I’ve already decided to make a branch and start working on the 1.1 version. I have a lot of ideas.

Delphi Builds Suck

Well, I never throught I’d write a post with that title.

I’m trying to script builds of Delphi programs in PowerShell. We now have an excellent script for interfacing with Vault and getting latest versions of source code from that. It’s sweet.

But building Delphi programs from the command line remains a mystery. There simply are no tools for doing that. Yes, you can run “dcc32″ from the command-line, but if you want to auto-update the build number, well… sorry, can’t be done. Yes, it’s written down in the .dof file, but it’s not used by dcc32, as .cfg isn’t used by bds. All those options are fetched from the compiled .res file, but there is no way to make the .res file manually, it is maintained solely by the IDE.

How is this possible? Who thought this up? Delphi has existed now for… how many years? Doesn’t anyone think?

No, I don’t want to use FinalBuilder, I want to use Powershell, because it’s free and I can write my own scripts without using a clumsy IDE for that as well.

So now I have to write a number of hacks for maintaining this: One that builds a default dcc32.cfg file from the loaded bpl packages, and one that updates the resource files.

Thanks, Borland/CodeGear.

Things I Never Knew Could Be Done With Cmd.Exe

I spent a part of yesterday looking through all the commands in Cmd.Exe (the Windows command shell, inheritor of the old COMMAND.COM). It’s interesting how they’ve added switches and stuff to improve on it since the early days, but how almost nobody seems to use it. Admittingly, it’s a far cry from bash, the Unix command shell, but there’s a few old tricks you still can pull out of the hat. People may flame it and despise it, but I always thought you should be able to do more with the good ol’ shell.

Here’s a few of the things I found … in alphabetical order.

ATTRIB [/s] [/d]

Changes file attributes. /s makes it recursive, /d makes it operate on directories as well. I didn’t know about these switches before. Handy.

CALL :label arguments

Neither did I know you could call a label in a batch file. This should make it easier to write “gosub”-like routines. And the parameters can be expanded with new interesting features, see below. To exit from the subroutine, use the “goto :eof” statement.

CHKNTFS

Schedule a check-disk on next boot. Might come in handy sometime.

EXIT /b [errorlevel]

Exits the command shell. If you use the /b switch, exits the current batch file. You can also pass an errorlevel along.

F7

Pressing F7 brings up the history list. How come I never knew that?

FINDSTR [/r] [/c:]“search string” filespec

Find strings in files. I might still use Turbo Grep, but this is cool too. Normally it searches using an OR pattern on the search string (meaning “I love you” finds all instances of “I”, “love” or “you”), use the /c: switch to make it an AND search.

The /r parameter turns the search string into a regexp. Note, some of the fancier stuff might not work as usual, consult the FINDSTR /? or the online help for further information.

FOR %%v IN (set) DO …

The FOR command is one of the coolest features in batch programming. I had no idea you could do so much with it.

FOR %%f IN (dpr pas dfm res) DO COPY *.%%f \deploy

Copy all Delphi source files for a project to a specific directory.

FOR /d %%d IN (set) DO …

Match directories in wildcards instead of files.

FOR /r [path] %%v IN (set) DO …

Recursive operation on files found, optionally operating relative to “path” instead of the current directory. It might be used like “FOR /r c:\deploy %%f IN (*.*) DO ATTRIB -r %%f”, which will recursively remove the read-only attribute from all files in c:\deploy.

FOR /l %%v IN (start, step, end) DO …

For-loop. “FOR /l %%v IN (1, 1, 5)” gives the sequence 1 2 3 4 5.

FOR /f ["options"] %%v IN (file-set | “string” | ‘command’) DO …

The /f parameter is probably the most interesting feature I’ve found. It reads lines from an input file, string, or result from a shell command, tokenizes them and processes a command for each line. Normally, the token delimiters are space and tab, and it usually operates on the first token found, so without extra options you will always get the first word in each line. But it can be modified with the following options:

eol=c Set the end-of-line character. One character only.
skip=n Skip n lines in the beginning.
delims=xxx Delimiter set, default is space and tab.
tokens=x,y,n-m Which tokens to feed into the command. Variables start at the variable given, and allocates further as needed in alphabetical order. * means “the rest of the line”.
usebackq Use backticks instead of apostrophe for the command evaluation. The format changes to (“file-set” | ‘string’ | `command`). Required if you use filenames with spaces.

FOR /f “eol=; tokens=2,3* delims=, ” %%i IN (myfile.txt) DO @ECHO %%i %%j %%k

Parse each line in myfile.txt, ignoring lines that begin with semicolon, pass 2nd and 3rd tokens into the command, separating each token my either comma or space. Notice how the sequence goes: %i, %j, %k.

FOR /f “usebackq delims==” %%i IN (`set`) DO @ECHO %%i

Enumerate all variables found.

Expansion of variable parameters is also available, see below.

GOTO :eof

Jump to end of file. Handy way of exiting from a script.

IF [NOT] ERRORLEVEL n ..
IF [NOT] EXIST filename …
IF [NOT] string1==string2 …
IF [/i] string1 EQU|NEQ|LSS|LEQ|GTR|GEQ string2 …

The normal IF command is enhanced, too. It can check errorlevels as before, file existance, and compare strings. But is also has new operators. For instance, the “IF ERRORLEVEL 3″ statement can now be written “IF %ERRORLEVEL% LEQ 3″.

/i means case-sensitive (or case-insensitive, I forgot which). Numeric strings evaluate as numbers, not strings.

IF now also supports multi-line statements and ELSE statements, see below.

MD \a\b\c\d

Will create new directories in sequence.

MORE /e

Extended more. These keys are available:

P n – next n lines
S n – skip n lines
F – next file
Q – quit
= – show line number
? – show help line
space – next page
return – next line

MORE +n

Start from line n.

PUSHD \\server\path

Create a temporary drive allocation, starting from Z:, for the particular UNC path. This will be cleared with POPD.

RD /s /q

Very dangerous command.

SET [var[=[value]]]
SET /a [var=]expression
SET /p var=[prompt]

SET only will display all variables. SET P will display all values starting with P. SET P= will clear variable P.

SET /a will perform a calculation, for instance SET /a X=2*2 + 5.

SET /p will prompt for user input and store the result in a variable.

SETLOCAL / ENDLOCAL

Make local changes to the environment. Work all you want with it, then call endlocal to revert back to where you were. Also handy, especially with some of the advanced SET features.

SHIFT [/n]

Shift parameters. Optionally start at the nth position, preserving all elements %0 .. %(n-1).

SORT [/+n] [/o outfile]

Sort may start sorting at the nth position now. Could be good for unwanted stuff in the beginning (timestamp in logs, perhaps). /o is faster than piping.

Interesting ways of treating variable expansion

Some new ways of treating variables are available. Like, string substitution and substring matching.

%PATH:str1=str2% Substitute all occurrences of str1 with str2.
%PATH:~10,5% Substring, start at position 10 and extract 5 characters.
%PATH:~-10% Only get the last 10 characters.
%PATH:0,-2% Extract all but the last 2 characters.
 
%CD% The current path
%DATE% Current date
%TIME% Current time
%RANDOM% A random number between 0..32767.
%ERRORLEVEL% The current errorlevel.
 
%* All arguments
%0 .. %9 Arguments
%~1 Remove quotes from parameter 1
%~f1 Expand to fully qualified filename
%~d1 Expand to drive letter only
%~p1 Expand to path only
%~n1 Expand to file name only
%~x1 Expand to extension only
%~s1 Expand to short file name only
%~a1 Expand to file attributes
%~t1 Expand to file date/time
%~z1 Expand to file size
%~$PATH:1 Search through all directories specified in %PATH%. If the file is found, return the
fully qualified filename in that directory. If the file isn’t found, return blank.
%~dp1 Expand to drive and path. (Further elements may be combined: %~ftza1 gives a DIR-like output)

Interesting ways of doing IF and FOR statements

There’s a syntax I’ve never seen either with IF and FOR statements. You can use IF-ELSE-syntax in this way:

IF EXIST hello.txt (
    DEL hello.txt
) ELSE (
    ECHO hello.txt is missing!
)

…or even…

IF EXIST hello.txt (DEL hello.txt) ELSE (ECHO hello.txt is missing!)

And how about this?

FOR /l %%v IN (1 1 5) DO (
    ECHO This is line number %%v.
)

The crucial thing seems to be, in ELSE statements, that ELSE has to be written “on the same line” as the IF statement. This is why ELSE is written on the same line as the parantheses.

So there you are. A whole new way of writing batch files. No extra software needed, just plain old Windows XP.

A Room with a View


For the past few days we’ve been intensely renovating and redecorating our workspace. The walls have been painted, a whole section of the wall has been torn out, and everything smells of fresh paint. There’s a ton of furniture, old computers and other stuff lying around, but step by step, we’re completing the job.

Anyhow, this means I now have a room with a view, so I can see the outside world as it goes by.

09:35 and Everything is FUBAR

A state of FUBAR occurred today at 09:35. Unusually fast, I thought.

I tried to run a program I’ve written today from a mapped drive, t:. It works beautifully when I run it from my hard drive on c:, but .NET considers t: to be less secure, and therefore the program throws a SecurityException when I try to run it from there. I don’t know why. I guess I could trace the setting down and change it somehow, but I don’t have the heart for it.

It is a wonderful practical application of the policy “Security by Insanity“.

The program, incidentally, works beautifully. It reads Excel files and transforms them into resource files. It works on my computer (Excel 2007), it works on our shared server (Excel 2003), but fails mysteriously with an “an exception has been thrown by the target of an invocation” exception on the customer’s computer (Excel 2003) and his colleague’s computer (Excel 2003).

FUBAR is an excellent term. It is an acronym for “Fouled Up Beyond All Recognition”. (Feel free to replace “fouled up” with a stronger term also beginning with F, if you want to.) It is thought to come from the U.S. military during World War II. Another useful term borrowed from the military is BOHICA (Bend Over, Here It Comes Again), or SNAFU (Situation Normal, All Fouled Up).

The IT industry has a lot of things in common with the U.S. military, I’ve noticed.