Rename Applications and Virtual Directories in IIS7

Have you ever wondered why the box to change the name or “Alias” on an application or virtual directory is greyed out (see screenshot below)? I found a way to change the name without recreating all your settings. It uses the built in administration commands in IIS7, called appcmd.

Renaming Applications In IIS7

  1. Open a command prompt to see all of your applications.

    C:> %systemroot%\system32\inetsrv\appcmd list app
    	APP "Default Web Site/OldApplicationName"
    	APP "Default Web Site/AnotherApplication"
  2. Run a command like this to change your “OldApplicationName” path to “NewApplicationName”. Now you can use http://localhost/newapplicationname

    C:> %systemroot%\system32\inetsrv\appcmd set app "Default Web Site/OldApplicationName" -path:/NewApplicationName
    	APP object "Default Web Site/OldApplicationName" changed

Renaming Virtual Directories In IIS7

  1. Open a command prompt to see all of your virtual directories.

    C:> %systemroot%\system32\inetsrv\appcmd list appcmd
    	VDIR "Default Web Site/OldApplicationName/Images" (physicalPath:\\server\images)
    	VDIR "Default Web Site/OldApplicationName/Data/Config" (physicalPath:\\server\config)

    We want to rename /Images to /Images2 and /Data/Config to /Data/Config2. Here are the example commands:

    C:> %systemroot%\system32\inetsrv\appcmd set vdir "Default Web Site/OldApplicationName/Images" -path:/Images2
    	VDIR object "Default Web Site/OldApplicationName/Images" changed
    C:> %systemroot%\system32\inetsrv\appcmd set vdir "Default Web Site/OldApplicationName/Data/Config" -path:/Data/Config2
    	VDIR object "Default Web Site/OldApplicationName/Data/Config" changed

Changing .Net Framework version on a website in IIS without restarting the W3SVC process

If you are changing the .Net Framework version of a website hosted in IIS  you will most likely receive a message that looks like the following

The problem is that if you restart the W3SVC, all the application pools will be recycled.  In my case we are hosting multiple versions of the site in IIS (Live, Staging, etc.).  I didn’t want to recycle every application pool if I didn’t need to.  Plus, if you are storing state information in the worker process it will be lost when the application pool gets recycled.

The dialog points to a command you can run in order to keep the W3SVC process from restarting.  The command is pretty straight forward except for the “IIS-Virtual-Path” part.  The “IIS-Virtual-Path” is the path IIS uses in order to differentiate between sites.  This path is in the form “W3SVC/Site ID/root”.  To find the Site ID, just click on the “Web Sites” folder in IIS and you should see a table in the right column that looks similar to this:



Once you find the Site ID, open up a command prompt window and navigate to the folder of the framework version you are wanting to change to.  The framework version folders are usually found in c:/Windows/Microsoft.Net/Framework/.  Once you are inside the folder  you can just run the following command for a site with the ID 1957079098:

aspnet_regiis.exe -norestart -s W3SVC/1957079098/root/

After you update the framework version, you will still need to restart the application pool for the website that you are changing though.

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.


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

@ECHO off

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%
if not exist %psexec% (
	echo ERROR: Could Not Find PSEXEC at path: %psexec%
if not exist %publish% (
	echo ERROR: Could Not Find PUBLISH at path: %publish%

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

if ErrorLevel 1 (
	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.




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

@ECHO off

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

ECHO =======================================================
ECHO Build Script.
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 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%
IF NOT EXIST %stagingdir% (
	ECHO Could not find path %stagingdir% on %COMPUTERNAME%

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

ECHO Pointing website at the StagingWeb folder...

CALL %appcmd_change%
If Errorlevel 1 GOTO IISError

ECHO New site is live

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

GOTO 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 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 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 Great job!  Now published on %COMPUTERNAME%.  Don't forget to set the other live web servers!

	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.

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

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