Making Windows Usable


Some of us can't avoid using Windows, whether for work or for software that won't run elsewhere. But there are things one can do to make using Windows more bearable. I've compiled here the steps I typically take to transform a Windows box into something a little more usable, with things we take for granted on other operating systems: powerful command-line tools, remote access, etc.


The most important software to install is cygwin, which provides both a set of UNIX tools and a set of UNIX compatibility libraries. IMO, Windows is completely unusable without cygwin's shells and utilities, in particular bash, perl, ssh, sshd, rsync, grep, and awk.

Installing cygwin

Install cygwin by running setup.exe from The default installation path is c:\cygwin, which I will assume has been chosen from here on. Choose the UNIX file format as the default. The package selection interface is difficult to use. If you have the disk space, I would recommend just installing everything by clicking the circular arrow next to All until it says Install (it may take a few seconds to change). Cygwin is getting larger and larger (recent installs of everything occupy nearly 2.5GB of disk space), however. If you don't want everything, go through the package list and select what you want. There are typically a number of packages not included by default that I want to have, like rsync. You can always re-run the installer later and add any packages you missed (it remembers what it already installed).

If you plan on installing cygwin on multiple machines and do not want every package, you should download locally the packages you want. Then you can point the installation GUI at the local source and tell it to install everything, which will be limited to what you downloaded and not the entire set of packages.


Cygwin's current mounts can be displayed with the mount command:

% mount
C:\cygwin\bin on /usr/bin type system (binmode)
C:\cygwin\lib on /usr/lib type system (binmode)
C:\cygwin on / type system (binmode)
Windows drives are accessible as /cygdrive/c/, /cygdrive/d/, etc. I typically mount each drive as /c, /d, etc. for shorter paths in accessing them:
mkdir /c; mount c: /c
Mounts used to be persistent by default, so you only had to issue the mount command once. On modern Cygwin versions, however, the /etc/fstab file should be edited to make persistent mounts by adding a line like this:
c:/ /c  ntfs  binary,posix=0,user 0 0
The posix=0 option turns off case sensitivity.

Many cygwin and some Windows applications can also handle mixed paths (with a drive letter but with forward slashes) such as c:/cygwin/home. The cygpath utility can be used to convert paths between Windows, 8.3, UNIX, and mixed formats. Here are some examples:

% cygpath -u c:\\cygwin\\bin\\ls.exe

% cygpath -w /cygdrive/c/cygwin/usr/bin/ls.exe

% cygpath -m c:/cygwin/usr/bin/ls.exe

% cygpath -d /c/Program\ Files/emacs-21.3/

% cygpath -u `cygpath -d /c/Program\ Files/emacs-21.3/`


I recommend adding c:\cygwin\bin to your Windows PATH for use in non-cygwin programs like Emacs or the Windows cmd shell. To edit your Windows PATH, open up:

Control Panel|System|Advanced|Environment Variables
In general, edit your own path, not the system one. The editing dialog is horribly done, as it cannot be resized. You could also edit the registry directly. Note that changes to environment variables are broadcast to the system, but only some applications (such as explorer.exe) listen for such events. You will have to restart cmd or cygwin shells to pick up any new values (as they are children of explorer.exe they will inherit the new values).

For your cygwin path, set it within your .bashrc as usual. You may want something like:

export CYGSYSROOT=`cygpath -u $SYSTEMROOT`
export PATH="/usr/local/bin:/c/program files/emacs-21.3/bin:/usr/bin:/bin:/usr/X11R6/bin:${CYGSYSROOT}/system32:${CYGSYSROOT}/system32/wbem"

Home directory

Cygwin provides a default home directory under c:/cygwin/home/, which is mounted as /home/. I prefer to use the same home directory for both cygwin and non-cygwin applications, so I want a shorter non-cygwin path. Thus I typically create a top-level directory c:/derek.

Edit /etc/passwd to update your cygwin home directory to point at your preferred home directory.

Some non-cygwin applications such as Emacs will read your HOME environment variable. Create such a variable using the same method as editing your path above and point it at your home directory. I use a mixed path c:/derek for HOME.

You could also try to change the Windows application-specific default directories by messing with other environment variables that default to the script-unfriendly Documents and Settings, though I have not yet tried this:

APPDATA='C:\Documents and Settings\derek\Application Data'
HOMEPATH='\Documents and Settings\derek'
USERPROFILE='C:\Documents and Settings\derek'
Recent Windows versions use the Users directory instead.


If you don't want to use a shell inside Emacs, or an xterm with cygwin's X server, I recommend using rxvt as a native Windows shell window that comes with cygwin. I run it like this as a Windows shortcut:

c:\cygwin\bin\rxvt.exe -sb -sl 2000 -fn "fixedsys" -bg lightgrey -e c:/cygwin/bin/ssh-agent.exe c:/cygwin/bin/bash.exe
You can select other fonts such as -fn "CourierNew-16".

Rxvt has Shift+PgUp, easy cut and paste (via Shift+Insert or the mouse middle button/scroll wheel), etc., all the features that you'll soon be banging your head against the wall wishing for if you run bash in the cmd window.

You can also customize the title of your rxvt window. I set mine via my prompt settings in my .bashrc file to indicate the hostname (to tell me whether I'm ssh-ed to a remote machine in that window) and the current directory:

if [ "$PS1" ]; then # interactive
    # set primary prompt to put host in window title
    PS1="\n\[\033]0;\h: \w\007\]\@ \w\n% "

Note that Ctrl+Z to suspend and then bg to move a foreground job into the background does not work in any cygwin window I've used. So plan your background jobs ahead of time.

If you do find yourself in cmd, you should learn the keyboard shortcuts for cutting and pasting.


I personally do not use cygwin's X server and use more of a mixture of UNIX and Windows. I find it impossible to avoid interacting with native Windows applications, so I can't completely isolate myself in the UNIX environment. The X server has caused problems for me, like preventing hibernation on my laptop. And Windows underlies it all anyway, so it may be unrealistic to try and achieve a true native UNIX feel. The UNIX and Windows environments co-exist in an uneasy truce. (Note that some of my bias here is coming from warts with older versions of cygwin where the X server involved a separate root window and X clients were separated from native Windows clients. More recent versions are getting better at integrating transparently.)

Miscellaneous Tools

You'll want to run updatedb so you can use locate to find files. You can use cygwin's cron to set up regular updates. You can also manage Windows scheduled tasks from the command line with the schtasks program (on XP and later).

For converting text file formats, use the dos2unix and unix2dos utilities.

Note that Task Manager will refuse or fail to kill certain processes. You can write a program that acquires maximum privileges to more reliably kill processes, and from the command line. You can also use the debugger:

ntsd -p PID -c q
See also sysinternals tools, such as PsKill.

  Symbolic links

Cygwin's symbolic links are only understandable by Cygwin. When the target is a directory, you can instead create NTFS junctions, which are understood both by Cygwin and by native Windows applications.

Creating junctions needs the SeCreateSymbolicLinkPrivilege privilege, which by default is not granted to non-administrators. To give yourself this privilege, run secpol.msc and then navigate to Security Settings | Local Policies | User Rights Assignment | Create symbolic links.

To create a junction from a Cygwin shell, route the command through cmd:

cmd /c mklink /J localname 'c:\path\to\target' 


Cygwin comes with a version of Emacs, and it is useful when logged in over ssh. But for interactive use I prefer a native Windows Emacs to one that requires the X server be running. You can obtain Windows Emacs and documentation from GNU. After unpacking the tarball you'll need to run the addpm program to add a Start Menu entry for it.

Windows Emacs can handle mixed paths as well as Windows paths, but it does not know about cygwin mounts.

Conveniently, you can drag-and-drop files into Emacs. Just like on UNIX you can change the font with Shift-LeftClick.

Emacs will honor your HOME environment variable. Put your .emacs file there. Also set a SHELL environment variable with a value of c:/cygwin/bin/bash.exe. This will allow you to use Emacs features that require a shell, such as compiling, running grep, or of course M-x shell.

I put Windows Emacs ahead of cygwin's Emacs on my PATH, except when over ssh:

if [[ -n $TERM ]] && [[ -n $SSH_CLIENT ]]; then
    # prefer cygwin emacs
    export PATH_EMACS="/usr/bin:/bin:/c/program files/emacs-22.2/bin"
    # presumably logged in via Windows, so prefer Windows Emacs
    export PATH_EMACS="/c/program files/emacs-22.2/bin:/usr/bin:/bin"
export PATH="/usr/local/bin:${PATH_EMACS}:/usr/X11R6/bin:${CYGSYSROOT}/system32:${CYGSYSROOT}/system32/wbem"

UNIX Emacs typically uses X resources to set its geometry and position. On Windows I set them directly in my .emacs file:

; subsequent frames are to the right
(setq default-frame-alist
      '((top . 0) (left . 687)
        (width . 91) (height . 50)
        (font . "-*-couriernew-bold-r-normal-*-12-*-*-*-*-*-*-*")
        (cursor-color . "black")
        (cursor-type . box)
        (foreground-color . "black")
        (background-color . "white")))

; initial frame is top-left
(setq initial-frame-alist '((top . 0) (left . 0)))

  Windows Shortcuts

Keyboard Shortcuts

Useful keyboard shortcuts:

Quickstart Menu

For convenient launching of custom applications, you can create a directory of shortcuts (Windows' version of symbolic links: create one by right-dragging a target file to the location where you want the shortcut and then select Create Shortcuts Here on the menu that pops up) and add it to the task bar. But there's no way to access it without using the mouse. The better solution is to stick the directory of shortcuts on the start menu. I put mine at the top level by placing a shortcut to my directory of shortcuts at:

C:\Documents and Settings\All Users\Start Menu
I call it Quickstart. Then I can access it by pressing Win q.

I set up a different shortcut for each of 3 rxvt windows, with names like 1 rxvt, 2 rxvt, and 3 rxvt, for quickly placing them on my laptop with a few keystrokes (Win q 1, e.g.):

C:\cygwin\bin\rxvt.exe --geometry 80x40-8-55 -sb -sl 2000 -fn "fixedsys" -bg white -e c:/cygwin/bin/ssh-agent.exe c:/cygwin/bin/bash.exe
C:\cygwin\bin\rxvt.exe --geometry 80x40+0-55 -sb -sl 2000 -fn "fixedsys" -bg white -e c:/cygwin/bin/ssh-agent.exe c:/cygwin/bin/bash.exe
C:\cygwin\bin\rxvt.exe --geometry 80x40+350-200 -sb -sl 2000 -fn "fixedsys" -bg white -e c:/cygwin/bin/ssh-agent.exe c:/cygwin/bin/bash.exe

"Double-Clicking" from the Command Line

I wrote a simple program called dclick that lets me launch applications from the command line using the file extension database as though I had double-clicked on the file in Windows Explorer. You can download the source code and executable from the file list. It acts like the start command in cmd. You can launch Explorer for the current directory with

dclick .

  Network Setup and Tools

SSH Agent

For password-less access to remote machines, you'll want to generate an RSA key pair on your local machine and then use the ssh agent. Be sure to keep your private key secure.

ssh-keygen -t rsa
Enter a passphrase to protect your key. Then copy your public key to the remote machine's authorized_keys file:
scp ~/.ssh/ remote-machine:.ssh/tmp
ssh remote-machine "cat .ssh/tmp >> .ssh/authorized_keys; rm .ssh/tmp"

Now you need to invoke the ssh agent. I run each of my bash instances under ssh-agent as shown earlier. Unlike on UNIX, on cygwin there is no single ancestor process (like the window manager) that we can easily run under ssh-agent. However, it turns out that a single ssh-agent process can be shared among all shells running on the machine. As long as that ssh-agent is alive the other shells can use its stored key. See the function "ssh-setup" in the sample .bashrc. The procedure is to invoke ssh-add (and type in your passphrase) in the first shell started after logging in. So long as you keep that shell alive, all later-started shells will be able to use its key without re-invoking ssh-add.

SSH Server

An ssh server can be installed on cygwin, giving remote command-line access, which is invaluable for scripting and low-bandwidth access. Here are instructions:

  1. Install cygwin packages openssh and cygrunsrv
  2. Set global env var CYGWIN=ntsec tty
  3. Make sure c:\cygwin\bin is on global Path env var
  4. Run ssh-host-config, say "yes" to privilege separation and installing sshd as a service, and have ntsec and tty in CYGWIN
  5. net start sshd
  6. sshd uses user info from its own /etc/passwd. To add users created since cygwin was installed (back up the passwd file first of course):
    mkpasswd -l > /etc/passwd
    Unfortunately you cannot copy the passwd file from another machine as the entries refer to guids on the local machine.
  7. If your home directory is not /home/user, change /home/user in /etc/passwd to the proper value (e.g., /c/user).
  8. For public key authentication: make sure .ssh/authorized_keys is o+r and that StrictModes is no in /etc/sshd_config. See also the command ssh-user-config.

When logging in over ssh, to source your .bashrc on login, you need a .bash_profile that sources it, as this is a login shell. Unfortunately a non-interactive remote login (giving a command to ssh to run) is not detected as being started by sshd (it is so detected on Linux) and so does not source .bashrc. I tried setting BASH_ENV (indicates what non-interactive bashes should source) as a global env var and restarting sshd but it didn't work. My solution is to explicitly source .bashrc in any non-interactive scripts that need it.


On Windows the hosts file is at %SYSTEMROOT%\system32\drivers\etc\hosts (on Windows NT and 2000, %SYSTEMROOT% is c:\WINNT, while on Windows XP+ it is c:\WINDOWS, assuming c: is your %SYSTEMDRIVE%). Cygwin links up /etc/hosts to the same file.

Other network tools

Other tools you should be aware of:

  Window Manager

I don't understand why Windows users put up with such a weak desktop and window manager. Fortunately there are options to add power to the interface.

Virtual desktop

There are several virtual desktop programs out there, such as Vern and Cool Desk. I use VirtuaWin, which at the time I evaluated alternatives seemed the most stable. I've been very happy with it. I set it up to not switch desktops when the mouse hits the screen edge unless Ctrl is pressed, and I use Win+arrow keys to switch between desktops. I also set a key combination to stick a window and use it to move windows from one desktop to another, un-sticking when at the destination.


Believe it or not, Windows does support focus-follows-mouse, though there is no GUI configuration exposing it. Instead you must edit a registry key and then log out and back in for the change to become effective. You can use regedit to edit the key.

On Windows NT, set the following registry key to have a value of 1:

HKEY_CURRENT_USER\Control Panel\Mouse\Active Windows Tracking
On NT it has some bugs: some apps auto-raise on focus, and alt-tab doesn't move the mouse.

On Windows 2000 or higher, you need to change a binary-valued registry key:

HKEY_CURRENT_USER\Control Panel\Desktop\UserPreferencesMask
This is a little-endian bitmask. For focus-follows-mouse, add the flag 0x1. For example, my XP SP2 laptop originally had a value of 9E 3E 05 80, which is 0x80053E9E. To activate focus-follows-mouse I changed to 0x80053E9F, or 9F 3E 05 80 in regedit.

According to you can also achieve raise-on-focus by adding the flag 0x40. I haven't tested that as I don't like raise-on-focus.

  Other Software

I typically install a few miscellaneous tools:


Sysinternals produces a number of excellent utilities for Windows aimed toward the power user. I always install Process Explorer. Autoruns is very useful for cleaning out the various auto-start programs that infest Windows computers. There are other command-line utilities for process-control, etc.


Using the Microsoft cl Compiler from the Command Line

To use the Visual C++ compiler from the command line, you need to set some environment variables. My sample .bashrc shows how I've adapted the batch file that Microsoft provides (typically at

C:\Program Files\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT
) for use with bash.


The best debugger on Windows is windbg. Its underlying engine is also present in two command-line-only debuggers: ntsd, which ships with Windows (though it's an older version) and cdb. The latter is identical to the former except it does not open a new window, which makes it useful for scripting. The kernel debugger kd also shares the same innards.

Install windbg by installing the Debugging Tools for Windows.

windbg is quite powerful. Most importantly, it exposes all of its power in its command-line interface yet still supports graphical interaction for times when that's the better way to view information.

Native OpenGL

Recent versions of cygwin use OpenGL libraries from freeglut targeting cygwin's own X server rather than the native Windows OpenGL libraries. This means that you cannot run your GL programs without first starting the X server, and you cannot have some else run them without installing cygwin.

There are two sets of header files and of libraries:

To use the native libraries rather than X libraries, you need to do two things when compiling your application:
  1. Specify the proper include path:
    make sure /usr/X11R6/include is NOT also on the include path earlier than w32api. If it is you will get link errors stemming from the calling convention mismatch.
  2. Link with the cygwin libraries that import from the native Windows libraries:
    -lopengl32 -lglu32 -lglut32 -L/usr/lib/w32api

To ensure you're using the right libraries you can launch your executable under the debugger that ships with Windows, ntsd. Look at the module list that is printed out by default on startup. correctly using windows libraries. The correct list should include C:\WINDOWS\system32\OPENGL32.dll:

ModLoad: 00400000 00566000   image00400000
ModLoad: 7c800000 7c8c0000   ntdll.dll
ModLoad: 77e40000 77f42000   C:\WINDOWS\system32\kernel32.dll
ModLoad: 68720000 68740000   C:\WINDOWS\system32\GLU32.dll
ModLoad: 77ba0000 77bfa000   C:\WINDOWS\system32\msvcrt.dll
ModLoad: 5e8d0000 5e99e000   C:\WINDOWS\system32\OPENGL32.dll
ModLoad: 77f50000 77fec000   C:\WINDOWS\system32\ADVAPI32.dll
ModLoad: 77c50000 77cef000   C:\WINDOWS\system32\RPCRT4.dll
ModLoad: 77c00000 77c48000   C:\WINDOWS\system32\GDI32.dll
ModLoad: 77380000 77412000   C:\WINDOWS\system32\USER32.dll
ModLoad: 73860000 738ac000   C:\WINDOWS\system32\DDRAW.dll
ModLoad: 73b30000 73b36000   C:\WINDOWS\system32\DCIMAN32.dll
ModLoad: 10000000 10038000   C:\cygwin\bin\glut32.dll
ModLoad: 76aa0000 76acd000   C:\WINDOWS\system32\WINMM.dll
ModLoad: 61000000 61180000   C:\cygwin\bin\cygwin1.dll
By contrast, if you're using the X libraries instead, you'll see X11R6 dlls:
ModLoad: 00400000 004bc000   image00400000
ModLoad: 7c800000 7c8c0000   ntdll.dll
ModLoad: 77e40000 77f42000   C:\WINDOWS\system32\kernel32.dll
ModLoad: 10000000 1005f000   C:\cygwin\usr\X11R6\bin\cygGL-1.dll
ModLoad: 004d0000 005ae000   C:\cygwin\usr\X11R6\bin\cygX11-6.dll
ModLoad: 61000000 61180000   C:\cygwin\bin\cygwin1.dll
ModLoad: 77f50000 77fec000   C:\WINDOWS\system32\ADVAPI32.DLL
ModLoad: 77c50000 77cef000   C:\WINDOWS\system32\RPCRT4.dll
ModLoad: 005b0000 005c1000   C:\cygwin\usr\X11R6\bin\cygXext-6.dll
ModLoad: 005d0000 00646000   C:\cygwin\usr\X11R6\bin\cygGLU-1.dll
ModLoad: 00650000 00678000   C:\cygwin\usr\X11R6\bin\cygglut-3.dll

  Interacting with UNIX

Dual-Boot Machines

If your machine also boots Linux, you may want to try Explore2fs, a tool for reading ext2 and ext3 partitions from Windows. And since Linux can read ntfs, you can transfer files in both directions. However, for both reading and writing from either operating system, a FAT32 partition is still the best way to go.

Remote Desktop Access

There are Remote Desktop Protocol (RDP) clients for Linux that allow you to connect to Terminal Services servers or Windows XP machines that allow Remote Desktop access. I use rdesktop on my Fedora box. To enable Remote Desktop on Windows XP, check the Allow box in

Control Panel|System|Remote

With old versions of X and rdesktop (prior to Fedora Core 2), I had to tweak the default X key mappings to get the Windows key to be forwarded to the remote host. I used this .xmodmaprc file:

keycode 115 = Hyper_L
keycode 116 = Hyper_R
clear MOD3
add mod3 = Hyper_L  Hyper_R
There was no support for forwarding the context menu key (keycode 117). But, recent versions need no tweaking and automagically forward the Windows key and the context menu key. Note that the right Alt key is not forwarded by default.

There are also VNC clients and servers for both Linux and Windows. When using vncviewer on Linux, unset Alt+F4 as otherwise pressing it when inside vncviewer will not be forwarded and will close the client instead of a target remote Windows application.

Windows X Server

There are several X servers available for Windows, enabling display of applications running on remote UNIX machines on your local Windows screen. With recent cygwin versions you can use cygwin's own X server for this purpose. In the past I've used Exceed, a commercial X server. New versions of Exceed may be different, but I had to copy my Linux .Xresources file into

c:/Documents and Settings/All Users/Application Data/Hummingbird/Connectivity/7.00/Exceed/xrdb.txt
and then tell Exceed to reload XRDB for Screen 0. I also liked to change the keyboard configuration to make both Alt keys go to X.

You can install Exceed's fonts as Windows fonts via the Control Panel's Fonts window. Search Exceed's database to find the file for the X font name you're interested in.


Besides unplugging your computer from the network, the best thing you can do is to keep your computer fully patched. Use Windows Update to install all service packs and security updates.

There are many features of Windows that are potential attack vectors yet don't really need to be enabled. Turn off all Windows services that you don't need, such as WWW Publishing Service, SMTP, and Messenger . You can use the MMC graphical interface (with my .bashrc simply type dclick services.msc from the cygwin command line, or type services.msc in the Start Menu | Run box, or select Administrative Tools | Services), or the new sc command-line utility on Windows XP and later. From the graphical interface, use the context menu (right-click) to bring up the Properties page and both turn the service off if currently running and change its startup type to Manual. With sc, issue this command:

sc config "servicename" start= demand

You should consider other measures like disabling the guest account and disabling hidden shares. Here is a good list of these and other key steps for better securing your computer


Comments to