18 Mar 2013

Configure a IIS website using Powershell

5 comments
Hello folks,
   In this post I will describe a Powershell script that I've created to automatically add and configure a new website in Microsoft IIS (Internet Information Services). I will first post all the Script Code and then I will describe every line in order to make it easier to understand. If you have any questions please feel free to add any comment and also share this article to other people interested in Powershell automatization.
   When running this script you will have to add a name to the new website, for example website.com. Then,  you'll have to choose between the options contained in the multi-selection box. This box contains some names that are some servers environments (like production, development etc.) When you choose UAT for example, the script will take the servers names from a .txt file that you will have to add near the script. After pressing the Install button the script will do the following:
   It will create two folders, one for the IIS logs and one for the website location, that will contain the website name, example D:\Inetpub\website.com and D:\IISLogFiles\website.com.
   It will then create a new application pool with your website name, example website.com
   A new website will be created (example website.com), that will use the two paths created earlier (one for the application location and one for the IIS logs). The application will use the app pool created earlier.
   If you add multiple servers in the .txt file, the script will do these configurations on all servers. This is usually done in an environment in which you have a lot of traffic and the servers need to be load balanced.
Here is the script code:



[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") # import system.drawing class from .net framework
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") # import System.Windows.Forms class from .net framework

$sel = @()
[string]$Name

$objForm = New-Object System.Windows.Forms.Form # creates an empty form in which we will place buttons
$objForm.Text = "IIS application" # form title
$objForm.Size = New-Object System.Drawing.Size(300,250) # form size w/h
$objForm.StartPosition = "CenterScreen" #form position

$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") # you can press enter instead of clicking ok
    {$x=$objTextBox.Text;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")  # you can press enter instead of clicking cancel
    {$objForm.Close()}})



# Cancel button
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,160)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)

# Label1
$objLabel1 = New-Object System.Windows.Forms.Label
$objLabel1.Location = New-Object System.Drawing.Size(10,20) 
$objLabel1.Size = New-Object System.Drawing.Size(280,20) 
$objLabel1.Text = "Please enter the IIS application name in the field:"
$objForm.Controls.Add($objLabel1) 

# Label2
$objLabel2 = New-Object System.Windows.Forms.Label
$objLabel2.Location = New-Object System.Drawing.Size(10,60) 
$objLabel2.Size = New-Object System.Drawing.Size(280,20) 
$objLabel2.Text = "Select the application environments:"
$objForm.Controls.Add($objLabel2) 

#TEXT box1 
$objTextBox = New-Object System.Windows.Forms.TextBox   
$objTextBox.Location = New-Object System.Drawing.Size(10,40) 
$objTextBox.Size = New-Object System.Drawing.Size(260,20) 
$objForm.Controls.Add($objTextBox) 

#Selection box
$objList = New-Object System.Windows.Forms.Listbox 
$objList.Location = New-Object System.Drawing.Size(10,80) 
$objList.Size = New-Object System.Drawing.Size(260,20) 
$objList.SelectionMode = "MultiExtended"
[void] $objList.Items.Add("DEV")
[void] $objList.Items.Add("SQA")
[void] $objList.Items.Add("UAT")
[void] $objList.Items.Add("LT")
[void] $objList.Items.Add("CERT")
[void] $objList.Items.Add("PROD")
$objList.Height = 70
$objForm.Controls.Add($objList) 

# Install button
$InstallButton = New-Object System.Windows.Forms.Button #creates Install button
$InstallButton.Location = New-Object System.Drawing.Size(75,160) # location inside the form
$InstallButton.Size = New-Object System.Drawing.Size(75,23)
$InstallButton.Text = "Install"
$InstallButton.Add_Click({
    $Name=$objTextBox.Text;
    foreach($Item in $objList.SelectedItems)
      {
     # Write-Host $Item
      $sel+= $Item
     # write-host $sel
      
      }
    
    foreach($i in $sel)
{
switch ($i){ 
<#"DEV" {
         foreach($s in "D:\iis\serversdev.txt")
         {
         CreateFolders($s)
         CreateAppPools($s)
         CreateApp($s)
         SelectLogPath($s)
         }
}#>
<#"SQA" { 
         foreach($s in "D:\iis\serverssqa.txt")
         {
         CreateFolders($s)
         CreateAppPools($s)
         CreateApp($s)
         SelectLogPath($s)
         }
}
#>
"UAT" { 
        foreach($s in "D:\iis\serversuat.txt")
        {
        CreateFolders($s)
        CreateAppPools($s)
        CreateApp($s)
        SelectLogPath($s)
        }
}
<#"LT"  {
        foreach($s in "D:\iis\serverslt.txt")
        {
        CreateFolders($s)
        CreateAppPools($s)
        CreateApp($s)
        SelectLogPath($s)
        }
}#>
<#"CERT"{
        foreach($s in "D:\iis\serverscert.txt")
        {
        CreateFolders($s)
        CreateAppPools($s)
        CreateApp($s)
        SelectLogPath($s)
        }
}#>
<#"PROD"{ 
        foreach($s in "D:\iis\serversprod.txt")
        {
        CreateFolders($s)
        CreateAppPools($s)
        CreateApp($s)
        SelectLogPath($s)
        }
}#>
            }
}

    $objForm.Close()
        
})
$objForm.Controls.Add($InstallButton)

#main
$objForm.Topmost = $True  # our form will appear in front of all opened windows
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()

#1 - Create Folders
function CreateFolders([string]$arg)
{
$servers = Get-Content $arg
foreach ($ser in $servers)
   {
   $remote = [WMIClass]"\\$ser\root\cimv2:Win32_Process"
   $remote.Create("cmd.exe /c md D:\Inetpub\$Name")
   $remote.Create("cmd.exe /c md D:\IISLogFiles\$Name")
   }
}

#2 - Create APP pools on the servers in the selected environments
function CreateAppPools([string]$arg01)
{
$server01 = Get-Content $arg01
$session01 = new-pssession -computername $server01
Invoke-command -session $session01 -ScriptBlock {param ($Name) Add-PSSnapin WebAdministration; New-WebAppPool $Name} -ArgumentList $Name
}

#3 - Create the Website
function CreateApp([string]$arg01)
{
$server02 = Get-Content $arg01
$session02 = new-pssession -computername $server02
Invoke-command -session $session02 -ScriptBlock {param ($Name) Add-PSSnapin WebAdministration; New-WebSite -Name $Name -IPAddress "*" -Port 80 -HostHeader www.$Name -PhysicalPath "D:\Inetpub\$Name" -ApplicationPool $Name} -ArgumentList $Name
}

#4 - Select the log files destination folder
function SelectLogPath([string]$arg01)
{
$server03 = Get-Content $arg01
$session03 = new-pssession -computername $server03
Invoke-command -session $session03 -ScriptBlock {param ($Name) Add-PSSnapin WebAdministration; Set-ItemProperty "IIS:\Sites\$Name" -name logfile.directory "D:\IISLogFiles\$Name"} -ArgumentList $Name
}

Get-PSSession | Remove-PSSession

  I've made this customized script for my company but it is pretty easy to modify it according to your needs. If you run this script using Powershell, the interface will look like this:
powershell script

   The first field will contain the IIS website name and the second field (the multi-selection menu) contains a group of servers in which the website will be installed. Now let me explain all the things that I've added in this script:
   First, I've imported the two .Net libraries, System.Drawing and System.Windows.Forms to be able to create customized forms, the import code is this one:

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") # import system.drawing class from .net framework
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") # import System.Windows.Forms class from .net framework


   After importing these libraries, I've declared two variables, $sel which is used to store the answer from the multi-selection menu (an array) and $Name which will store the answer from the first field (a string).
The next lines of code are used to create an empty form. I've added a title for the form contained in the upper section:
   The size of the form will be 300 width / 250 height and the position will always be in the centre of the screen. These are the lines that I've described here:

$objForm = New-Object System.Windows.Forms.Form - creates an empty form in which we will place buttons
$objForm.Text = "IIS application" - form title
$objForm.Size = New-Object System.Drawing.Size(300,250) - form size w/h
$objForm.StartPosition = "CenterScreen" - form position

   Then, I've added the feature in which you can press "Enter" key instead of clicking the Install button or press the "Esc" key instead of clicking the Cancel button:

$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") - you can press enter instead of clicking ok
    {$x=$objTextBox.Text;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")  - you can press enter instead of clicking cancel
    {$objForm.Close()}})

   I've then started coding the Cancel button. 
# Cancel button
$CancelButton = New-Object System.Windows.Forms.Button - creates an empty button form
$CancelButton.Location = New-Object System.Drawing.Size(150,160) - the location inside the form
$CancelButton.Size = New-Object System.Drawing.Size(75,23) - the size of the button w/h
$CancelButton.Text = "Cancel" - text that will appear inside the button
$CancelButton.Add_Click({$objForm.Close()}) - the button will close the form on click
$objForm.Controls.Add($CancelButton) - adds the Cancel button to our form ($objForm)

   I've then added the two labels which are basically the text indications that appear in the form:
# Label1
$objLabel1 = New-Object System.Windows.Forms.Label - crates an empty label form
$objLabel1.Location = New-Object System.Drawing.Size(10,20) - the location inside the form
$objLabel1.Size = New-Object System.Drawing.Size(280,20) - the size of the label
$objLabel1.Text = "Please enter the IIS application name in the field:" - the text that will appear inside the label
$objForm.Controls.Add($objLabel1) - added the label to our form

   I've done something similar to the 2'nd label but I've changed the inside text:



# Label2
$objLabel2 = New-Object System.Windows.Forms.Label
$objLabel2.Location = New-Object System.Drawing.Size(10,60) 
$objLabel2.Size = New-Object System.Drawing.Size(280,20) 
$objLabel2.Text = "Select the application environments:" - inside text
$objForm.Controls.Add($objLabel2) 

   After adding the two labels, I've created the field that is under the "Please enter the IIS application name in the field":

#TEXT box1 
$objTextBox = New-Object System.Windows.Forms.TextBox  - created a new text box 
$objTextBox.Location = New-Object System.Drawing.Size(10,40)  - the location inside the form
$objTextBox.Size = New-Object System.Drawing.Size(260,20) - the size of the text box
$objForm.Controls.Add($objTextBox) - added the text box to our form

   After adding the text box, I've created the multi-selection menu or the selection box. This is customized according to my needs, the objects that appers inside the selection box can be changed to your needs:

#Selection box
$objList = New-Object System.Windows.Forms.Listbox - new list box
$objList.Location = New-Object System.Drawing.Size(10,80) - the location of the list box
$objList.Size = New-Object System.Drawing.Size(260,20) - the size of the selection box
$objList.SelectionMode = "MultiExtended" 
here are the options available in the selection box:
[void] $objList.Items.Add("DEV")
[void] $objList.Items.Add("SQA")
[void] $objList.Items.Add("UAT")
[void] $objList.Items.Add("LT")
[void] $objList.Items.Add("CERT")
[void] $objList.Items.Add("PROD")
$objList.Height = 70 - the height of the list box
$objForm.Controls.Add($objList) - added the selection box to our form
This is how this selection box will appear when you run the script:
powershell script

   The Install button is a little more complex, it also acts as our main menu.

# Install button
$InstallButton = New-Object System.Windows.Forms.Button - creates Install button
$InstallButton.Location = New-Object System.Drawing.Size(75,160) - location inside the form
$InstallButton.Size = New-Object System.Drawing.Size(75,23) - the size of the install button
$InstallButton.Text = "Install" - the text inside the button
$InstallButton.Add_Click({ 
    $Name=$objTextBox.Text; - on click, the value contained in the text box($objTextBox.Text) will be added to the $Name variable
    foreach($Item in $objList.SelectedItems) - for each item that you've selected from the selection menu
      {
     # Write-Host $Item
      $sel+= $Item - items will be added to our array ($sel)
     # write-host $sel
      
      }
    
    foreach($i in $sel) - for each item contained in our array
{
switch ($i){  - the switch statement will test every option that you've chosen and if it finds your selection, it will run some functions. In this script only the UAT section is activated, you can activate all if you remove <# and >#
<#"DEV" {
         foreach($s in "D:\iis\serversdev.txt") - for each server contained in the .txt file do the following:
         {
         CreateFolders($s) - run the Create Folders function
         CreateAppPools($s) - run the CreateAppPools function
         CreateApp($s) - run the CreateApp function
         SelectLogPath($s) - run the SelectLogPath function
         }
}#>
<#"SQA" { 
         foreach($s in "D:\iis\serverssqa.txt")
         {
         CreateFolders($s)
         CreateAppPools($s)
         CreateApp($s)
         SelectLogPath($s)
         }
}
#>
"UAT" { 
        foreach($s in "D:\iis\serversuat.txt")
        {
        CreateFolders($s)
        CreateAppPools($s)
        CreateApp($s)
        SelectLogPath($s)
        }
}
<#"LT"  {
        foreach($s in "D:\iis\serverslt.txt")
        {
        CreateFolders($s)
        CreateAppPools($s)
        CreateApp($s)
        SelectLogPath($s)
        }
}#>
<#"CERT"{
        foreach($s in "D:\iis\serverscert.txt")
        {
        CreateFolders($s)
        CreateAppPools($s)
        CreateApp($s)
        SelectLogPath($s)
        }
}#>
<#"PROD"{ 
        foreach($s in "D:\iis\serversprod.txt")
        {
        CreateFolders($s)
        CreateAppPools($s)
        CreateApp($s)
        SelectLogPath($s)
        }
}#>
            }
}

    $objForm.Close() - in the end, the Install button will close the form
        
})
$objForm.Controls.Add($InstallButton) - added the Install button to our form

   The #main section will actually make the form visible and it will appear in front of every window that you are already opened:
#main
$objForm.Topmost = $True  # our form will appear in front of all opened windows
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()

   After I've finished with the form creation, I've created the functions. The first function will create the folders on the indicated servers.
#1 - Create Folders
function CreateFolders([string]$arg) - uses an argument ( the txt file in which you've added the servers names
{
$servers = Get-Content $arg - reads the .txt file content
foreach ($ser in $servers) - for each element inside the txt file
   {
   $remote = [WMIClass]"\\$ser\root\cimv2:Win32_Process" - calls for the WMI class that is used to remote create folders
   $remote.Create("cmd.exe /c md D:\Inetpub\$Name") - creates a folder in the Inetpub section with the application name
   $remote.Create("cmd.exe /c md D:\IISLogFiles\$Name") - creates a folder in the IISLogFiles section with the application name
   }
}

   Then, I've added the application pool function:
#2 - Create APP pools on the servers in the selected environments
function CreateAppPools([string]$arg01) - creates the function with the same argument (the txt file)
{
$server01 = Get-Content $arg01 - reads the content
$session01 = new-pssession -computername $server01 - creates a new powershell session on the remote machine
Invoke-command -session $session01 -ScriptBlock {param ($Name) Add-PSSnapin WebAdministration; New-WebAppPool $Name} -ArgumentList $Name - it will run the -ScriptBlock section on the remote machine. It will add the WebAdministration module in which the New-WebAppPool cmdlet is located and then the script will create a new application pool that has the same name as our website
}

   The next section contains the function that configures a new website, I will only describe the new elements:
#3 - Create the Website
function CreateApp([string]$arg01)
{
$server02 = Get-Content $arg01
$session02 = new-pssession -computername $server02
Invoke-command -session $session02 -ScriptBlock {param ($Name) Add-PSSnapin WebAdministration; New-WebSite -Name $Name -IPAddress "*" -Port 80 -HostHeader www.$Name -PhysicalPath "D:\Inetpub\$Name" -ApplicationPool $Name} -ArgumentList $Name
}


The script will create a new website with the name contained in the $Name variable, it will create a binding on the port 80 with the name of our application (in our example, www.website.com). The script will also set the application location (
D:\Inetpub\website.com) and the application pool that it will use (website.com).
   In the end, I've created the function that will change the IIS logs path:
#4 - Select the log files destination folder
function SelectLogPath([string]$arg01)
{
$server03 = Get-Content $arg01
$session03 = new-pssession -computername $server03
Invoke-command -session $session03 -ScriptBlock {param ($Name) Add-PSSnapin WebAdministration; Set-ItemProperty "IIS:\Sites\$Name" -name logfile.directory "D:\IISLogFiles\$Name"} -ArgumentList $Name
}

Get-PSSession | Remove-PSSession - closes any Powershell session.

   That is all for this Powershell script folks, I hope it will serve you well. Please leave a comment and share it to others and enjoy a wonderful day.
Socialize It →
Subscribe Us by Email and Get Free Updates

Other Interesting Posts :

5 comments :

  1. Thanks for this great share..i will definitely get some good knowledge from here.

    ReplyDelete
  2. Everyone want to use virus-less and problems free system and in this scenario your post is really informative and effective to get rid of the virus causes. This kind of awareness is very important for every computer user.

    ReplyDelete
  3. I am totally stunned by your article. You saved my time. Thanks a million for sharing this article

    ReplyDelete
  4. After read this informative and effective post regarding technicalities of viruses attacon on systems i have good knowledge now to fix this issue and to explain this issue to others.

    ReplyDelete
  5. Thank you very much, I appreciate this!

    ReplyDelete

© 2014 All Rights Reserved.
IT training day & Powered By BloggerHero