Controlling IIS7 With Custom Build Script

Handling IIS after doing a publish was always a bit of a pain.

We use Web Deployment Projects which automates much of the build process, such as minifying CSS and JavaScript and copying new files to the web servers. But we still had to deal with the pain of manually controlling IIS after a publish. This actually required remoting into the servers, and changing the home directories of the site in IIS.

This was always a small headache, but if we only published once a month or so, it wasn’t a big deal. A few months ago, we started doing weekly releases in Foliotek, our assessment portfolio tool to take care of any problems that customers were having on the live site.

Here is what we used to do:

  1. Build the WebDeploy project in ‘release’ mode. This will copy files to a StagingWeb folder on both servers.
  2. Load up the staging website (which is hosted on Server1 and pointing directly at the StagingWeb folder). Verify any fixes.
  3. (Here is the annoying part): Remote into both servers, and open IIS Manager. At approximately the same time, switch the home folder over to StagingWeb and make sure the site is still up. Back up the Web folder, delete it and copy StagingWeb then rename the copy to Web. Point IIS back to the Web folder.

We have extra steps in part 3 to prevent any downtime, but it is tedius and prone to error, timing problems, etc. And it is not something to look forward to at the start of the week. Why should we do something manually that should be easy to automate?

Here is what we do now:

  1. Build the WebDeploy project in ‘release’ mode. This will copy files to a StagingWeb folder on both servers.
  2. Load up the staging website (which is hosted on Server1 and pointing directly at the StagingWeb folder). Verify any fixes.
  3. Run a batch script to handle backups and switching IIS

The solution uses the PsExec utility which allows remote execution of batch scripts, and the AppCmd.exe command line tool for managing IIS7.

It is just a couple of batch scripts. You can call them on the command line, or through MSBuild. We actually have a Windows Forms project that gets run on the AfterBuild event of our Web Deployment project. This executable has links to all of the sites, shortcuts to remote desktop, status of the servers, and a link to the publish script.

Run it using this command:

publish_server_connector.bat \\Server1
publish_server_connector.bat \\Server2

The source code is below. It would probably need to be modified for different environments, and I’m sure there are better ways to handle this problem, at least this is simple to read and modify.

publish_server_connection.bat

This file basically just calls PSExec on the given server passing up the myproject_publish.bat script.

@ECHO off
SETLOCAL 

REM Publish Connection Script
REM This will call the publish.bat script on the server specified in the first argument
REM Usage: publish_server_connection.bat [servername]

SET server="%1"
SET server_dir="%1\c$\inetpub\wwwroot\MyProject"
SET psexec="%~dp0psexec.exe"
SET publish="%~dp0myproject_publish.bat"
SET usage=USAGE: publish_server_connection.bat [servername]

if not exist %server_dir% (
	ECHO ERROR: The path %server_dir% does not exist!  Exiting..
	ECHO %usage%
	GOTO End
)
if not exist %psexec% (
	echo ERROR: Could Not Find PSEXEC at path: %psexec%
	GOTO End
)
if not exist %publish% (
	echo ERROR: Could Not Find PUBLISH at path: %publish%
	GOTO End
)

ECHO Starting publish on %server%.
%psexec% %server% -c -v %publish%

if ErrorLevel 1 (
	ECHO.
	ECHO ERROR: Having problems starting PSExec.  Please verify access to the server, and retry.
	ECHO If the problem persists, then you will need to manually publish.
	ECHO.
)

:End

ENDLOCAL

myproject_publish.bat

This file will be copied to the servers using PSExec, and will be executed locally in the server environment.

@ECHO off
SETLOCAL 

REM Publish Script
REM This is called from development machines, using the PSExec Command.

CLS
ECHO.
ECHO =======================================================
ECHO Build Script.
ECHO %COMPUTERNAME%
ECHO This script will:
ECHO    1. Point the IIS entry for the LIVE website to StagingWeb
ECHO    2. Backup the original Web folder
ECHO    3. Copy StagingWeb over the original Web folder
ECHO    4. Point the IIS entry to the new Web folder
ECHO =======================================================
Echo.
ECHO Make sure you go to the staging site and confirm it is ready to go live.

For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (SET startdate=%%c-%%a-%%b)
For /f "tokens=1-2 delims=/:" %%a in ("%TIME%") do (SET starttime=%%a%%b)

SET livedir="C:\inetpub\wwwroot\MyProject\Web"
SET stagingdir="C:\inetpub\wwwroot\MyProject\StagingWeb"
SET livedir_revert="C:\inetpub\wwwroot\MyProject\WebRevert"
SET backupdir="C:\inetpub\wwwroot\MyProject\backups\%startdate%_%starttime%"
SET appcmd="C:\Windows\System32\inetsrv\appcmd.exe"
SET appcmd_change=%appcmd% set vdir "MyProject/" -physicalPath:%stagingdir%
SET appcmd_revert=%appcmd% set vdir "MyProject/" -physicalPath:%livedir%

IF NOT EXIST %livedir% (
	ECHO Could not find path %livedir% on %COMPUTERNAME%
	GOTO End
)
IF NOT EXIST %stagingdir% (
	ECHO Could not find path %stagingdir% on %COMPUTERNAME%
	GOTO End
)

Choice /M "Are you ready to start?"
If Errorlevel 2 GOTO End REM Only proceed if ready, exit if user types "N"

ECHO.
ECHO Pointing website at the StagingWeb folder...

CALL %appcmd_change%
If Errorlevel 1 GOTO IISError

ECHO New site is live
ECHO.

Choice /M "Does the site still work?  If NO, IIS will be reverted."
If Errorlevel 2 GOTO Revert

GOTO Backup


:Backup
	ECHO Starting Web Backup to archives folder, and WebRevert in case you need to revert changes.
	if exist %livedir_revert% (
		rmdir %livedir_revert% /s /q
	)
	xcopy %livedir% %backupdir%\ /E /Y /q
	xcopy %livedir% %livedir_revert%\ /E /Y /q

	ECHO.
	ECHO Removing old Web folder and copying StagingWeb to Web.
	rmdir %livedir% /s /q
	xcopy %stagingdir% %livedir%\ /E /Y /q
	
	If Errorlevel 1 GOTO BackupError
	
	ECHO.
	ECHO Backup path is: %backupdir%
	ECHO Backup Success!  Resetting IIS to the Web/ folder...
	
	REM Reset IIS to Web/ (which is copied from StagingWeb/)
	CALL %appcmd_revert%
	If Errorlevel 1 GOTO IISError
	
	ECHO.
	ECHO Great job!  Now published on %COMPUTERNAME%.  Don't forget to set the other live web servers!
	GOTO End

:BackupError
	ECHO IMPORTANT: There was an error backing up the files.
	ECHO This could be caused by lack of permissions when trying to remove the old Web directory, if IIS has a lock on the folder.
	ECHO Don't worry, the live site should still be ok, but you will need to manually remote into the server to sort out the backups.
	GOTO End

:IISError
	ECHO IMPORTANT: There was an error switching IIS over (error code = %ErrorLevel%)
	ECHO Please manually remote into the server to sort things out.
	GOTO End

:Revert
	echo Resetting to the original Web folder...
	CALL %appcmd_revert%
	If Errorlevel 1 GOTO IISError
	GOTO End
	
:End

ENDLOCAL
Advertisements

Simple Usability Testing with TryMyUI.com

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

Any software developer that is concerned with making great software should be testing their interfaces on their users (or people similar to their users). Its easy to convince yourself you’ve built a great UI if you only see people on the team using it. People on the team have intimate knowledge of how the system is supposed to work, and so they nearly always succeed.

The real test comes when you watch someone who has never seen your system before attempt to perform some vague tasks you have set out for them to do.  These types of usability tests can not only point out the failures of your system to match what typical users expect – but watching these users struggle with stuff you wrote can be a strong motivator to improve things.  For that reason, it’s important to do usability tests as often as possible, and let as many people watch as possible.

At Lanit, we’ve attempted to do usability tests a number of ways:

We’ve done full scale tests that record mouse tracking and video in addition to audio. These take a ton of time to set up, to edit/summarize the results, and to share. And, it doesn’t seem that the mouse tracking or video added much to what the user was saying (assuming the moderator was prompting for their thoughts often). This time investment caused us to do them at most once or twice a year.

We’ve tried doing simpler screen-cast and voice recordings at a local university. This was an improvement – but it still took time to schedule a room, and we still need to bring back videos to the office to share or spend time summarizing/editing them. It also eat up a half day for two people to find participants and set up the tests. And, it was a bit awkward to approach people to ask them to let you record them testing your software.  Usually, we managed to do these every few months.

We’ve also tried bringing users in to our office – so that we can easily share the screen and voice live, and have an immediate discussion afterwords (similar to what Steve Krug suggests here: http://network.businessofsoftware.org/video/steve-krug-on-the-least-you). This was an improvement, but still required a time investment in finding willing users to come to us.  We only tried this once – but the effort to advertise etc. felt like we would still only do a test at most once a month.

Finally, we decided to give one of the new services that have recently popped up a try. There are many of these services that do some form of usability testing for you – but we narrowed in down to usertesting.com and trymyui.com because they seemed to best emulate what we were doing live  (the only real difference is that users are screened/trained by the site to speak what they are thinking, instead of requiring a live moderator to prompt them). I chose trymyui mainly because I liked the results of my first (free) test, and it was slightly cheaper ($25/user/test instead of $39). All we had to do was provide the script of tasks they were to accomplish (took all of maybe 10 or 15 minutes to create), request testers, and usually within an hour or two we had a great recording of the users screen and voice. I had one experience where a video didn’t arrive for about 2 days, but their support was very helpful and indicated that they pre-screened the results to ensure the testers tried the tasks, etc (a bonus, as you are basically guaranteed to get a good video for your $25).

We were hoping that going the online service route would save us a bunch of time – and it did – but an unexpected benefit was that the short turnaround allowed us to do a kind of A/B testing.  Before when we did live tests – we’d come away with 10 or so items from across 3-5 tests in our session we’d want to improve, and we’d put them in a list to take care of some time in the future.  Then, we’d have to wait until the next time to see if we made a significant improvement and what the next set of problems were.

With trymyui, we could often develop a change to improve the experience and test that change the same day.  This created an even more motivating experience to build a great UI – because you could often see where the next user did better because  of the last test.  In the end, we made several improvements over a week that would have taken us months to do before.  And, it was so effortless to set up and so easy to see the benefits that I know we will continue to use this site to test our UIs on a regular basis.