Skip to content
⌘ NSIS Forum Archive

How to config IIS Server's property thorugh NSIS?

27 posts

alan_lin#

How to config IIS Server's property thorugh NSIS?

I have a request which is IIS Server configured by NSIS.
Like to add virtual directory...
Can I to do that?
Please someone of Masters tell me.
Thanks.
alan_lin#
I have read NSIS IIS Plugin and got a question.
What mean is "You MUST Pop the message"? and purpose is?
Becasue I am a newer.
Thanks
Highcoder#
This plugin push it´s success or fail messages to nsis stack and you have to pop it (out).
Have a look to the example script provided with the plugin.
The best way to learn how to use it.
alan_lin#
OK,I see that.
The return flag need to POP out.
I am confusing between pop messagebox and pop what.
Thank you very much.
Highcoder#
pop it into a variable and do what you want with it. pop $0 will pop the last stack entry into the variable $0.

Now you can show $0 in MsgBox or show it in detailprint or feed an "if"-condition (success=go on, fail=abort) or ignore it simply.

The Plugin author just says "You MUST pop it". But it´s on you what you want to do with it.

Here is an explanation of the NSIS Stack.
dcbrewster#
Good luck

I have never been able to get this plug_in to work.
It aborts on every command.
No response from developer for over a year.
navastha#
NsisIIS plugin is not working for IIS 8 (windows 8+). Is there any other plugins that support IIS 8 ?
themanisagod#
I'm fairly new at using NSIS so I'm still learning a lot.

I'm using the November 2016 release of the NsisIIS plugin. I can get this plugin to work to list my websites on Windows 10 and Server 2016, but my problem is that it lists all the websites in my dropdown as a single selection value.

It combines the index number and text name of the first website, then lists the index number and text name of the second website all on one line. I need it to only display the name of each website, and to have each website name as separate selection line in the dropdown.

Example portion of my NSI:

Function GetWebsites
NsisIIS::ListWebSites
Pop $0
WriteINIStr "$PLUGINSDIR\pick_website.ini" "Field 2" "ListItems" $1
FunctionEnd

Function PickWebsite
Call GetWebsites
!insertmacro MUI_HEADER_TEXT "Webserver Configuration" "Choose the website and web application installation path."
!insertmacro MUI_INSTALLOPTIONS_DISPLAY "pick_website.ini"
!insertmacro MUI_INSTALLOPTIONS_READ $SITENAME "pick_website.ini" "Field 2" "State"
!insertmacro MUI_INSTALLOPTIONS_READ $APPNAME "pick_website.ini" "Field 4" "State"
FunctionEnd



This then displays "1: Default Web Site,2: www2" all on one line. How do I get this to show as:

Default Web Site
www2
Anders#
You probably need to write a little loop that replaces "," in $1 with whatever InstallOptions uses as a separator.
themanisagod#
The index number, colon, and the comma between the values have to go away. These are unusable in any scripting.

I did read the InstallOptions page but couldn't find anything that indicated I could use comma separated values for a list. It appears that the static default is using pipes to separate values. I'm also not sure how to loop through anything, especially to get multiple items from the stack to appear in my drop down. There's just not enough actual examples of the push/pop stuff to help make it understandable to me.

The NsisIIS plugin returns undesirable values, where the index number and colon have to be filtered out of the returned values to make it useful. What a bunch of extra unnecessary work!

I have the below function working using the nsExec plugin but it only returns the single value "Default Web Site", even if there are multiple websites on the IIS machine. I've been trying to find out some kind of way to return these multiple values into multiple lines but all the help pages I've read don't seem to directly touch on this kind of approach.


Function GetWebsites
nsExec::ExecToStack '"$SYSDIR\inetsrv\appcmd.exe" list site /text:name'
Pop $0
Pop $R2
; Reads the value and put it in the page's INI, will only grab one value until a better looping solution is found
WriteINIStr "$PLUGINSDIR\pick_website.ini" "Field 2" "ListItems" $R2
FunctionEnd
JasonFriday13#edited
It's fairly straight forward to create a loop:

Function addSites
start:
  nsExec::ExecToStack '"$SYSDIR\inetsrv\appcmd.exe" list site /text:name'
  Pop $0
  Pop $R2
  ; add code to add the returned string ($R2) into the list.
  StrCmp $0 "error" end
  StrCmp $0 "timeout" end
  IntCmp $0 0 start
end:
FunctionEnd 
Push and Pop are easy to understand. Imagine you have some books on a desk. The books represent the data and the desk represents the nsis script. When you Push some data onto the stack, you are copying a book from the desk onto a shelf. The shelf represents the stack. Using Pop $0 means taking the book from the shelf and replacing the one on the desk (replacing the data in $0). The NSIS plugins also have access to the stack/shelf, lets call it a bench. So using Push in the plugin copies a book from the bench onto the shelf. When the plugin returns from it's call, using Pop $0 takes off the book that was just placed on the shelf and replaces the one on the desk (replacing the data in $0). This is how the script communicates with the plugin.

An example of how this works can be illustrated with reversing the order of some data:
Name "reverse"
OutFile "reverse.exe"
RequestExecutionLevel user
ShowInstDetails show
page instfiles
Section
  StrCpy $0 "Line 1"
  StrCpy $1 "Line 2"
  StrCpy $2 "Line 3"
  DetailPrint "$$0=|$0|, $$1=|$1|, $$2=|$2|, in order"
  Push $0
  Push $1
  Push $2
  Pop $0 ; Line 3
  Pop $1 ; Line 2
  Pop $2 ; Line 1
  DetailPrint "$$0=|$0|, $$1=|$1|, $$2=|$2|, reversed"
SectionEnd 
jpderuiter#
You can use the Explode function to split the websites and get rid if the id:
StrCpy $R0 0
${Explode} $R1 "," "1: Default Web Site,2: www2"
${For} $R0 1 $R1
  Pop $R2
  ${Explode} $R3 ":" "$R2"
  Pop $R3 # ID
  Pop $R3 # Website
  ${Unless} $R0 = 0
    StrCpy $R4 "$R4|"
  ${EndIf}
  StrCpy $R4 "$R4$R3"
${Next}
WriteINIStr "$PLUGINSDIR\pick_website.ini" "Field 2" "ListItems" $R4 
Note: I did not test this code.
themanisagod#
JasonFriday13 and jpderuiter, thank you for your responses.

JasonFriday13: It seems like your example does not include writing the selected variable into the INI field after your looping example. Also, based on what you mentioned, would the Pop $0 and Pop $R2 both be necessary, or just use Pop $0 if it is looping through? I tried a few iterations based on your suggestion but couldn't get it to work. It looked like a simple approach but I'm missing something.

jpderuiter: I was able to get it to work using your approach with the Explode function. There was the include and the macro that I had to add to my .nsi, but it was able to parse through the string and provide dynamic list selections. Here's what I put together.

Function GetWebsites
NsisIIS::ListWebSites
Pop $0
StrCpy $R0 $1
${Explode} $R1 "," $R0
${For} $R0 1 $R1
Pop $R2
${Explode} $R3 ":" "$R2"
Pop $R3 # ID
Pop $R3 # Website
${Unless} $R0 = 0
StrCpy $R4 "$R4|"
${EndIf}
StrCpy $R4 "$R4$R3"
${Next}
WriteINIStr "$PLUGINSDIR\pick_website.ini" "Field 2" "ListItems" $R4
FunctionEnd
themanisagod#
I may have spoke too soon. The solution proposed using the NsisIIS plugin with jpderuiter's Explode example works great to list all the available websites in IIS on a Windows 10 machine, but it only shows a single index value when it is ran on a Server 2012 R2 or Server 2016 machine. I'm guessing this is a quirk with the NsisIIS plugin on these operating systems.

It seems like trying to write the appcmd.exe output to the stack with a loop as suggested by JasonFriday13 may be the more reliable option as the results will be relative to the appcmd.exe running on each operating system. Still not sure the best way to implement JasonFriday13's suggestion though....
JasonFriday13#
The kind of loop that you need depends on the data you can get back from the 'appcmd.exe' command.

If you can get a list back in $R2, then you only need to loop through the data in $R2, processing it into a string that installoptions supports. Once the single string is done, write it into the .ini file with a single WriteINIStr instruction. $0 is the plugins return value, if it shows 'error' then the plugin command failed.

You will have to look into the commands that 'appcmd.exe' supports. If it supports getting the total number of sites, and returning a site based on its internal index, then you could loop each index to return that site and process it into a single string that installoptions supports. Once the single string is done, write it into the .ini file with a single WriteINIStr instruction.

I can't really help much further than this because appcmd doesn't work on my machine (Win10, the inetsrv folder is empty).
nsExec::ExecToStack '"$SYSDIR\inetsrv\appcmd.exe" list site /text:name'
Pop $0 ; $0 contains 'error', so the command failed. 
themanisagod#
I appreciate you trying to help. I believe you do not have Internet Information Services installed. You can enable this on your Windows 10 machine (if Pro or Enterprise).

Control Panel --> Programs and Features --> Turn Windows features on or off --> Check the box for "Internet Information Services"
JasonFriday13#edited
I know I don't have it installed. I can't justify setting up a VM just to write a short piece of code, so I'm going to reference this instead: https://www.iis.net/learn/get-starte...with-appcmdexe. Yeah, that's what I'll use to determine the type of data I can get from it, then I can write the loop (hint hint).

[edit]
I can get a list back, so I can use '%systemroot%\system32\inetsrv\APPCMD list sites' to return a list. So I'll be going with option 1 that I outlined above.

The string processing code will be a real joy to write. I'll probably use StrStr to skip to the parts I need and cut everything else out.

How do you want your string formatted (what do you want each list entry to look like)?
[/edit]
themanisagod#
Awesome!

I was trying to get the text string name of each website to show in my drop list selection. Ideally, this would be like the following (without the double quotes).

"Default Web Site"
"MyAwesomeWebSite"
"www3"
"Another Site"
JasonFriday13#
Try this and see if it works. Ideally the functions would be moved to an external .nsh file and use !include to use it.
themanisagod#
I compiled this and the results are in the screenshot. The test machine has 3 websites listed in IIS, but the drop down list was entirely blank.

JasonFriday13#
Put a message box in before AddEntries that displays the contents of $R0 (MessageBox MB_OK "$R0"). We'll see what the actual return string is.
themanisagod#
Dang it, it was just permissions. I changed the "RequestExecutionLevel" from user to admin and it worked exactly as needed.

I tested this successfully on Windows 7, Windows 10, Windows Server 2008 R2, Windows Server 2012 R2, and Windows Server 2016.

Thank you for all of your help!!!!!!!
JasonFriday13#
Cool. I use the 'user' level so that I don't have to keep clicking "Yes" on the dialog that pops up when I'm testing code.

RequestExecutionLevel admin is the default in NSIS 3, I don't think it is admin in NSIS 2.xx.
Anders#
Originally Posted by JasonFriday13 View Post

RequestExecutionLevel admin is the default in NSIS 3, I don't think it is admin in NSIS 2.xx.
In 2.xx it is not set at all by default but that effectively ends up as admin + compatibility stuff because Windows auto-detects it as a installer.