Blog

  • Creating Start Menu shortcuts with Javascript

    While preparing the installer for the Web 2.0 Starter Toolkit for IBM DB2, I had to set up Start Menu shortcuts. The way to do that is to work through the Windows Scripting Host (WSH).

    The WSH supports two built-in languages – VBScript and Jscript – and a theoretical number of third-party alternatives. VBScript is the better documented of the two in terms of examples, but I find its syntax ugly and constrained. Fortunately, Jscript can do anything VBScript can.

    So here’s how we can create Start Menu shortcuts with Javascript.

    Locate the Start Menu Programs folder

    Most interesting Windows folders can be found by working with special folders

    var shell = new ActiveXObject("WScript.Shell");
    var startmenu = shell.SpecialFolders("Programs");
    

    The shell object will be reused in code below, but you can redeclare it every time if you like.

    Create a Folder

    Scripting Guy has more details

    var folder = "My App";
    var group = startmenu + "\" + name;
    
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    if (!fso.FolderExists(folder)) fso.CreateFolder(folder);
    

    startmenu is defined above.

    Create an LNK Shortcut

    The very hidden file extension of standard Windows shortcuts is LNK. This distinguishes them from website shortcuts, which have the equally hidden extension of URL.

    If you are interested in something closer to the symbolic links of Unix, the NTFS equivalent is called junctions. You may find Junction Link Magic of interest.

    var name = "My Shortcut";
    var file = "myfile.txt";
    var path = "C:\Program Files";
    
    var shortcut = shell.CreateShortcut(group + "\" + name + ".lnk");
    shortcut.TargetPath = path + "\" + file;
    shortcut.WorkingDirectory = path;
    shortcut.Save();
    

    See the full list of properties. I recommend always setting the working directory for application links. If you don’t, your program won’t be able to load resources from it’s installation folder.

    shell and group are defined above.

    Create a URL Shortcut

    This is very similar. The main difference is that you set the extension to URL.

    var name2 = "My Other Shortcut";
    var address = "http://example.org/";
    
    var shortcut = shell.CreateShortcut(group + "\" + name2 +".url");
    shortcut.TargetPath = address;
    shortcut.Save();
    

    See the full list of properties.

    shell and group are defined above.

    Locate Program Files

    When creating shortcuts, it is often useful to know where a user’s Program Files directory is located. It is called different things in different versions of Windows, and some advanced users like to move it or rename it.

    var REG_PF = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir";
    
    var progFiles = null;
    var process = shell.Environment("PROCESS");
    if (process)
    	progFiles = process("ProgramFiles");
    if (!progFiles)
    	progFiles = shell.RegRead(REG_PF);
    

    shell is defined in the first code excerpt.

  • Setting up svn with trac

    Trac is an excellent web-based wrapper for SVN that adds bug tracking, a wiki, and several handy project management features. I keep setting up new repositories up for all the little projects we cook up in DB2 Technical Marketing, so I thought I’d write up a guide.

    Installing Trac, SVN, and dav_svn for Apache2 is left as an exercise for the reader.

    Create a new SVN repository:

    svnadmin create /var/svn/Project
    

    Create a new Trac environment:

    trac-admin /var/trac/Project initenv
    

    Change the owner to Apache so that it can read and write:

    cd /var/svn
    chown -R www-data Project
    cd ../trac
    chown -R www-data Project
    

    Navigate to Apache site settings:

    cd /etc/apache2/sites-enabled
    

    If you want Trac to support multiple repositories, edit the trac file to look like this:

    
            ServerAdmin me@somewhere.com
            ServerName mysite.com
            DocumentRoot /usr/share/trac/cgi-bin/
            
                    Options Indexes FollowSymLinks MultiViews ExecCGI
                    AllowOverride All
                    Order allow,deny
                    allow from all
            
            Alias /var/trac/chrome/common /usr/share/trac/htdocs
            
                    Order allow,deny
                    Allow from all
            
            Alias /trac "/usr/share/trac/htdocs"
    
            
                    SetEnv TRAC_ENV_PARENT_DIR "/var/trac"
            
            
                    AuthType Basic
                    AuthName "Trac"
                    AuthUserFile /etc/apache2/trac.passwd
                    Require valid-user
            
    
            DirectoryIndex trac.cgi
            ErrorLog /var/log/apache2/error.trac.log
            CustomLog /var/log/apache2/access.trac.log combined
    
    

    The above assumes that all the repositories are in /var/trac

    Navigate to Apache settings:

    cd /etc/apache2/mods-enabled/
    

    Append to dav_svn.conf:

    
       DAV svn
       SVNPath /var/svn/Project
    
       AuthType Basic
       AuthName "Subversion Repository"
       AuthUserFile /etc/apache2/dav_svn.passwd
    
      AuthzSVNAccessFile /etc/apache2/dav_svn.authz
    
      
        Require valid-user
      
    
    
    

    The above lets you check out from http://yoursite/svn/Project

    If you like, you can add a new user to dav_svn.psswd:

    cd ..
    htpasswd2 /etc/apache2/dav_svn.passwd NewUser
    

    Users can then be granted permissions by editing the dav_svn.authz file. Sample file:

    [groups]
    developers = NewUser, OtherUser
    others = ThirdUser
    
    # Restrictions on the entire repository.
    [/]
    # Anyone can read.
    * = r
    # Developers can change anything.
    @developers = rw
    
    # Other can write here
    [/trunk/public/images]
    @others = rw
    
    [/trunk/public/stylesheets]
    @others = rw
    

    Restart Apache:

    killall apache2
    apache2
    

    You now have have an Trac/SVN install with SVN at http://yoursite/svn/Project and Trac at http://yoursite/trac.cgi

  • Rails and DB2 data types

    When creating a table in a Rails migration, you have to specify data types using platform-agnostic names. The mapping of Rails types onto DB2 types is defined in ibm_db_adapter.rb:

    :primary_key => @servertype.primary_key,
    :string      => { :name => "varchar", :limit => 255 },
    :text        => { :name => "clob" },
    :integer     => { :name => "integer" },
    :float       => { :name => "float" },
    :datetime    => { :name => "timestamp" },
    :timestamp   => { :name => "timestamp" },
    :time        => { :name => "time" },
    :date        => { :name => "date" },
    :binary      => { :name => "blob" },
    
    # A boolean can be represented  by a smallint,
    # adopting the convention that False is 0 and True is 1
    :boolean     => { :name => "smallint"},
    :xml         => { :name => "xml"},
    :decimal     => { :name => "decimal" }
    

    Useful Resources

    InfoCenter | DB2 Data Types
    dW | DB2 and Ruby on Rails, Part 1 (May 2007)
    dW | An Introduction to Ruby on Rails for DB2 Developers (June 2006)

    The DB2 adapter is now called ibm_db. You can refresh your installation by typing gem install ibm_db at the command line and choosing the latest win32 release.

  • No implementation defined for org.apache.commons.logging.LogFactory

    While writing a DB2 stored procedure that invoked a SOAP/WSDL web service using Apache Axis as part of WSIF, I ran into this doozie:

    org.apache.commons.discovery.DiscoveryException:
    No implementation defined for org.apache.commons.logging.LogFactory

    Ultimately, it’s caused by a too restrictive lib/security/java.policy file that ships with DB2.

    Wrong Solution

    The standard way to define an implementation is to create the following commons-logging.properties file and place it anywhere in your CLASSPATH (such as the root of a JAR file):

    # Default
    #org.apache.commons.logging.LogFactory = org.apache.commons.logging.impl.LogFactoryImpl
    
    # SimpleLog
    #org.apache.commons.logging.Log = org.apache.commons.logging.impl.SimpleLog 
    
    # JDK 1.4 logger
    #org.apache.commons.logging.Log = org.apache.commons.logging.impl.Jdk14Logger
    
    # Avalon Toolkit
    #org.apache.commons.logging.Log = org.apache.commons.logging.impl.LogKitLogger
    
    # Log4j (Recommended by Axis)
    org.apache.commons.logging.Log = org.apache.commons.logging.impl.Log4JLogger

    Alternatively, you can set the org.apache.commons.logging.Log configuration attribute for LogFactory programmatically.

    Right Solution

    Solution: Running an Axis SOAP client in Domino [or DB2]

    My DB2 is installed into C:Program FilesIBMSQLLIB

    1. Copy all your JARs to C:Program FilesIBMSQLLIBjavajdkjrelibext
    2. Open C:Program FilesIBMSQLLIBjavajdkjrelibsecurity
    3. Open java.policy
    4. Add:

    permission java.util.PropertyPermission "java.protocol.handler.pkgs", "write";

    5. Restart DB2

  • Utilities for Windows I

    Hard Drive Cleanup

    WinDirStat is an excellent utility for visualizing your used disk space and drilling down to files that you can clean up, back up, and delete. It’s similar to SequoiaView and Steffen Gerlach’s Scanner, but even more powerful. You can drill down through a folder tree as well as highlight filetypes in the graphical representation. The next time my hard drive gets too full, this is the utility I’ll use to clean things up.

    WinDirStat

    It’s only weakness is that you can’t drill down in the visual representation once it’s built, unlike both SequoiaView and Scanner.

    Scanner 0Scanner 1Scanner 2

    Startup Management

    AutoRuns is a very comprehensive utility for dealing with the bane of hidden startup programs. TSRs and daemons date back to prehistory, but starting with Win95 a lot of rude programs began adding themselves to the system tray. This utility exposes all of the different hooks for management.

    Autoruns

    Task Management

    Process Explorer can:

    • Kill processes Task Manager cannot
    • Find which process is preventing you from deleting a file
    • Match up processes to windows
    • Kill the root process of a multi-process app

    Process Explorer

    I find it invaluable on any Windows install.

    Defragmentation

    As you delete files from your hard drive, gaps of empty space form. New files get split into parts across these gaps. Over time, performance degrades. Some file systems are less vulnerable to this than others, but both NTFS and FAT are affected.

    Windows comes with a defragmenter, but it has stayed uniformly crappy and slow since 95. I vastly prefer Vopt. Unfortunately, it’s shareware. It’s also well done, informative, and very fast.

    Is there a good, free alternative?

    Vopt

    Gods, I need to defragment!

    Hidden Settings

    Tweak UI is a cliché choice, but I don’t know of a good replacement. My favourite tweak is to disable everything except Text Document from the New submenu in Explorer. I only ever create Folders and Text Documents that way, and Explorer significantly delays the display of the menu until all the useless icons are loaded.

    Tweak UI

    While you are there, grab Create Command Window Here and Power Calculator. Being able to open a command prompt window by right-clicking on a folder is very convenient. Meanwhile, Power Calc has a usable history, saveable formulas, primitive graphing, and super-handy unit conversions.

  • Choosing colours

    One of the tricky things in web design is picking the right colours. They need to be easy to read, not grim, not flashy, yet somehow distinctive. Often, taking a stab in the dark and then tweaking a screenshot of the result for saturation, contrast, and the like can be very effective. At other times, you need a starting point.

    These have all helped me:

  • Unexpected for following namespace declaration

    I ran into a problem running a simple test xquery. I hadn’t directly dealt with XML namespaces in xquery prior to this, but the documentation was clear enough:

    XQUERY
    declare default element namespace "http://posample.org"
    for $x in db2-fn:xmlcolumn("PURCHASEORDER.PORDER")
    return $x

    Oops, EOF error. It needs a terminator.

    XQUERY
    declare default element namespace "http://posample.org"
    for $x in db2-fn:xmlcolumn("PURCHASEORDER.PORDER")
    return $x;

    Unexpected “for” following the namespace declaration? Pardon? It turns out xquery prologs need to be terminated by a semicolon:

    XQUERY
    declare default element namespace "http://posample.org";
    for $x in db2-fn:xmlcolumn("PURCHASEORDER.PORDER")
    return $x;

    Unexpected “http://posample.org”? But that’s the exact syntax given in the examples! Alas, this semicolon is distinct from the usual semicolon separator in SQL. It’s part of a single xquery statement, so what I need to do is change the SQL separator to something more exotic. This will allow xquery to be parsed correctly:

    XQUERY
    declare default element namespace "http://posample.org";
    for $x in db2-fn:xmlcolumn("PURCHASEORDER.PORDER")
    return $x@

    Eureka.:)

  • Mapping DB2 databases after a reinstall

    Due to the vagaries of software, I had to reinstall DB2 on my laptop. Unfortunately, the existing databases were not automatically added to the Control Center.

    Physically, DB2 stores its databases in a directory similar to C:DB2NODE0000. Logically, there must a way to remap them. So, how does one remap them?

    To list databases stored at a path:
    % db2 list db directory on c:

    To recatalog them:
    % db2 catalog db SAMPLE on c:

    Reference:
    DB2 at a Glance | The DB2 Environment

  • Installing Pear and PECL on Zend Core for IBM

    Links

    Atomized | PHP Performance Best Practices – Informative.

    Installing PEAR and PECL on Zend Core for IBM

    1. Save http://go-pear.org/ to go-pear.php (in, say, C:Program FilesZendCore for IBMpear)
    2. Open Command Prompt
    3. % cd “C:Program FilesZendCore for IBMpear”
    4. % ../bin/php go-pear.php
    5. Follow the steps and let it modify your php.ini
    6. Restart your Apache

    Installing the profiling packages mentioned in Best Practices

    1. % pear install Benchmark
    2. % pecl install apd