IISExpress in Application Server Mode: External + HTTPS

IIS Express can also be run from the command line in “Application Server Mode”. (REF: http://blogs.msdn.com/b/robert_mcmurray/archive/2012/07/03/working-with-the-different-iis-express-modes-and-https.aspx) This option is desirable if you need to run IIS outside of Visual Studio; however, due to a design limitation (flaw?) in the iisexpress.exe command-line, you can’t use the HTTPS protocol, only HTTP. I’ve found a reasonable workaround in PowerShell that works with both IIS 7.5 and 8. We take advantage of the \config option to load in our own customizations. We override the protocol to allow HTTPS and also broaden the port bindings (we want the site to be accessible by other systems for testing, not just localhost, so we drop “localhost” from the port’s bindingInformation).

NOTE: You may first need to make a one-time reservation of the port using “netsh http add urlacl url=… user=…” from an elevated command prompt. “netstat -ab” can help determine which ports are in use. (The “b” option requires an elevated command prompt but it gives you the process names.)

param (
    [string]$site_path = "%IIS_BIN%\AppServer\empty_wwwroot",
    [string]$site_port = "8080",   
    [string]$site_protocol = "http" # needs to be http OR https

$dirConfigRoot = "$env:USERPROFILE\My Documents\IISExpress\"
$dirConfigTemp = $dirConfigRoot + 'tmp-config\' + [system.guid]::newguid().ToString()
$dirAppRoot = "${env:ProgramFiles(x86)}\IIS Express\"
$srcCfg = "$dirAppRoot\AppServer\applicationhost.config"

# create temp dir with a copy of applicationhost.config
new-item -ItemType directory -Path "$dirConfigTemp"
copy $srcCfg $dirConfigTemp

# modify temp applicationhost.config to allow site protocol (http OR https)
# this fragment is based on http://robrich.org/archive/2012/07/06/iis-express-protocolhttps.aspx
$doc = New-Object System.Xml.XmlDocument;
$vdirNode = $doc.SelectSingleNode("//sites/site[@id='1']//virtualDirectory");
$vdirNode.physicalPath = "$site_path";
$bindNode = $doc.SelectSingleNode("//sites/site[@id='1']//binding");
$bindNode.protocol = "$site_protocol"; # override protocol
$bindNode.bindingInformation = "*:" + $site_port + ":"; # allow public by dropping localhost

# run
set-alias iisexpress "$dirAppRoot\iisexpress.exe"
iisexpress /config:$dirConfigTemp\applicationHost.config /siteid:1 /systray:true /trace:error

# clean up when exit
remove-item $dirConfigTemp -force -recurse

If you get this exception when you run the above script:
Failed to register URL “http://*:8080/” for site “Development Web Site” application “/”. Error description: Access is denied. (0x80070005)

Then you’ve need to make the one-time reservation of the port I mentioned earlier. Set this from an elevated command prompt:
netsh http add urlacl url=http://*:8080/ user=everyone

Of course, substitute whatever port you are trying to set for 8080; for example, 44300 for HTTPS:
netsh http add urlacl url=https://*:44300/ user=everyone

Leave a Comment