Hello all,
I've been struggling with a lot of "localhost" root-level development installations later and had trouble switching from one to another in an easy way. I thought of a solution involving appcmd.exe and thought it would be good to share it with others. Reposting from my blog:
http://dnnuke.blogspot.com/2010/11/ho...
The reason I'm reposting is that I'd like feedback and/or alternative suggestions.
Warning: This is for advanced users only.
The situation
- You've got a development machine which has more than one DNN sites that you are currently working on.
- You're using host headers on those sites to have multiple root-level DNN sites. (And you know the terms "host header" and "binding")
- You are using IIS7 or higher with Windows 7 or Windows 2008. (I suspect it may work on Vista too, but who's still got Vista? :) ).
(Don't continue reading if the above don't match your case. One of the most common reasons for the above scenario could be that there are root-level urls inside your DNN site, generated by custom modules or just hard-coded into skins / modules, so you have to make your development PC believe that this is a root-level site and not a virtual directory of your default web site. Or, even worse, if you're working on a copy of a site that's already online and there are links and other stuff pointing to the WHOLE domain, you may have to alter your hosts file to make your PC believe that your local site is running on the exact same domain. If you're dealing with DNN a lot, you've probably seen that we don't live in a perfect world and such cases do exist.)
The problem
You need to configure some modules on your installations, but the modules you have installed can run without limits only on "localhost". Furthermore, some modules, (for example, IndooGrid) need you to buy a licence if you run them ANYWHERE else than localhost - even if it's a test / development machine. But you don't want to buy additional licences since you can do your development work on localhost.
What you need
You need a way to quickly switch between what you see when you type "localhost" on your PC's browser, so that you can work on the site of your choice each time.
Of course, you can do it by altering your sites' host headers in IIS but that wouldn't be quick. And, I won't say a word about using different virtual machines, each with one localhost site - I've seen it happen. :)
The solution
Let's suppose I've got two sites, let's say Site1 and Site2. These listen to their respective host headers, let's say site1.mypc.local and site2.mypc.local. You have configured your Site1 to listen to "localhost" too. Currently, when you type "localhost" on your browser you see Site1.
Now, you either have configured your IIS to have an extra host header (*:80) for Site 1 or you have changed the location of your "default web site" to point to Site1's folder on your hard disk.
Do the following:
1. STOP your default web site (if that's what you're using to do the trick).
2. Go to all the sites that you need to implement the "switching" on, and add a portal alias for localhost so that they can respond to the call (if there is not one already). If you do so, an IISRESET would be good too, in order to avoid the dreaded "redirect loop" error that can happen from time to time.
3. Create a batch file with the following and save it as changehost.bat (or any name you choose):
@echo off
if "%1" == "site1" goto site1
if "%1" == "site2" goto site2
if "%1" == "" goto error
:site1
%windir%\System32\inetsrv\appcmd set site /site.name:site2 /-bindings.[protocol='http',bindingInformation='*:80:']
%windir%\System32\inetsrv\appcmd set site /site.name:site1 /+bindings.[protocol='http',bindingInformation='*:80:']
goto end
:site2
%windir%\System32\inetsrv\appcmd set site /site.name:site1 /-bindings.[protocol='http',bindingInformation='*:80:']
%windir%\System32\inetsrv\appcmd set site /site.name:site2 /+bindings.[protocol='http',bindingInformation='*:80:']
goto end
:error
@echo You have to provide a parameter!
:end
Let's explain what this batch file does. You call it like this (make sure you have administrator rights):
changehost site2
And you expect to see your "site2" responding to localhost instead of "site1".
What the batch file does is go to the matching section of the batch code, following the IFs. When it gets there, it does two things:
First, it uses appcmd.exe (an utility located in your windows directory\system32\inetsrv folder, which allows you to access several IIS properties from the command line) to add a binding to localhost (*:80) to the site you need and REMOVE this binding from any other of your sites that possibly has it. Essentially, it does what you would do by hand - go to iis, add a binding to the site of your choice, remove the binding from the previous site since you are not allowed to have two sites with the same host header.
The result is that you will always have one and only one site bound to localhost, and that you can change what site this is by just executing your batch file.
Some things to have in mind:
The parameter's values can be anything you want, as long as there is a section inside the batch file you can GOTO if you match a parameter value. I've used the same names as the names of the sites in order to have some consistency, but this isn't needed. "Foo" and "Poo" would do the same job, as long as there was a "Foo" section for site1 and a "poo" section for site2.
The /site.name switch needs the actual site's name as it is declared in IIS.
You must FIRST remove any possible localhost bindings (/-bindings switch) and add the localhost binding (*:80) last (/+bindings switch), otherwise you'll get an error and the binding won't be added because it will exist on another site.
If a site does not have a localhost binding, you'll get a message that it can't be found, like this one:
ERROR ( message:Cannot find requested collection element. )
Don't be alarmed, it's normal. Appcmd just tried to remove a non-existent binding, no problem.
If you try to run this script twice for the same site, you'll also get an error like this:
Cannot add duplicate collection entry of type 'binding' with combined key attributes 'protocol,bindingInformation' respectively set to 'http, *:80:'. )
This means that you tried to add a binding to *:80 to the site that already had it. That's perfectly normal, too, nothing to worry about, no changes will be made.
The example is for two sites, if you have three you'll have to adjust the number of sections, your IF statements and your appcmd calls accordingly. Remember, we're doing a simple thing: Attempting to remove localhost bindings from sites that may have it (only one will) and add a localhost binding to the site we want.
I hope this helps a bit. It worked for me, if anyone tries it, please let me know if you have succeeded.
Standard disclaimer / warning: Even if you are an advanced user, please use this information at your own risk. It's easy to mess things up (actually, the only thing you'll mess up is your bindings - you won't lose any data but it's enough to make your development sites unaccessible if you don't know what you're doing). I cannot be held responsible if any of the above information proves misleading or incorrect.
Happy localhosting! :)