Ken Robertson's Blog

Ramblings of a .NET developer

Using NSIS to install to a website other than the Default Website.

One of my biggest gripes with the default setup package that Visual Studio produces is that for projects, it only supports installing applications to the Default Website.  I don't want all my applications on the default website, and I find it a pain to have to manually move them and then have the uninstaller not work.

Since we're ready for a new release of nGallery, we've been wanting a better setup package than the default, one that lets you chose which website, setup the SQL database (if you want to use it), and setup all write permissions.  We've started writing an installation script using the Nullsoft Scriptable Install System (free software, yay!).  There are tons of functions available on their website to do stuff like detect the .NET framework, detect IIS, and more.  There wasn't one for allowing you to pick which website to use, so I thought I'd write one myself.  The end result is an installer screen that will look like this:

[Installer screen sample]

This script outputs a small Windows Hosting Script that queries the IIS metabase to get the list of website's names and their physical path, then display the names in a drop down and allow you get the path of the one they picked.

First, the script to put in your .nsi:

Function GetWebsites
 ; Output the VBScript
 FileOpen $4 "$PLUGINSDIR\GetWebsites.vbs" w
 FileWrite $4 'Set IISOBJ = getObject("IIS://localhost/" & "w3svc")$\n'
 FileWrite $4 'Set objFSO = CreateObject("Scripting.FileSystemObject")$\n'
 FileWrite $4 'Set objTextFile = objFSO.OpenTextFile("$PLUGINSDIR\websites.ini", 8, True)$\n'
 FileWrite $4 'AllSites = ""$\n'
 FileWrite $4 'for each Web in IISOBJ$\n'
 FileWrite $4 'if (Web.Class = "IIsWebServer") then$\n'
 FileWrite $4 'Set IISWebSite = getObject("IIS://localhost/" & "w3svc" & "/" & Web.Name)$\n'
 FileWrite $4 'Set IISWebSiteRoot = getObject("IIS://localhost/" & "w3svc" & "/" & Web.Name & "/root")$\n'
 FileWrite $4 'AllSites = AllSites & "|" & IISWebSite.ServerComment$\n'
 FileWrite $4 'objTextFile.WriteLine("[" & IISWebSite.ServerComment & "]")$\n'
 FileWrite $4 'objTextFile.WriteLine("Path=" & IISWebSiteRoot.Path)$\n'
 FileWrite $4 'objTextFile.WriteLine("")$\n'
 FileWrite $4 'Set IISWebSiteRoot = nothing$\n'
 FileWrite $4 'Set IISWebSite = Nothing$\n'
 FileWrite $4 'end if$\n'
 FileWrite $4 'next$\n'
 FileWrite $4 'objTextFile.WriteLine("[Websites]")$\n'
 FileWrite $4 'objTextFile.WriteLine("AllSites=" & Right(AllSites, Len(AllSites)-1))$\n'
 FileWrite $4 'objTextFile.Close$\n'
 FileWrite $4 'Set objFSO = Nothing$\n'
 FileWrite $4 'Set objTextFile = Nothing$\n'
 FileWrite $4 'Set IISOBj = Nothing$\n'
 FileClose $4

 ; Execute the script
 nsExec::Exec /TIMEOUT=20000 '"$SYSDIR\cscript.exe" "$PLUGINSDIR\GetWebsites.vbs"'

 ; Read the value and put it in the page's INI
 ReadINIStr $0 "$PLUGINSDIR\websites.ini" "Websites" "AllSites"
 WriteINIStr "$PLUGINSDIR\pick_website.ini" "Field 2" "ListItems" $0
FunctionEnd

You also might want a function to include a function to change an installation path of /myApp/ to \myApp\:

;--------------------------------
; StrSlash
;    By dirtydingus
;
; Usage:
;   Push $filenamestring (e.g. 'c:\this\and\that\filename.htm')
;   Push "\"
;   Call StrSlash
;   Pop $R0
; Now $R0 contains 'c:/this/and/that/filename.htm'

Function StrSlash
  Exch $R3 ; $R3 = needle ("\" or "/")
  Exch
  Exch $R1 ; $R1 = String to replacement in (haystack)
  Push $R2 ; Replaced haystack
  Push $R4 ; $R4 = not $R3 ("/" or "\")
  Push $R6
  Push $R7 ; Scratch reg
  StrCpy $R2 ""
  StrLen $R6 $R1
  StrCpy $R4 "\"
  StrCmp $R3 "/" loop
  StrCpy $R4 "/" 
loop:
  StrCpy $R7 $R1 1
  StrCpy $R1 $R1 $R6 1
  StrCmp $R7 $R3 found
  StrCpy $R2 "$R2$R7"
  StrCmp $R1 "" done loop
found:
  StrCpy $R2 "$R2$R4"
  StrCmp $R1 "" done loop
done:
  StrCpy $R3 $R2
  Pop $R7
  Pop $R6
  Pop $R4
  Pop $R2
  Pop $R1
  Exch $R3
FunctionEnd

Next, you'll need to use the InstallOptions plug in to show the custom page.  I created a basic pick_website.ini which lets you pick the website and specify the installation directory.

[Settings]
NumFields=4

[Field 1]
Type=label
Text=Please select which Web Site to set the application to use.
Left=0
Right=-1
Top=0
Bottom=10

[Field 2]
Type=Droplist
Text=droplist
ListItems=
Left=25
Right=150
Top=10
Bottom=22


[Field 3]
Type=label
Text=Path for the application:
Left=0
Right=-1
Top=30
Bottom=40

[Field 4]
Type=text
Text=webPath
State=/myApp
Left=25
Right=150
Top=40
Bottom=52

Next, have the .nsi display the custom page and call our little function to get the websites.  Along with my list of pages, I have a “Page custom PickWebsite”, which tells it to go to a page called PickWebsite instead of having them pick an installation directory (commented out the MUI_PAGE_DIRECTORY page).  You'll also need to do the usual calls for InstallOptions pages to reserve the files and extract the INI on runtime.

Now our custom page function looks like this:

Function PickWebsite
 Call GetWebsites
 !insertmacro MUI_HEADER_TEXT "Webserver Configuration" "Choose the website and path that your installation will reside at."
 !insertmacro MUI_INSTALLOPTIONS_DISPLAY "pick_website.ini"
FunctionEnd

And then in the installer section for your web application, use the following to set the $INSTDIR properly:

 ; Get the website path and the app path
 ReadINIStr $0 "$PLUGINSDIR\pick_website.ini" "Field 2" "State"
 ReadINIStr $1 "$PLUGINSDIR\websites.ini" "$0" "Path"
 ReadINIStr $2 "$PLUGINSDIR\pick_website.ini" "Field 4" "State"

 ; First, convert the / from the path to \, then setup the installation path
 Push $2
 Push "/"
 Call StrSlash
 Pop $R0
 StrCpy $INSTDIR "$1$R0"
 SetOutPath "$INSTDIR"

Coming next time, I'll include a function to mark the folder as an application, which can be done with a rendition of the sample to create a virtual directory.

To get a complete sample script, feel free to fetch my sample.  The sample includes the functions to check for the .NET Framework and if the user is has administrator priviledges.  I need to update it to check for IIS and to setup the folder as an application.  Will get to that this evening, hopefully.

Posted: Apr 01 2004, 05:05 PM by qgyen | with 10 comment(s)
Filed under: ,

Comments

Adriana Guerrero said:

Hi Ken,

I'm kind of new in making installers and that sort of thing. So I was wondering if you would be so kind to send me a copy of you complete sample .zip file because i guess the link you posted is broken.

I would be so glad and grateful to you if you could do so.

My email is a_guerrero@hotmail.com


Thanks for all your help and kindness.

Best regards,

Adriana
# July 21, 2004 9:10 PM

Jeffrey Tucker said:

I'm very interested in your nsis script.  I'm new to writing custom pages and I'd like to see how your sample hangs together because we are trying the same technology in one of our dev efforts.  Would you be able to send it my way?  (link above is broken).

Thanks,

jtucker@inflexxion.com

# December 5, 2007 1:02 PM

Dana said:

Could you send me a copy of your sample script? The link is broken in the article.

Thanks,

laminateddog@live.com

# December 6, 2007 8:16 AM

Erik said:

> Could you send me a copy of your sample script? The link is broken in the article.

Same here.

websample@erik.prutser.cx

# February 13, 2008 1:51 AM

Jirapat said:

Cound you send me a copy of your sample script?

I'm very interested in your nsis script

Thanks

oad_333@hotmail.com

# March 20, 2008 5:46 AM

Rosa said:

Cound you send me a copy of your sample script?

# July 21, 2008 10:23 AM

Jared said:

Seems like you could have just created your web site, then used IISCfg.vbs to back it up.

Then add the backup file to your installer and use IISCfg.vbs to install it.

ExecWait '$WINDIR\System32\cscript.exe $WINDIR\System32\IIsCnfg.vbs /import /f "IISConfigFile.xml" /sp /LM/W3SVC/1/Root/YourWebSite /dp /LM/W3SVC/1/Root/YourWebSite'

Well, you get the picture.

# September 17, 2008 11:37 PM

Using NSIS to Install an ASP.NET Web Application to IIS | Meroal said:

Pingback from  Using NSIS to Install an ASP.NET Web Application to IIS | Meroal

# December 22, 2008 8:19 AM

Jimbo said:

I would be like all the rest and ask to email me a copy of your script, but rather can you fix the link to it? Thanks :)

# September 30, 2009 4:36 AM

FlowerBeauty said:

Добрый день. Прошу у Вас помощи. У меня сложилась очень неприятная ситуация. Дело в том, что мой блог с недавнего времени перестал показываться в поиске Yandex'a. Сам блог проиндексирован, то есть если посмотреть наличие конкретной страницы в результатах поиска, то она там имеется. А вот по поисковым запросам, да и по точным текстовым вхождениям сайт не находится. При чём его нет не только в 100, но даже в тысяче показов. Ума не приложу, что произошло. Сайт был доступен, поблем на хостинге не было. А обнаружил это - по счётчику ЛивИнтернет, который вдруг стал показывать гораздо меньшее количество посещений.

Кстати, юзеры с Гугла и Рамблера идут в прежних объёмах.

# November 29, 2009 8:22 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)