Installing IIS on Windows XP

If you attempt to install IIS on Windows XP SP2, and you use a CD from Windows XP (pre-SP2), you may receive a message that setup cannot copy adsutil.vbs.

 The solution is to find your CD for Windows XP SP2.  If you have only a pre-SP2, then Google for Windows, XP, and slipstream to find out how to manufacture an SP2 install CD from a pre-SP2 install CD plus SP2.

Building a Ruby Extension With Win32, Windows XP, in May 2007

When I Googled for building Ruby extensions for Windows, I found a lot of old (very old) information. I found some good info at this web site. What follows is a record of my attempts to follow this guidance.

  1. Download and install Visual C++ 2005 Express Edition (free)
  2. Download and install the Platform SDK (ISO Edition) from Microsoft.
    1. I installed none of the 64–bit stuff — mostly just the 32–bit Intel core SDK
  3. Edit $RUBY_HOME/lib/ruby/1.8/i386-mswin32/config.h and delete the “#error MSC version unmatch” line
  4. Click your way to:
    • Start
    • All Programs
    • Microsoft Platform SDK…
    • Open Build Environment Window
    • Windows XP 32–bit Build Environment
    • Set Windows XP…(Retail)
  5. cd "C:\Program Files\Microsoft Visual Studio 8\VC\bin"
    • The quotes are important.
  6. vcvars32.bat
  7. cd C:\temp\guitest\ext\cguitest
    • I'm building the guitest extension
  8. ruby extconf.rb
  9. nmake
  10. mt.exe -manifest my_test.so.manifest -outputresource:my_test.so;2
    • Copy and paste the command above. You need it all from the 'mt' to the ';2'
  11. nmake install
  12. cd \temp\guitest
  13. ruby install.rb install
  14. irb
    • require 'win32/guitest'
  15. Happiness

RAD Web Development Frameworks and Tools

  1. Rails
  2. Grails
  3. Trails
  4. AppFuse
  5. Django
  6. Seaside

What I’d like to try:

  • Install the tool and any supporting infrastructure
  • Generate/create a CRUD phone book app (name, street, city, state, zip, phone)
  • Start and run the app
  • Add an email field
  • See it show up in the app

Summary (from the experiences below):

  1. Rails is easy to spark a simple app to life, owing in part to InstantRails.
  2. Grails is easy to spark to life a simple app, but it takes more grunt work.
  3. Java EE (Trails and AppFuse) is harder and more work than Rails/Grails/Django.
  4. Django is easy to spark a simple app to life.  It doesn’t appear to have anything comparable to Rails migrations, but its CRUD starter-app has more functionality than Rails.
  5. Seaside is elegant. So is Smalltalk.  I need more syntactic sugar. I can get past unusual if-statements, but I’m not going to use (word) messages for array subscripting.

Conclusions:

  1. The Ruby + Rails guys really understand packaging and reduction of barriers to entry, in addition to the oft-cited promotion.
  2. InstantGrails and InstantDjango would enable more developers to quickly become more familiar with these frameworks.
  3. Even the easy starter tools for Java EE frameworks take too much effort to attract developers from small ASP or PHP shops.
  4. I started off expecting Rails to be a clear winner.  I was impressed by Django.

<hr /><p> Rails (May 4, 2007)</p><ol><li>Download http://rubyforge.org/frs/download.php/18843/InstantRails-1.7-win.zip</li><li>Unzip into C:</li><li>Run: C:\InstantRails\InstantRails.exe</li><li>Add C:\InstantRails\mysql\bin;C:\InstantRails\ruby\bin to PATH</li><li>mysql -u root <ul><li>create database addressbook_development;</li><li>quit;</li></ul></li><li>Run: rails addressbook</li><li>cd addressbook</li><li>Run: ruby script\generate model Address</li><li>Run: ruby script\generate controller Address</li><li>Add “scaffold :address” to C:\addressbook\app\controllers\address_controller.rb</li><li>Edit C:\addressbook\db\migrate\001_create_addresses.rb adding this Ruby code to the create_table bvlock</li><li>Run: rake db:migrate</li><li>Run: ruby script/server</li><li>Browse to http://localhost:3000/address/list and test the CRUD</li><li>Run: ruby script/generate migration add_email_field</li><li>Edit C:\addressbook\db\migrate\002_add_email_field.rb , adding “add_column :addresses, :email, :string, :limit => 80” to self.up and “remove_column :addresses, :email” to self.down</li><li>Run rake db:migrate</li><li>Browse to http://localhost:3000/address/list and test the CRUD</li></ol><p>Note: It appears to me that Rails development activities can all be run as a ‘portable app’ from a flash drive.</p><p><hr /></p><p>Grails (May 6, 2007)</p><ol><li>Download http://build.canoo.com/grails/artifacts/grails-bin-0.5.5-SNAPSHOT.zip</li><li>Unzip to C:\ and rename grails-0.5 to grails</li><li>Download JDK 6u1 from http://java.sun.com/javase/downloads/index.jsp</li><li>Run the JDK install</li><li>Add environment variable GRAILS_HOME=C:\grails</li><li>Add “C:\grails\bin;C:\ant\bin” to PATH</li><li>Download Ant 1.7 from http://ant.apache.org/bindownload.cgi</li><li>Extract Ant to C:\ and rename to C:\ant.  [Note: If there is an InstantGrails that is comparable to InstantRails, somebody please tell me.]</li><li>Add environment variable ANT_HOME=C:\ant</li><li>Set environment variable JAVA_HOME to C:\Program Files\java\jdk1.6.0_01</li><li>Open a Command prompt in C:\ and run “grails” and you get a message that you can use “grails help” for help.  Try it.  Get “Error executing script Help: String index out of range: 1” and a Java runtime exception.  Great.</li><li>Run “grails create-app”.  Oops. That throws the same error.</li><li>On a whim, “mkdir grails_apps” and “cd grails_apps”</li><li>Run “grails create-app addressbook”. Bingo!  I’m guessing that the grails developers aren’t big on Windows, or perhaps they have a philosophical  objection to letting me create an app directory at the root level. I’m betting that they can’t be bothered to deal with a current directory ending with a backslash.</li><li>cd addressbook</li><li>grails create-domain-class Address</li><li>Edit C:\grails_apps\addressbook\grails-app\domain\Address.groovy and add this Groovy code inside the class</li><li>Run “grails create-controller Address”</li><li>Edit C:\grails_apps\addressbook\grails-app\controllers\AddressController.java and replace “def index = {}” with “def scaffold = Address”</li><li>Run grails run-app</li><li>Browse to http://localhost:8080/addressbook/address and test the CRUD <ol><li>How odd!  It sequences the columns as Zip, Phone, Street, Name, State, City. It is neither the order I defined them nor alphabetic, or any other sequence I can discern.</li></ol></li><li>Edit  C:\grails_apps\addressbook\grails-app\domain\Address.groovy and add “String email”</li><li>Stop and restart the app (may not be necessary). <ol><li>Oops! We lost all the old data.  Oh. That’s right, it uses an in-memory database by default.</li></ol></li><li>Download and install MySQL “Windows Essentials” from http://dev.mysql.com/downloads/mysql/5.0.html#win32</li><li>mysql -u root <ul><li>create database addressbook_development;</li><li>quit;</li></ul></li><li>Edit C:\grails_apps\addressbook\grails-app\conf\DevelopmentDataSource.groovy and make it look like this Groovy code:</li><li>Download the MySQL JDBC driver from http://www.mysql.com/products/connector/j/</li><li>Extract mysql-connector-java-5.0.5-bin.jar to C:\grails_apps\addressbook\lib</li><li>Stop and restart the app (necessary).</li></ol><p>Note: It appears to me that grails development activities can NOT be run as a ‘portable app’ from a flash drive.  Also, I didn’t find evidence of anything like Rails’ migrations.  Yes, Grails can automatically alter your database structure to match your domain model, but if you need to do anything more than add/drop database entities, you’ll have to write and sequence your updates, and you’ll own repeating the process against your production database.</p><hr /><p> Trails (May 7, 2007)</p><ol><li>Download JDK 6u1 from http://java.sun.com/javase/downloads/index.jsp</li><li>Run the JDK install</li><li>Add “C:\ant\bin” to PATH</li><li>Download Ant 1.7 from http://ant.apache.org/bindownload.cgi</li><li>Extract Ant to C:\ and rename to C:\ant.  [Note: If there is an InstantTrails that is comparable to InstantRails, somebody please tell me.]</li><li>Add environment variable ANT_HOME=C:\ant</li><li>Set environment variable JAVA_HOME to C:\Program Files\java\jdk1.6.0_01</li><li>Download Maven from http://maven.apache.org/download.html</li><li>Extract Maven to C:\ and rename it to c:\maven</li><li>Add c:\maven\bin to your PATH.</li><li>Download http://www.reverse.net/pub/apache/tomcat/tomcat-6/v6.0.10/bin/apache-tomcat-6.0.10.exe</li><li>Install the downloaded Tomcat</li><li>mvn archetype:create -DarchetypeGroupId=org.trailsframework -DarchetypeArtifactId=trails-archetype -DremoteRepositories=http://snapshots.repository.codehaus.org -DarchetypeVersion=1.0-SNAPSHOT -DgroupId=addressbook -DartifactId=addressbook</li><li>cd addressbook</li><li>mvn tomcat:run</li><li>Error message: <ol><li>Reason: POM 'org.codehaus.mojo:tomcat-maven-plugin' not found in repository: Unable to download the artifact from any rep repository    org.codehaus.mojo:tomcat-maven-plugin:pom:1.0-SNAPSHOT</li><li>Note: This is based on the instructions at http://www.trailsframework.org/Quick+Start at 9:58 PM (Eastern Daylight Time) on May 6, 2007.  It says they just changed things around a lot, so it looks to me like they haven’t finished with their changes.  Maybe I’ll try again another day.</li></ol></li></ol><p>Trying to work around the problem:</p><ol><li>Create folder C:\maven\repository</li><li>Edit c:\maven\conf\settings.xml and point localRepository to C:/maven/repository. Also define ibiblio as a mirror.</li><li>Fiddle with settings.xml until the following works: <ul><li>mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeVersion=1.0</li><li>Note: See http://repo1.maven.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart</li><li>Somewhere in there I added ibiblio as a mirror (in the maven settings.xml)</li><li>mvn archetype:create -DarchetypeGroupId=org.trailsframework -DarchetypeArtifactId=trails-archetype -DremoteRepositories=http://snapshots.repository.codehaus.org -DarchetypeVersion=1.0-SNAPSHOT -DgroupId=com.kleinfelter.demo1 -DartifactId=addressbook</li><li>Edit c:\code\addressbook\pom.xml and change the version on tomcat-maven-plugin to “1.0-alpha-1”</li><li>Note: I found the version from http://repository.codehaus.org/org/codehaus/mojo/tomcat-maven-plugin</li></ul></li><li>Add this XML to your project’s pom.xml, just before the “<build>” line.</li><li>Add a repository to pom.xml for tapernate at http://www.carmanconsulting.com/mvn/</li><li>Download tapestry-spring-1.0.0 from http://howardlewisship.com/downloads/tapestry-javaforge/</li><li>Install tapestry-spring via: mvn install:install-file -DgroupId=com.javaforge.tapestry -DartifactId=tapestry-spring -Dversion=1.0.0 -Dpackaging=jar -Dfile=tapestry-spring-1.0.0.jar</li><li>mvn tomcat:run</li><li>Boom! It starts tomcat, but when I browse to http://localhost:8080/, it dies with <ul><li>javax.servlet.ServletException: Unable to construct service tapernate.MergeReattachPropertyPersistenceStrategy: Unable to construct service hivemind…</li></ul></li></ol><p>I’m sure this all works for someone, but this is hardly making development easy.  I can see why the Grails team is proud of its work; by comparison, it is far better than this.</p><p><hr /> </p>AppFuse with Candy (May 17, 2007) <ol><li>Download and install Java EE 5 SDK Update 2 from http://java.sun.com/javaee/downloads/index.jsp
 User=admin/password
 admin-port=4848
 HTTP-port=9090
 HTTPS-port=9191
 Tell it not to start (not sure how I did this; may have disabled the Service)</li><li>Download Eclipse SDK 3.2.2 from http://www.eclipse.org/downloads/ and extract to C:</li><li>Add jdk\bin to your PATH</li><li>Download and install Windows Essentials from http://dev.mysql.com/downloads/mysql/5.0.html#downloads.  Install to C:\MySQL
 Transactional
 Data files in C:\mysql-databases
 Root password = password</li><li>Start Eclipse, set C:\Code as your default workspace, add
 http://candy4appfuse.sf.net/site
 http://commonclipse.sourceforge.net.as an update site, run update, select all available except Eclipse 3.2.1 patches</li><li>Window/Preferences/Java/Commonclipse. Select the General tab. Uncheck Append super in hashCode() and Append super in equals(). Click OK. </li><li> Window/Show View/Console</li><li>In the Package Explorer pane (left side), right-click and
  New/Project/New AppFuse project, name it HelloAppFuse, Struts 2 Basic, group =com.kleinfelter</li><li>Wait. Wait some more.</li><li>Edit pom.xml, and set jdbc.password to password</li><li>Right-click the project in Package Explorer/Run As/Maven Build… (the one with …) <ul><li>In the "Goals:" text box, enter jetty:run-war</li><li>Click Run</li></ul></li><li>Browse to http://localhost:8080/</li><li>Save this code as C:\code\HelloAppFuse\src\main\java\com\kleinfelter\model\Address.java (upper-case A)</li><li>Right-click the source code, and select Generate Getters and Setters</li><li>Select Address.java in Package Explorer, right-click/Source/"Generate hashCode() and equals()" and DE-select id.</li><li>Right-click the source/Commonclipse/"Generate toString()"</li><li>Edit src/main/resources/hibernate.cfg.xml for the basic archetypes and add after the other mapping rows: <ul><li><mapping class="com.kleinfelter.model.Address"/></li></ul></li><li>Create src/main/webapp/WEB-INF/applicationContext.xml containing this code</li><li>Create C:\code\HelloAppFuse\src\main\java\com\kleinfelter\webapp\action<a href=”/files/addressAction.java” title=”address action class”>AddressAction.java  containing this code</a></li><li>Create a src/main/webapp/WEB-INF/pages/addressList.jsp containing this code</li><li>Edit src/main/resources/struts.xml and append this code after the row with "<!– Add additional actions here –>":</li><li>Edit src/main/resources/ApplicationResources.properties and append these properties</li><li>Create a src/main/webapp/WEB-INF/pages/addressForm.jsp containing this code</li><li>Browse to http://localhost:8080/addresses.html (login is mraible/tomcat)</li><li>I still need to add the email field… This one has worn me out!</li></ol><hr /><p>Django</p><ol><li>Install Python 2.5.1 from http://www.python.org/download/</li><li>Download Django 0.96 from http://www.djangoproject.com/download/ , extract it into a temp directory, cd to the directory, run python setup.py install <ul><li>Make sure your PATH includes C:\python;C:\Python\Lib\site-packages\django\bin</li></ul></li><li>Download and install MySQL “Windows Essentials” from http://dev.mysql.com/downloads/mysql/5.0.html#win32 . Check your my.ini to verify that “default-storage-engine=INNODB” is in the “[mysqld]” section.</li><li>mysql -u root <ul><li>CREATE DATABASE addressbook_development CHARACTER SET utf8;</li><li>quit;</li></ul></li><li>Download and run mysql for python (win32 exe edition) from http://sourceforge.net/project/showfiles.php?group_id=22307</li><li>“cd c:\code” and run “django-admin.py startproject addressbook”</li><li>“cd addressbook” and run “python manage.py startapp address”</li><li>Edit settings.py and make it resemble this code</li><li>Edit addressbook/address/models.py to contain this</li><li>Add to INSTALLED_APPS in addressbook/settings.py: ‘addressbook.address’ and ‘django.contrib.admin</li><li>Edit your mysite/urls.py file and uncomment the line below “Uncomment this for admin:”.</li><li>python manage.py syncdb <ul><li>Admin user=admin, password=password</li></ul></li><li>python manage.py runserver</li><li>Browse to http://localhost:8000/admin/</li><li>Test out the CRUD <ul><li>Hey! It enforces the length=2 on state!</li><li>The basic CRUD is pretty nice, with admin login, shortcuts, history.</li></ul></li><li>Edit addressbook/address/models.py and add: ‘    email = models.CharField(maxlength=80)’</li><li>I’d like to see “python manage.py syncdb” add the new column, but it doesn’t.  You have two choices: either write and run your own SQL script to do so (‘alter table address_address add column email char(80);’) or you could: <ul><li>python manage.py dumpdata address > temp.json</li><li>python manage.py reset address</li><li>python manage.py loaddata temp.json</li></ul></li><li>Test CRUD with the new field.</li></ol><p><hr /> </p> <p>Seaside</p><p>This exercise is not really Seaside’s forte.  Smalltalkers aren’t really into relational databases, preferring object databases </p><ol><li>Download http://wwwmaster.postgresql.org/download/mirrors-ftp?file=%2Fbinary%2Fv8.2.4%2Fwin32%2Fpostgresql-8.2.4-1.zip</li><li>Create your database (“addressbook-development”) via PostgreSQL’s GUI tools.</li><li>Go into pg_hba.conf and change the authentication method from md5 to password</li><li>Download and install Seaside 2.7 via Squeak’s “world menu”/open/squeakmap, navigate to Seaside 2.7, right-click, and install. <ol><li>Tell it Debug and then Proceed on the redefining Cache error.</li><li>Config user=admin/password</li></ol></li><li>Download and install Postgress Client 1.0 via Squeak’s “world menu”/open/squeakmap, navigate to PostgresSQL Client, right-click, and install. <ol><li>Windows Service Account = kevin on local machine domain</li><li>DB user = admin/password</li></ol></li><li>Download and install Glorp 0.3.138 via Squeak’s “world menu”/open/squeakmap, navigate to Glorp port, right-click, and install.</li><li>After you load Glorp, edit PGConnection class>>buildDefaultConnectionArgs and point it to your postgres server and database.</li><li>Evaluate (“do it”) “WAKom startOn: 9090” in a Squeak workspace window, and browse to http://localhost:9090/seaside/config <ol><li>Add “addressbook” as an application.</li></ol></li></ol><p>I'm unlikely to finish this one. There is too much construction required.  For starters, if I want it to work with MySQL, I'll have to write the database driver.  You get your choice of databases, so long as your choice is PostgreSQL.</p><p>Seaside is elegant. So is Smalltalk.  I need more syntactic sugar. I can get past unusual if-statements, but I’m not going to use (word) messages for array subscripting. I like minimalism in theory; in practice, I really like common array subscripting, whether via [] or () or even (. and .) (which I used for Pascal on the DEC-10).  I like the convenience if-modifiers and the unless-statement.  I don’t need them.  I like them.  I think in English.  I think that if I were a mathematician I might like Smalltalk better.  I like its concepts, but I don’t like practicing with those concepts.</p><p>Note: http://www.squeaksource.com/MagritteGlorp.html might be interesting for a follow-up test.</p>

Don't vmware-mount a Vmdk File That Is On a USB Drive

I did a vmware-mount on a vmdk file that is on a USB drive. Then I discovered that when I wrote bytes to the virtual drive and read them back, I didn't get the same bytes back. Very bad.

More specifically, I have a large collection of files that are on both a real file system and duplicated on the virtual drive. When I run windiff, comparing the two, it reports a few as not matching. Using Windows Explorer, I copied files from the real drive to the virtual drive. I ran windiff again. They don't match.

Then I unmounted the vmdk, and copied it to my IDE drive. I mounted it there. I ran windiff and got the mismatched files. Then I copied files from the real drive on top of the bad files, and ran windiff again. They match.

I unmounted the vmdk, and copied it back to my USB drive and mounted it. Windiff reports files not equal.

Then I unmounted the vmdk, and copied the vmdk again from the USB to the IDE. I ran windiff on the vmdk files and they are the same. I mounted both vmdks (using different drive letters), and ran windiff agains the two virtual drives and the files did NOT match.

I conclude that I/O to a virtual drive stored on an external USB (2.5") drive is prone to failing silently.

Version is:
VMware DiskMount Utility version 5.5.0 build-18463

I don't have support, and I think vmware-mount is unsupported software, so I don't know how to tell VMWare about it

USB Drive Problems With Multiple Drives

Close encounter with USB Drive Failure
<p>I ran into trouble when I tried to hook up two external USB 2.5 inch drives to my desktop computer. I'd been using them with no trouble on my employer's laptop, but my contract ran out, so I took them home and plugged the black one in.</p> <p>No problem. Drive works fine. I hooked up the silver drive, and the black one went offline. Error 10, says device manager. Silver drive works fine.</p> <p>Unhooked the silver drive, reconnected the black drive, still error 10. Removed all USB drives, deleted the devices in Device Manager, and rebooted. </p> <p>Windows recreated the USB devices, but the black drive still wouldn't work. I thought it sounded like it was repeatedly recalibrating the heads.</p> <p>Downloaded and installed the latest VIA 4-in-1 driver update (my motherboard uses a VIA chipset). Rebooted, reconnected the black drive. It works. Hooray!</p> <p>Not so fast. I hooked up the silver drive again, and the black drive went dead. Nothing I could do would cause it to work right. Mostly it was totally ignored by the computer.</p> <p>I could hear it making brrrip, brrrip, brrrip sounds. Out of desperation, I hooked it up to my wife's laptop. No problems at all. Figuring the drive was failing, I copied everything to another drive.</p> <p>But it bugged me that it worked on one PC but not another…</p> <p>It is one of those drives with a Y-cable, so it can draw power from multiple USB connections. On a whim, I hooked it to a powered USB hub. It spun up without making the dreaded 'recalibration' noise.</p> <p>Notice the appearance of the quotes around recalibration…</p> <p>The really interesting thing was that the USB hub was connected to AC power, but not to a computer.</p> <p>It turns out that the brrrip sound was the drive attempting to spin up, failing, and trying again. Apparently, even with the Y-cable, it was drawing too much power for the cheap USB system on my motherboard. I'm guessing that when the drive spin-up drew enough current, the voltage dropped below 5V and the drive controller quit. When the drive spun down, power went back above 5V and the drive started to spin up again. And again…</p> <p>The solution was to plug the DATA half of the Y cable into the computer and the POWER-ONLY half of the Y cable into the hub, using the hub as a power supply.</p> <p>The drive also has an input for 5V (with reversed polarity), so I found an old power supply, and rewired its connector to tip-negative, and now the drive works fine with just the data cable and the power supply connected. </p>

Narrative for Seaside Smalltalk Blog Video

There's a good video on building a simple app with Seaside (on Squeak Smalltalk) at this blog.

 

Here's the missing voice-over:

 

  1. Start your web server (SSKom startOn: 91.)
  2. Create a new category named "SeasideBlog"
  3. Change the generic class definition to declare BlogView a subclass of WAComponent. Accept.
  4. Define a class method canBeRoot, returning true. Accept. (I’m going to stop saying, “Accept.”
  5. Define and accept an instance method

renderContentOn: html

html text: 'Hello world!'

  1. Browse to your seaside/config site (http://localhost:91/seaside/config, ID=admin/seaside)
    1. Add an application entry point “seasideBlog”
    2. Set Root Component = BlogView and click Done

i. If you don’t see BlogView as a choice, you probably defined canBeRoot as an instance method. Oops!

    1. Click your new seasideBlog link and confirm that you see “Hello world!”
  1. Create a BlogPost class, subclassing Object, with instance variables title, body, and comments.
    1. I don’t know what a Magritte description is, but whenever it asks, I tell it to create them.
  2. Create a BlogComment class, subclassing Object, with instance variables name and comment.
  3. Select name, right-click/selection/create accessors biz simple
  4. Select comment, right-click/selection/create accessors biz simple
  5. In BlogComment’s class method descriptionName, change priority to 10.
  6. In BlogComment’s class method descriptionComment, change priority to 20, and change MAStringDescription to MAMemoDescription
  7. BlogPost, (instance): create accessors biz simple for the 3 instance variables.
  8. Remove the “comments:” method but not “comments” (without the colon)
  9. Select class, delete descriptionComments,
  10. Change priority on descriptionTitle to 10
  11. Change priority on descriptionBody to 20, and change MAStringDescription to MAMemoDescription
  12. Still on BlogPost, create a database method category, and create a class method

repository

^repository ifNil:[repository := OrderedCollection new]

    1. When you accept, it will whine about repository. Tell it to create an instance variable.
  1. Alphabetize your method categories
  2. Insert the following into BlogPost’s descriptionTitle, just before beRequired:

addCondition: [:value | (BlogPost repository contains: [:each | each title = value]) not ]

labelled: 'Post with that title already exists';

  1. Select instance and BlogView and renderContentOn and make it’s body look like:

renderContentOn: html BlogPost repository reversed do: [:eachPost | html div: [html heading: eachPost title level: 2; text: eachPost body. html div: [html bold: 'Comments'. eachPost comments do: [:eachComment | html heading: eachComment name level: 4; text: eachComment comment]]]]. html anchor on: #newPost of: self <ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">Add a method:</li></ol> newPost | post |post := self call: (BlogPost new asComponent addValidatedForm; yourself ). post ifNotNil: [BlogPost repository add: post] <ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">Back in your browser: <ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">Refresh your browser and add a new post (making some sample mistakes along the way). Click Save.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Whoops! We have an error. Click the link for Debug and the debugger opens in Squeak.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">We can see where the problem is, so close the debugger and go to BlogPost’s comments method, and change the body to “ ^comments ifNil: [comments := OrderedCollection new]”</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Refresh your browser and view your new post.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Try and create a posting with the same title. Can’t do that! Change the title and save it.</li></ol></li><li class="MsoNormal" style="margin: 0in 0in 0pt">Select BlogView, renderContentOn, and make it look like this:</li></ol> renderContentOn: html BlogPost repository reversed do: [:eachPost | html div: [html heading: eachPost title level: 2; text: eachPost body. html div: [html bold: 'Comments'. eachPost comments do: [:eachComment | html heading: eachComment name level: 4; text: eachComment comment]]. (html anchor) callback:[self addCommentTo: eachPost]; text: 'Add Comment']]. <ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">Back to your browser:<ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">Refresh</li></ol></li><li class="MsoNormal" style="margin: 0in 0in 0pt">Create addCommentTo:</li></ol> <p style="margin: 0in 0in 0pt" class="MsoNormal">addCommentTo: aPost</p><p style="margin: 0in 0in 0pt" class="MsoNormal"> | comment |</p><p style="margin: 0in 0in 0pt" class="MsoNormal"> comment := self call: (BlogComment new asComponent addValidatedForm ; yourself).</p><p style="margin: 0in 0in 0pt" class="MsoNormal"> comment ifNotNil: [aPost comments add: comment]</p> <ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">Create a new method category named actions, and move addCommentTo and newPost into it.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Back to your browser<ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">New session</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Add a comment and save it.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Add a second comment and save it.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Add and save one final posting.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Turn halos on. Click on S for source.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Click on configure and set it to deployment mode.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">With a new session, no more development tools available.</li></ol></li></ol>

VMWare, VirtualBox, and Virtual PC

Testing VMWare Player 1.0.3, VirtualBox, and Virtual PC 2007...

Time between starting from the text-mode (F8) boot screen.  256MB RAM allocated to VM. Windows 2000 Pro (SP4) guest.  Host Extensions installed in every case.

Seconds before Login prompt displayed:

Safe Mode w/Networking

  • VirtualBox  31 sec
  • VMWare Player 1.0.2 38 sec
  • VMWare Player 2 beta 53 sec
  • Virtual PC 2007


Boot Normally

  • VirtualBox  26 sec
  • VMWare Player 1.0.2 29 sec
  • VMWare Player 2 beta 45 sec
  • Virtual PC 2007

Notes:

  • VirtualBox Shared Folders crashes the guest.  Semi-repeatable if you browse to C:\foo\bar and bar has hundreds of files in it.  VMWare Player has no Shared Folders.  Pay $200 for Workstation and you get Shared Folders that work.  Which is the better option: free broken or $200 working?
  • Virtual PC Shared Folders might work. I haven't tested it yet.

Tip Sheet

Tips on how to fix/tweak Windows applications and Microsoft Windows


  • USB Drives
    • If you use an external USB disk drive with Windows 2000 or XP (and maybe with Vista), set HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisableLastAccessUpdate = 1. This reduces updates on the external drive. Having a lot of updates puts your MFT at risk if a poorly designed devices munges the USB bus for a second.
  • Bluetooth
    • If your computer and your Bluetooth device aren't connected, check to see if Bluetooth Settings (via the Bluetooth icon in the tray) shows it as a connected device. If it is not shown as a device:
      • Close Bluetooth Settings, disable your Bluetooth via the computer's hardware or keyboard switch, and re-enable Bluetooth. This fixed it for me at least once.
    • If you're using the Microsoft Bluetooth stack, you should see both of the following in Device Manager:
      • [computer-name]/Bluetooth Radios/[your-Bluetooth-device-name]
      • [computer-name]/Bluetooth Radios/Microsoft Bluetooth Enumerator
  • VMWare - See VMWare
  • Delay Connection to Windows Mapped Drives
    • When you map a network drive in Windows and select the "reconnect at logon," Windows will re-map the drive when you next reboot and it will also "connect to" the drive. If you'd like to defer the connect until your first access of the drive:
      • Set (or create DWORD) HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NetworkProvider\RestoreConnection=0
      • You'll get the drive re-mapped and it will show up in Windows Explorer with a small red X until you actually access the drive.VMWare
  • Windows Mobile 5 (Smartphone) - Cingular 3124 (HTC StrTrk)
    • how do i disable the startup and shutdown sounds on a Windows Mobile 5 Smartphone
      • Delete the value of WAV (\windows\STARTUP_422.wav) in HKLM\SOFTWARE\HTC\Startup
      • Delete the value of WAV (\windows\STARTUP_422.wav) in HKLM\SOFTWARE\HTC\Shutdown
    • Recording voice tags
      1. Make sure you are in a quiet room when you record the tag.
      2. Ensure at least one hard consonant in the tag.
    • Using voice tags
    •  
      1. Briefly press the "Comm Manager" button (left side, nearest the hinge)
      2. Speak the tag
    • The buttons! What do they do?
      • Edge buttons
        • Closed
          • ALL - single-click = show external display
          • Right double-click = camera on
          • Left toggle double-click = volume control display (it works as volume control up/down when volume control is displayed)
        • Open
          • Right single = camera on; camera shutter
          • Left single click = enable voice dial and voice shortcuts
          • Left single hold = enable voice recorder
          • Left toggle = volume control
      • Interior buttons
      • Face buttons
    • x
  • McAfee VirusScan Enterprise
    • One of the McAfee modules provides "Buffer Overflow Protection" (BOP).  In theory, this is a good thing.  It prevents a virus from executing code by overflowing a data buffer into the stack or code area.  In practice, you can get a BOP error if you have an add-on to Microsoft Outlook that writes a single byte past the end of a buffer.  Since you're running the Enterprise edition of McAffee, your network administrator controls BOP, and any changes you make on your PC get overwritten within a few minutes.  Your network administrator probably doesn't want to make a BOP exception for you.  But there is a work-around.  BOP monitors only a few .EXE files.  Just copy OUTLOOK.EXE to NO-BOP-OUTLOOK.EXE and run the copy instead of OUTLOOK.EXE.
  • z