Having done this a few times before and always ending up scouring the documentation regarding exactly how to enable the options I need, I’m hereby committing it to long-term memory…

Subversion 1.4.0 and later support running Subversion directly as a Windows Service. This allows you to access your repository via TortoiseSVN, svn.exe, etc. using:

svn://server/RepoName

You can find information in the Subversion FAQ as well as a link to a document describing exactly how to set it up. There is no tool provided to configure the Windows Service. So you’re stuck using sc.exe, the Service Control command line tool, which ships with various versions of Windows. It is rather quirky, even for command line tools. Note that the name/value pairs are “Name=” followed by a space followed by “Value”. The equals sign is part of the name and won’t work if the equals sign is omitted or if you insert a space before the equals sign.*

Here’s how I typically configure Subversion to run as a service:

sc create <ServiceName> binPath= “\”<PathToSvnBin>\svnserve.exe\” –service -r <SrcRepoRoot>” DisplayName= “Subversion Service” depend= Tcpip start= auto obj= <Computer or Domain\ServiceAccount> password= <Password>

where

<ServiceName> is the name of the service (as used in commands such as net stop <ServiceName>).

<PathToSvnBin> is the fully-qualified path to svnservce.exe. N.B. You have to surround it with \” to escape the path if it contains spaces.

<SrcRepoRoot> is the fully-qualified path to the directory that contains all your repositories.

<ComputerOrDomain\ServiceAccount> is the user account under which you want to run the service. You need to include the computer or domain name (depending on if it’s a local or domain account, respectively).

For my environment, it ends up looking like this:

sc create svnserve binPath= “\”C:\Program Files\Subversion\bin\svnserve.exe\” –service -r c:\SrcRepos” DisplayName= “Subversion Service” depend= Tcpip start= auto obj= Server\SvnDaemon password= P@ssw0rd

I usually use a local computer account, SvnDaemon, for running my repositories. After creating the account, I remove it from the Users group. By removing the account from Users, no one can log in using that account and it also removes it from the main log-in screen in Windows XP and Vista. In Local Security Policy… Local Policies… User Rights Assignment…, grant SvnDaemon the “Log on as a service” privilege. Explicitly grant Full Control to c:\SrcRepos.

Last thing you need to do is punch a hole in your firewall to allow connections on the standard svn port, which is TCP 3690.

Now you can start the service via “net start svnserve”. Your firewall might prompt you to grant permission for svnserve.exe to listen on the Subversion port.

Time to test. Launch the TortoiseSVN RepoBrowser and enter “svn://server/RepoName”. You should be able to now browse your repository.

* Note that PowerShell doesn’t grok the “Name=” syntax. PowerShell tries to interpret it as some sort of assignment. I haven’t bothered digging in to find out how to instruct PowerShell to treat the “Name=” literally. In the meantime, it works just fine from cmd.exe. Confused

Next week, I am competing in Speaker Idol at TechEd 2007 in Orlando, Florida. What is Speaker Idol? Think Idol – Geek Edition. There will be twelve geeks taking the stage to sing and strut their stuff.* The Honourable Carl Franklin and Richard Campbell of .NET Rocks fame will be hosting. We’ve each got 5 minutes to present on a technical topic of our choice. The top prize is a highly-coveted speaker slot at TechEd 2008. The competition should be a lot of fun and is being broadcast from the Virtual TechEd stage. So even if you’re not there, you can cheer me on from the comfort of your own office. I’ll post links for the competition once they’re available.

* I can make no guarantees that I will or will not sing. You’ll have to tune in and find out. Open-mouthed

I honestly don’t know who is right or wrong from a legal perspective (Damn it, Jim, I’m a developer not a lawyer!), but does anyone find it a bit strange that Microsoft is suing Jamie Cansdale over TestDriven.NET? Jamie’s legal troubles stem from TestDriven.NET supporting Visual Studio Express. Microsoft apparently feels that add-ins to VS Express are verboten.* Read Jamie’s posts here and here and make your own decision. Is Microsoft really worried that VS Express and TestDriven.NET are such a killer combo that it’s going to impact sales of VSTS Developer Edition? My guess is that allowing one add-in opens the door for other vendors to create add-ins. So it’s more about establishing precedent than Microsoft feeling that unit testing and code coverage integration are not appropriate for hobbyist developers.

Regardless of Jamie’s legal troubles, TestDriven.NET is an excellent add-in. In an effort to support software that makes my development life easier, I’ve bought a copy of TestDriven.NET. Thanks for all your hard work, Jamie.

* If add-ins aren’t allowed in VS Express, does Microsoft have to sue themselves over Popfly Explorer? (I can’t take credit for this as it was pointed out by Stephen Oakman, a commenter on Jamie’s blog.)

UPDATE: Bil makes a good point that XNA Game Studio Express is another Microsoft-made extension to Visual Studio Express. Personally I don’t buy the “Microsoft is giving Express away for free and therefore should be able to extend it if they want” argument. If that was a valid argument, I would recommend to Microsoft that they give away Windows for free. Then Microsoft could tell various third-party software companies (anti-virus, Adobe, Sun, etc.) that their products violate the EULA for the free Windows operating system, but release competing products. Well, they wouldn’t actually be competing because there would be nothing to compete with. Note that this would be a completely different story if a product enabled unavailable premium features, such as Vista Ultimate Extras on a non-Ultimate editions. We’re talking about extending a piece of software to which you have a license.

Kenny Kerr has released Window Clippings 2.0, complete with its own website. I’ve been using Window Clippings for a few years now and it continues to be my favourite screen capture tool. Simple, efficient, elegant, and (mostly) free. He has been continuing to update it and it includes cool features like:

  • Support alpha transparency, both for windows and mouse cursors, enabling capture of non-rectangular windows.
  • Outputs to a variety of formats, including PNG, JPG, TIFF, and BMP. (Extensible through add-in model.)
  • Capturing to a variety of destinations including any combination of directory, clipboard, and OneNote.
  • Support for Aero Glass, including removing “dirty glass”.
  • 32-bit and 64-bit Windows support, including XP, Server 2003, and Vista.
  • Optional integration with PrtScn key.
  • Automatic updates.

From Day One, Kenny has provided this awesome utility free of charge. With Window Clippings 2.0, Kenny is turning this into a small business. You can download and use Window Clippings for free with all the features it had before. With 2.0, he has added some advanced features (such as post-processing PNG images and enabling add-ins) that are enabled when you buy a license. Licenses currently cost a whopping $10 USD! I have more than happily sent Kenny $10 so that he can continue development of this awesome tool.

Source control is a must when it comes to development. It doesn’t matter if you’ve got a large team of developers or if you’re the only one. You need to set up source control. For my own pet projects, I use Subversion. Simple to set up and simple to use, especially with TortoiseSVN. I’m not going to go into a long intro on how to set up and use Subversion or TortoiseSVN. There are many quickstarts kicking around the web on how to do this. You can google those as well as I can. What I am going to discuss is initial repository setup.

I usually create a Subversion repository per project. If I ever need to move a repository to another computer, I simply copy the directory containing the repository. No complicated export/import scripts required. Same is true with backup/restore. If something goes horribly wrong (which it never has, but just in case), I can retrieve the source repository from backup without affecting any other repository. The standard structure within a repository includes a number of project-level directories, including trunk, tags, and branches:

Trunk is where mainline development occurs. Most of the time, I will be working from svn://Eddings/Sample/trunk. When you create a release, I want to tag it, which involves making a copy of the files in trunk (or elsewhere) to the tags directory. For instance, using TortoiseSVN, I would Branch/Tag… to svn://Eddings/Sample/tags/v1.0. (N.B. Subversion uses a copy-on-write mechanism so that I’m only storing one copy of a file, even if I tag/branch it multiple times. It also uses a binary differencing mechanism to keep the repository small. So if I add a 10 MB binary file to my repository, change a few bytes, and push my changes back into the repository, the space occupied by the file will be 10 MB plus the few bytes of changes plus some versioning information.) Branches is exactly the same as tags, except it is typically used as temporary scratch space for changes that will later be merged into trunk or tags. For instance, let’s say I released v1.0, which is tagged. I am working on v2.0 in trunk, but I need to make a bug fix in v1.0. I branch v1.0 into branches/v1.0-Remediation and make the fix. When I’m ready to release, I tag branches/v1.0-Remediation as tags/v1.01 and delete branches/v1.0-Remediation. I will probably reverse integrate the bug fixes into the trunk.

Typically I also point my new repository to a globally-maintained user list. (Unfortunately Subversion doesn’t integrate with Windows auth out-of-the-box. I believe you can do it, but you need to run Subversion under Apache. More trouble than it’s worth for a single developer, in my opinion.) So there’s another manual step…

The main take-home message is that when I create a new repository, there is a bunch of initial setup that needs to be done. Why not automate it? I wanted to learn PowerShell and this seemed like a good mini-project to do it on. This is based on my own exploration of PowerShell and there might be better ways of doing things in PowerShell. So your mileage may vary. Don’t take this as gospel or best practices, but as one man’s fumblings through learning PowerShell.

Why PowerShell?

First question is why do we have scripting environments in the first place. Usually it’s because we need to glue together a bunch of commands to do something more complex. The complexity doesn’t warrant a full-fledged application and we want to be able to change it easily. Scripting to the rescue. It’s the main reason we’ve had the Windows Command Shell and the Windows Scripting Host on the Windows platform and bash, ksh, tcsh, … on Unix platforms.

Next question… Why PowerShell and not something with more sex appeal like Ruby? PowerShell has an attraction for me because it targets the .NET platform. 90% of learning a new environment is learning the libraries. PowerShell lets me leverage my .NET knowledge in a scripting environment. Maybe I’ll learn Ruby one day, but Ruby is a one-trick pony in my opinion — specifically Ruby on Rails. RoR is one hell of a trick for web applications, but I’m not ready to learn a whole new set of libraries just to write web apps. I don’t like web applications that much! Tongue out

Just like bash, ksh, tcsh, and other command shells before it, PowerShell lets me glue together simpler commands to create complex scripts. The Unix shells did this by having standard mechanisms to pipe the results of one command to the input of another, but everything is text. This means that each command requires its own parsing routines to handle the incoming text. PowerShell communicates between cmdlets using .NET objects. No more dealing with raw strings. Now I can examine objects, query them using reflection, or use them to perform actions. Cool stuff!

Getting Started with PowerShell

There are a number of good references for PowerShell that you should definitely keep close at hand.

I’m not going to walk through all the features of PowerShell as others have already done that. What I will do is discuss how I solved different pieces of the puzzle in building a script to create a new Subversion repository. Let’s look at the script piece-by-piece.

Execution Policy

Before we can execute a PowerShell script, we must modify execution policy. By default, PowerShell ships in a locked-down mode that prevents scripts from running. You can execute cmdlets at the PowerShell prompt, but you can’t execute “.ps1” files containing scripts. To enable running script files, open a PowerShell prompt and execute:

Set-ExecutionPolicy unrestricted

Note that PowerShell features cmdlet completion using the tab key. So typing set-e[TAB] will auto-type the rest for you. If there are multiple cmdlets with the same name, you can tab multiple times to cycle through the options. You can even use wildcards to pattern match cmdlets and cycle through matching cmdlets using tab.

CreateSvnRepo.ps1

PowerShell code is in green. Discussion is in black. A discussion of implementation details are after each section of code. I’m not going to discuss the purpose of each section as that is noted in the comments heading each major section.

# CreateSvnRepo v1.2
# Copyright © 2007 by James Kovacs
# All rights reserved.
# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
# ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
# TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND/OR FITNESS FOR A
# PARTICULAR PURPOSE.

Just an informational header. Comments in PowerShell are denoted by the hash (#) sign.

# Check usage
If($args.Length -ne 1) {
  Write-Host "Usage: .\CreateSvnRepo.ps1 "
  Write-Host "  where RepoName is the name of the new repository"
  Write-Host "N.B. RepoName cannot accept a file path or url."
  Write-Host "     CreateSvnRepo assumes that svn and svnadmin are in your path."
  Exit(0)
}

We need to check the command line arguments and possibly print usage information. The script expects to be called like this:

.\CreateSvnRepo.ps1 <RepoName>

where RepoName is the name of the new repository.

Variables in PowerShell are prefixed by $. There are a few default variables such as $args, which is the command line arguments. (N.B. Like in .NET, the executed script is not included in the list of arguments.) $args is a string[] and we can check its Length property, just like in C# or VB.NET. Comparison operators in PowerShell do not use conventional operator syntax, but instead use “dash” syntax. For instance, -ne is not equal, -eq equal, -gt greater than, -ge greater than or equal, -lt less than, -le less than or equal, etc. There are also bitwise, matching, and type comparison operators as well as case-insensitive versions where appropriate. See Comparison Operators in the PowerShell Quick Start for a full list.

Write-Host serves the same purpose as Console.WriteLine. Notice that cmdlet calls do not use parentheses to denote arguments as this matches the flavour of calling commands in scripting environments. Also note the standard syntax used for cmdlets, which is VERB dash SINGULAR NOUN. Even if you expect multiple items, the singular noun is used. For instance, to get a list of running processes, execute Get-Process. Cmdlets are case-insensitive.

# Set up variables needed by script
$newRepoName = $args[0]

Variables are created when they are assigned. We do not have to explicitly set the type of a variable, though we can by prefixing the variable with [type]. For example, [int]$i = 42.

$currentWorkingDir = (Get-Location).Path.Replace("\", "/")

Get-Location is a cmdlet that returns the current working directory as a System.Management.Automation.PathInfo object. To execute the cmdlet and get its result, we wrap the cmdlet in parentheses. Without the parentheses, PowerShell assumes we’re looking for a cmdlet or executable named Get-Location.Path.Replace. (This is because executables often have names such as DoStuff.exe.) Once we have a PathInfo object, we can examine its Path property. Notice that the Path property returns a string and we can perform normal .NET string operations on it, in this case changing backslashes to slashes since svnadmin (the Subversion command for creating repositories) uses Unix-style path separators.

Speaking of Unix, PowerShell includes a lot of Windows and Unix aliases. Aliases are names that execute cmdlets, possibly with parameters. For instance, both “dir” and “ls” actually execute “Get-Item *”. An alias for Get-Location is “pwd” or print working directory, which should be familiar to all Unix-heads. Get-Alias lists all the currently defined aliases and Set-Alias allows you to add or modify an alias.

$newRepoSvnPath = "file:///$currentWorkingDir/$newRepoName"

There are two types of strings in PowerShell, expanded and non-expanded strings. Single-quotes are used to denote non-expanded strings, similar to string literals in C# using @”No special characters here”. Double-quotes are used to denote expanded strings. Any variables in the string are replaced with their value. So if $fortyTwo = 42, then ‘The answer to life, the universe, and everything is $fortyTwo’ has the value The answer to life, the universe, and everything is $fortyTwo whereas “The answer to life, the universe, and everything is $fortyTwo” has the value The answer to life, the universe, and everything is 42.

$repoConfigFile = Join-Path $newRepoName 'conf\svnserve.conf'

Join-Path performs the same function as System.IO.Path.Combine in that it saves you from having to worry about whether the strings have directory separators in the correct places.

$tempPath = [System.IO.Path]::GetTempPath()
$tempDirName = [System.IO.Path]::GetRandomFileName()

Here I need to access some static methods for which there is no equivalent cmdlet (as far as I know). We identify the type using square brackets followed by :: and the name of the static method.

$workingCopy = Join-Path $tempPath $tempDirName
$dirNames = 'branches', 'tags', 'trunk'

The only new thing here is that we’re creating an array of strings. Nothing special, just comma-separate the objects and assign them to a variable.

# Ensure that we were passed only a repository name and not a path
$invalidChars = [System.IO.Path]::GetInvalidFileNameChars()
If($newRepoName.IndexOfAny($invalidChars) -ne -1) {
  Write-Host "You must specify a valid repository name. It cannot be an absolute or relative path."
  Exit(-1)
}

More of the same, except now we’re calling a method on $newRepoName, which is of type System.String. This is a standard .NET method call with parameters. So we use parentheses around the arguments, as you can see in the call to IndexOfAny. This is the main difference between calling cmdlets and calling methods on objects.

# Ensure that repository doesn't already exist
If(Test-Path $newRepoName) {
  Write-Host "Error: Repository, $newRepoName, already exists."
  Exit(-1)
}

Here’s a new cmdlet, Test-Path, that will let us know if the path already exists or not.

The help system in PowerShell is quite useful. You access via Get-Help (or the shorter alias, help). Get-Help cmdlet will give you information on a command. Get-Help Get-Help gets help on the help system itself! Get-Help accepts wildcards. So if you want to find out everything you can do with Paths, type Get-Help *-Path. If you want to find everything you can Set, type Get-Help Set-*. This is an excellent way to poke around and find out more about available cmdlets.

# Create directory to hold the new repository
Write-Host "Creating new repository: $newRepoName"
New-Item -path . -name $newRepoName -type directory

We’re using the New-Item cmdlet, but this time we’re using named parameters. New-Item can be used to create directories, files, registry keys, and more. PowerShell uses a provider model. So as long as there is an appropriate provider, you can interact with any information store. Anyone can create a provider to extend the functionality of PowerShell. For instance, people are implementing (or have implemented) PowerShell providers for Subversion, Newsgator, SharePoint 2007, …

If(!(Test-Path $newRepoName)) {
  Write-Host "Unable to create directory, $newRepoName. Verify that you have permission to create this directory."
  Exit(-1)
}

We can use ! or -not to negate a boolean value. Here we want to make sure that we successfully created the directory.

# Create the repository
svnadmin create $newRepoName

Svnadmin is an executable that ships with Subversion. It is used for creating repositories, among other things. I execute it just like I would from the command line. The only trick is that I’m passing it the value of a PowerShell variable.

# Clear repo configuration directory
$configFiles = Get-ChildItem -path $repoConfigDirectory
ForEach ($configFile in $configFiles) {
  Remove-Item -path $configFile.FullName
}
# Overwrite configuration file to point to global password directory
"[general]`r`nanon-access=none`r`npassword-db=../../passwd`r`n`r`nrealm=Default`r`n" | Out-File -filePath $repoConfigFile -encoding ASCII

Now we’re entering territory that is usually reserved for Perl-heads. (If you’ve ever read Perl code, you’ll know what I’m talking about.) I’m creating an expanded string (denoted by double quotes) that includes escaped character sequences, which are denoted by the back tick (`). I find the back tick a bit odd to read, but it has the advantage that you don’t have to escape slashes, which are used as path separators. So `r`n is a carriage return/line feed, equivalent to \r\n in most curly-brace languages. Next we write the string to a file by piping the string to Out-File. I set the encoding to ASCII since svnserve.exe doesn’t like Unicode encoding, which is the default. If you want to write Unicode text, you can out the output redirection operator (>). If you want to append to the file rather than overwrite, use the >> operator.

# Create a temporary working copy so we can commit initial setup in one go
Write-Host "Creating temporary working copy in $workingCopy"
New-Item -path $tempPath -name $tempDirName -type directory
svn checkout --non-interactive $newRepoSvnPath $workingCopy

Nothing interesting here. We’re just checking out a working copy into a temporary directory. Svn.exe is the main command line tool for Subversion that allows us to perform checkouts, updates, commits, branches, and a myriad of other operations. I typically use TortoiseSVN for performing these operations, but svn.exe is good when you need to script things. There are numerous ways I could have interacted with Subversion (Scott Hanselman has some other suggestions), but I wanted the one with the least dependencies. (i.e. You just need PowerShell and Subversion installed.)

Write-Host "Creating directories in working copy"
ForEach ($dirName in $dirNames) {
  $path = Join-Path $workingCopy $dirName
  svn mkdir $path
}

The only thing new here is the ForEach keyword, which does what you’d expect and iterates through the string[] of $dirNames.

# Commit changes to the repository
Write-Host "Committing changes"
svn commit $workingCopy --message "Initial repository setup"

Once again, we’re just executing svn.exe to commit our newly created directories to the repository.

# Perform cleanup
Write-Host "Cleaning up working copy"
Remove-Item -path $workingCopy -recurse -force

Lastly we clean up the mess of temporary files and directories that we created.

So that’s it. A simple PowerShell script that quickly creates a new Subversion repository for whichever pet project I’m working on. I honestly haven’t even scratched the surface of what PowerShell can do. Hopefully this gives you some ideas and a starting place for your own PowerShell scripts. Honesty the biggest benefit of PowerShell for .NET developers is that it lets us seamlessly leverage the .NET Framework. Not having another API to lug around in my head is a good thing and makes me more productive right away.

Feel free to modify the script to your heart’s content to suit your own environment. The full script can be found here.

UPDATE: Corrected the encoding of the svnserve.conf to use ASCII encoding.

Jeffrey Palermo is throwing another of his famous parties, this time at TechEd 2007 in Orlando, Florida. I attended a “Party with Palermo” at the Microsoft Global MVP Summit in Redmond this spring and it was a blast. A veritable who’s who in the Microsoft space. I got to meet a lot of cool people whom I’d only conversed with online. I hung out with Jeffrey and the rest of the agile crowd for the remainder of the week. Hence my association with the NHibernate Mafia by Richard Campbell on .NET Rocks. (Actually it’s the TDD Mafia, as Scott Bellware* later corrected him.) So this is a party that you don’t want to miss.

Website: http://partywith.palermo.cc
Date: June 3, 2007 from 7-11pm
Venue: Glo Lounge (http://www.gloloungeorlando.com)

* I would like to go on record stating that Scott Bellware has done a tremendous amount for the agile community, but I don’t understand his anti-Microsoft rants as of late, nor do I agree with them. Microsoft, like any company, has good and bad aspects in terms of products, direction, competitiveness, licensing, etc. It’s also a huge organization. Maybe Scott doesn’t like some aspects of Vista — which he is within his rights to complain about — but don’t paint the Developer Division (and others) with the same brush. There is no place for personal attacks or derogatory comments when trying to engage in a meaningful discussion on improving a product or a company. Just my three cents. (Inflation, don’t cha know.)

I was recently asked how to configure a site to redirect automatically from HTTP to HTTPS. By this I mean when the user types in http://server.example.com/app/page.aspx,* the browser will automatically redirect to https://server.example.com/app/page.aspx. You can do it through code, but with a little ingenuity, you can do it strictly through IIS configuration. Let’s walk through the setup…

Open IIS Manager and select properties for the website for which you want to require SSL. For TCP port, enter any unused port other than port 80 (the default HTTP port). For example, use 8888. For SSL port, enter the default SSL port, which is 443. Now go to the Directory Security tab… Secure communications… Edit… Set the “Require secure channel (SSL)” (required) and “Require 128-bit encryption” (optional, but recommended). Restart IIS. Browse to http://server.example.com:8888 now and you will get “The page must be viewed over a secure channel”. So far, so good.

Create a brand new IIS website by right-clicking… New… Web site… Click Next and give the website a name such as “Redirect to SSL”. Click Next… For TCP port, choose port 80, the default HTTP port. For path, point it to c:\inetpub\wwwroot. (It doesn’t really matter as we’ll be changing this in a minute.) Click Next… Give it Read permissions. Click Next… Finish… to create the website. Right-click, properties on the new website. Select the Home Directory tab. Change “The content for this resource should come from:” to “A redirection to a URL”. In the “Redirect to:” textbox, enter https://server.example.com. You can also optionally select “A permanent redirection for this resource”, which will cause bookmarks to update to the new URL. DO NOT, I repeat, DO NOT select “The exact URL entered above” or “A directory below URL entered”. Restart IIS. Now browse to http://server.example.com and you’ll be redirected to the SSL site. Note that the path portion of the URL is preserved and only the protocol and server are modified. So http://server.example.com/some/path/deep/within/my/app.aspx will redirect to https://server.example.com/some/path/deep/within/my/app.aspx just by applying the redirection steps noted above.

N.B. The redirect URL is sent back to the client. So if you type https://localhost as the redirect, the client browser will try to redirect to localhost on the client’s machine, which probably won’t exist. Same thing goes for NetBIOS names. (e.g. https://server rather than https://server.example.com)

* Little known fact. Example.com, example.net, and example.org are reserved top level DNS names as specified in RFC 2606, Section 3 and are intended for – surprise, surprise – examples. This allows authors to create bogus URLs in books, blog posts, and elsewhere that are guaranteed to go nowhere, which is generally the author’s intent when creating a bogus URL.

Ian Griffiths has an excellent post on why UAC exists and why we as developers shouldn’t turn it off in frustration. Like Ian, I ran Windows XP as a non-admin and UAC is welcome relief to the tedium of switching between accounts to configure things.* Now I’m not claiming that UAC is perfect. Notably Vista Backup doesn’t play nicely. Rather than giving you the option to elevate, you must log in as an admin. But honestly most programs don’t cause elevation prompts and the ones that do, they occur seldomly. I would really like to know what people are doing that cause so many elevation prompts. I run Visual Studio 2005 as a regular user on Vista and can develop quite happily. Sure there are some edge cases where VS doesn’t work such as browsing MSMQ within the server explorer. Honestly, how often do I do that? Seldom. When I need to, I can run a MMC console elevated rather than running all of VS elevated. So stop your griping and turn UAC back on.

* The Windows Firewall in XP is notoriously non-admin friendly as it blocks the program without providing the option to allow it through by providing admin credentials. That meant that if a new program was blocked, you would have to log into the admin account and manually add an exception to the list of programs. Now you just type in your admin credentials.

In this episode, we talk about Silverlight, Calgary Code Camp, Silverlight, GoDaddy refunds, Silverlight, Rhino Mocks, Silverlight, Entity Framework, Silverlight, NHibernate, Silverlight, and Halo 2. We finally wrap up the show by talking about Silverlight… You can download it from here.

Veni, vedi, codi… We came, we saw, we coded. The second Calgary Code Camp has come and gone. We had just over 100 attendees show up at our doors on Saturday. I would like to offer a big thanks to:

  • Our sponsors who donated $20,000 worth of prizes as well as enough money to rent the facilities and A/V equipment.
  • Our speakers for generously giving up their time and many for travelling long distances to share their knowledge with everyone.
  • Our organizing committee – Terry, Jean-Paul, Bil, and John – for helping to make this event possible.
  • Everyone who attended because without you, there would have been no code camp!

For a visual retrospective, check out Bil’s blog (and Flickr set) for some great photos. I would have to agree with Bil and John – their dual LCD projector setup to show a laptop debugging a game on the XBox 360 was just damn sexy.

Thanks again, everyone, and see you next year!