PowerShell.PowerLibrary.ExtendedWebAdministration.psm1

FUNCTION Register-ApplicationPool
{
    param
    (      
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [Alias('N')]
        [string]
        $Name,
            
        [Parameter(Mandatory = $false, ValueFromPipeline = $true, HelpMessage='LocalSystem|0;LocalService|1;NetworkService|2;SpecificUser|3;ApplicationPoolIdentity|4')]
        [Alias('I')]
        [string]
        [ValidateSet('ApplicationPoolIdentity', 'LocalService', 'LocalSystem', 'NetworkService', 'SpecificUser')]
        $IdentityType,
            
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [Alias('C')]
        [pscredential]
        $Credentials,
            
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [Alias('32')]
        [switch]
        $Enable32BitApplication
    );

    Write-Host "Creating new Application Pool " -ForegroundColor Yellow -NoNewline;
    Write-Host $Name -ForegroundColor White;

    IF([string]::IsNullOrEmpty($IdentityType))
    {
        $IdentityType = 'NetworkService';
    }

    Set-Location IIS:;

    $RootDirectory = 'IIS:\AppPools\';

    $Path = [System.IO.Path]::Combine($RootDirectory,  $Name);

    if(Test-Path $Path)  
    {
        Write-Host "Application Pool $Name already exists and will be removed." -ForegroundColor Magenta;
        Remove-WebAppPool $Name;
        #gci IIS:\AppPools
    }

    $pool = New-Item $Path;
    $pool.processModel.identityType = $IdentityType;
    IF($IdentityType -eq 'SpecificUser')
    {
        $NetworkCredentials = $Credentials.GetNetworkCredential();
        $pool.processModel.userName = $Credentials.UserName;
        $pool.processModel.password = $NetworkCredentials.Password;
    }
    IF($Enable32BitApplication)
    {
        $pool.enable32BitAppOnWin64 = [bool]::TrueString;
    }
    ELSE
    {
        $pool.enable32BitAppOnWin64 = [bool]::FalseString;
    }
    $pool | Set-Item;
    
    Write-Host "$Name Application Pool has been created" -ForegroundColor Green;
    Set-Location $PSScriptRoot;
}

FUNCTION Register-ApplicationPools
{
    param
    (      
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [psobject[]]
        $ApplicationPools,

        [Parameter(Mandatory = $false, ValueFromPipeline=$true)]
        [Alias('Progress')]
        [switch]
        $WithProgress
    );

    Write-Host "Creating new Application Pools" -ForegroundColor Cyan;
    
    IF($ApplicationPools -eq $null)
    {
        Write-Message "ApplicationPools is required!!!" -ForegroundColor Red;
        Write-Message "Please provide an array of [psobject].`nAn Example of [psobject] is defined below." -ForegroundColor DarkYellow;
        Write-Message '[psobject]$ApplicationPool = @{ [string]Name = "Application Pool Name"; [string]IdentityType = [ValidateSet("ApplicationPoolIdentity", "LocalService", "LocalSystem", "NetworkService", "SpecificUser")]; [pscredential]Credentials = Get-Credential; [switch]Enable32BitApplication = $false; }' -ForegroundColor Yellow;
        return;
    }

    IF($WithProgress)
    {
        $Total = $ApplicationPools.Count;
        $Index = 0;
        $Progress = 0;
        IF($Total -gt 0) 
        {
            $Progress = $Index / $Total * 100;
        }
        Write-Progress -Activity "Creating new Application Pools" -Status "----" -PercentComplete 0;
    }

    FOREACH($ApplicationPool in $ApplicationPools)
    {
        IF($WithProgress)
        {
            IF($Total -gt 0) 
            {
                $Progress = $Index / $Total * 100;
            }
            Write-Progress -Activity "Creating New Application Pool" -Status "$($ApplicationPool.Name)" -PercentComplete $Progress;
        }
        
        Register-ApplicationPool -Name $ApplicationPool.Name -Credentials $ApplicationPool.Credentials -IdentityType $ApplicationPool.IdentityType  -Enable32BitApplication:$($ApplicationPool.Enable32BitApplication);

        IF($WithProgress)
        {
            $Index ++;
        }
    }

    IF($WithProgress)
    {
        Write-Progress -Activity "Creating new Application Pools" -Status "Completed" -PercentComplete 100 -Completed:$true;
    }

    Write-Host "Creating new Application Pools Completed" ;
}

FUNCTION Unregister-ApplicationPool
{
    param
    (      
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [Alias('N')]
        [string]
        $Name
    );

    Write-Host "Deleting Application Pool " -ForegroundColor Yellow -NoNewline;
    Write-Host $Name -ForegroundColor White;

    Set-Location IIS:;

    $RootDirectory = 'IIS:\AppPools\';

    $Path = [System.IO.Path]::Combine($RootDirectory,  $Name);

    if(Test-Path $Path)  
    {
        Write-Host "Application Pool $Name already exists and will be removed." -ForegroundColor Magenta;
        Remove-WebAppPool $Name;
    }
    
    Write-Host "$Name Application Pool has been deleted" -ForegroundColor Green;
    Set-Location $PSScriptRoot;
}

FUNCTION Unregister-ApplicationPools
{
    param
    (      
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [object[]]
        $ApplicationPools,

        [Parameter(Mandatory = $false, ValueFromPipeline=$true)]
        [Alias('Progress')]
        [switch]
        $WithProgress
    );

    Write-Host "Deleting Application Pools" -ForegroundColor Cyan;
    
    IF($WithProgress)
    {
        $Total = $ApplicationPools.Count;
        $Index = 0;
        $Progress = 0;
        IF($Total -gt 0) 
        {
            $Progress = $Index / $Total * 100;
        }
        Write-Progress -Activity "Deleting Application Pools" -Status "----" -PercentComplete 0;
    }

    FOREACH($ApplicationPool in $ApplicationPools)
    {
        IF($WithProgress)
        {
            IF($Total -gt 0) 
            {
                $Progress = $Index / $Total * 100;
            }
            Write-Progress -Activity "Deleting Application Pool" -Status "$ApplicationPool" -PercentComplete $Progress;
        }
        
        Unregister-ApplicationPool -Name $ApplicationPool;

        IF($WithProgress)
        {
            $Index ++;
        }
    }
    IF($WithProgress)
    {
        Write-Progress -Activity "Deleting Application Pools" -Status "Completed" -PercentComplete 100 -Completed:$true;
    }
    Write-Host "Deleting Application Pools Completed" ;
}

FUNCTION Restart-ApplicationPool
{
    param
    (      
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [Alias('N')]
        [string]
        $Name
    );

    Write-Host "Restarting Application Pool " -ForegroundColor Yellow -NoNewline;
    Write-Host $Name -ForegroundColor White;

    Set-Location IIS:;

    Restart-WebAppPool -Name $Name;
    
    Write-Host "$Name Application Pool has been Restarted" -ForegroundColor Green;
    Set-Location $PSScriptRoot;
}

FUNCTION Restart-ApplicationPools
{
    param
    (      
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string[]]
        $ApplicationPools,

        [Parameter(Mandatory = $false, ValueFromPipeline=$true)]
        [Alias('Progress')]
        [switch]
        $WithProgress
    );

    Write-Host "Restarting Application Pools" -ForegroundColor Cyan;
    
    IF($WithProgress)
    {
        $Total = $ApplicationPools.Count;
        $Index = 0;
        $Progress = 0;
        IF($Total -gt 0) 
        {
            $Progress = $Index / $Total * 100;
        }
        Write-Progress -Activity "Restarting Application Pools" -Status "----" -PercentComplete 0;
    }

    FOREACH($ApplicationPool in $ApplicationPools)
    {
        IF($WithProgress)
        {
            IF($Total -gt 0) 
            {
                $Progress = $Index / $Total * 100;
            }
            Write-Progress -Activity "Restarting Application Pool" -Status "$($ApplicationPool)" -PercentComplete $Progress;
        }
        
        Restart-ApplicationPool -Name $ApplicationPool;

        IF($WithProgress)
        {
            $Index ++;
        }
    }
    IF($WithProgress)
    {
        Write-Progress -Activity "Restarting Application Pools" -Status "Completed" -PercentComplete 100 -Completed:$true;
    }
    Write-Host "Restarting Application Pools Completed" ;
}

FUNCTION Stop-ApplicationPool
{
    param
    (      
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [Alias('N')]
        [string]
        $Name
    );

    Write-Host "Stopping Application Pool " -ForegroundColor Yellow -NoNewline;
    Write-Host $Name -ForegroundColor White;

    Set-Location IIS:;

    Stop-WebAppPool -Name $Name;
    
    Write-Host "$Name Application Pool has been Stopped" -ForegroundColor Green;
    Set-Location $PSScriptRoot;
}

FUNCTION Stop-ApplicationPools
{
    param
    (      
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string[]]
        $ApplicationPools,

        [Parameter(Mandatory = $false, ValueFromPipeline=$true)]
        [Alias('Progress')]
        [switch]
        $WithProgress
    );

    Write-Host "Stopping Application Pools" -ForegroundColor Cyan;
    
    IF($WithProgress)
    {
        $Total = $ApplicationPools.Count;
        $Index = 0;
        $Progress = 0;
        IF($Total -gt 0) 
        {
            $Progress = $Index / $Total * 100;
        }
        Write-Progress -Activity "Stopping Application Pools" -Status "----" -PercentComplete 0;
    }

    FOREACH($ApplicationPool in $ApplicationPools)
    {
        IF($WithProgress)
        {
            IF($Total -gt 0) 
            {
                $Progress = $Index / $Total * 100;
            }
            Write-Progress -Activity "Stopping Application Pool" -Status "$($ApplicationPool)" -PercentComplete $Progress;
        }
        
        Stop-ApplicationPool -Name $ApplicationPool;

        IF($WithProgress)
        {
            $Index ++;
        }
    }
    IF($WithProgress)
    {
        Write-Progress -Activity "Stopping Application Pools" -Status "Completed" -PercentComplete 100 -Completed:$true;
    }
    Write-Host "Stopping Application Pools Completed" ;
}

FUNCTION Start-ApplicationPool
{
    param
    (      
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [Alias('N')]
        [string]
        $Name
    );

    Write-Host "Starting Application Pool " -ForegroundColor Yellow -NoNewline;
    Write-Host $Name -ForegroundColor White;

    Set-Location IIS:;

    Start-WebAppPool -Name $Name;
    
    Write-Host "$Name Application Pool has been Started" -ForegroundColor Green;
    Set-Location $PSScriptRoot;
}

FUNCTION Start-ApplicationPools
{
    param
    (      
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string[]]
        $ApplicationPools,

        [Parameter(Mandatory = $false, ValueFromPipeline=$true)]
        [Alias('Progress')]
        [switch]
        $WithProgress
    );

    Write-Host "Starting Application Pools" -ForegroundColor Cyan;
    
    IF($WithProgress)
    {
        $Total = $ApplicationPools.Count;
        $Index = 0;
        $Progress = 0;
        IF($Total -gt 0) 
        {
            $Progress = $Index / $Total * 100;
        }
        Write-Progress -Activity "Starting Application Pools" -Status "----" -PercentComplete 0;
    }

    FOREACH($ApplicationPool in $ApplicationPools)
    {
        IF($WithProgress)
        {
            IF($Total -gt 0) 
            {
                $Progress = $Index / $Total * 100;
            }
            Write-Progress -Activity "Starting Application Pool" -Status "$($ApplicationPool)" -PercentComplete $Progress;
        }
        
        Restart-ApplicationPool -Name $ApplicationPool;

        IF($WithProgress)
        {
            $Index ++;
        }
    }
    IF($WithProgress)
    {
        Write-Progress -Activity "Starting Application Pools" -Status "Completed" -PercentComplete 100 -Completed:$true;
    }
    Write-Host "Starting Application Pools Completed" ;
}

FUNCTION Register-WebApplication
{
    param
    (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $WebsiteName,  
          
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $ApplicationName,  
          
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $PhysicalPath,  
          
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $ApplicationPool
    );
    
    Write-Host "Creating new Web Application " -ForegroundColor Yellow -NoNewline;
    Write-Host $ApplicationName -ForegroundColor White;

    Set-Location IIS:;

    $RootDirectory = 'IIS:\Sites\';

    $Path = [System.IO.Path]::Combine($RootDirectory,  $WebsiteName, $ApplicationName);

    if(Test-Path $Path)  
    {
        Write-Host "Web Application $Path already exists and will be removed." -ForegroundColor Magenta;
        
        Remove-WebApplication -Name $ApplicationName -Site $WebsiteName;

        #gci IIS:\Sites;
    }
    
    New-WebApplication `
    -Site $WebsiteName `
    -Name $ApplicationName `
    -PhysicalPath $PhysicalPath `
    -ApplicationPool $ApplicationPool;
    
    Write-Host "$ApplicationName Web Application has been created" -ForegroundColor Green;

    Set-Location $PSScriptRoot;
}

FUNCTION Register-WebApplications
{
    param
    (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $WebsiteName,  
          
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $ApplicationPool,

        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [psobject[]]
        $WebApplications
    );

    Write-Host "Creating new Web Applications" -ForegroundColor Cyan;

    FOREACH($WebApplication in $WebApplications.GetEnumerator())
    {
        Register-WebApplication `
        -WebsiteName $WebsiteName `
        -ApplicationName $WebApplication.Name `
        -PhysicalPath $WebApplication.Value `
        -ApplicationPool $ApplicationPool;
    }
}

FUNCTION Register-VirtualDirectory
{
    param
    (    
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $WebsiteName,  
          
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $VirtualDirectoryName,  
          
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $PhysicalPath
    );
    
    Write-Host "Creating new Virtual Directory " -ForegroundColor Yellow -NoNewline;
    Write-Host $VirtualDirectoryName -ForegroundColor White;

    Set-Location IIS:;

    $RootDirectory = 'IIS:\Sites\';

    $Path = [System.IO.Path]::Combine($RootDirectory,  $WebsiteName, $VirtualDirectoryName);

    if(Test-Path $Path)  
    {
        Write-Host "Virtual Directory $Path already exists and will be removed." -ForegroundColor Magenta;
        
        Remove-WebVirtualDirectory -Site $WebsiteName -Name $VirtualDirectoryName;

        #gci IIS:\Sites;
    }
    
    New-WebVirtualDirectory `
    -Site $WebsiteName `
    -Name $VirtualDirectoryName `
    -PhysicalPath $PhysicalPath;
    
    Write-Host "$VirtualDirectoryName Virtual Directory has been created" -ForegroundColor Green;

    Set-Location $PSScriptRoot;
}

FUNCTION Register-VirtualDirectories
{
    param
    (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $WebsiteName,

        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [psobject[]]
        $VirtualDirectories
    );

    Write-Host "Creating new Virtual Directories" -ForegroundColor Cyan;

    FOREACH($VirtualDirectory in $VirtualDirectories.GetEnumerator())
    {
        Register-VirtualDirectory `
        -ApplicationName $WebsiteName `
        -VirtualDirectoryName $VirtualDirectory.Name `
        -PhysicalPath $VirtualDirectory.Value;
    }
}

FUNCTION Register-Binding
{
    param
    (    
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $WebsiteName,  
          
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $HostHeader,    
          
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [string]
        $Protocol,   
          
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [string]
        $Ip,  
          
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [int]
        $Port,  
          
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [string]
        $CertificateThumbprint
    );
    
    Write-Host "Creating new Web Binding " -ForegroundColor Yellow -NoNewline;
    Write-Host $HostHeader -ForegroundColor White;

    $Secure = ![string]::IsNullOrWhiteSpace($CertificateThumbprint);

    IF($null -eq $Port -or $Port -eq 0)
    {
        IF($Secure)
        {
            $Port = 443;
        }
        ELSE
        {
            $Port = 80;
        }
    }

    IF($null -eq $Protocol -or [string]::IsNullOrWhiteSpace($Protocol))
    {
        IF($Secure)
        {
            $Protocol = "https";
        }
        ELSE
        {
            $Protocol = "http";
        }
    }

    IF($null -eq $Ip -or [string]::IsNullOrWhiteSpace($Ip))
    {
        $Ip = "*";
    }

    (Get-WebBinding -Name $WebsiteName -Protocol $Protocol -HostHeader $HostHeader -Port $Port -IPAddress $Ip) | Remove-WebBinding;
    New-WebBinding -Name $WebsiteName -Protocol $Protocol -HostHeader $HostHeader -Port $Port -IPAddress $Ip;
    IF($Secure)
    {
        (Get-WebBinding -Name $WebsiteName -Protocol $Protocol -HostHeader $HostHeader -Port $Port -IPAddress $Ip).AddSslCertificate($CertificateThumbprint, "WebHosting");
    }
    
    Write-Host "$HostHeader Web Binding has been created" -ForegroundColor Green;
}

FUNCTION Register-Bindings
{
    param
    (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $WebsiteName,

        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [psobject[]]
        $Bindings
    );

    Write-Host "Creating new Web Bindings" -ForegroundColor Cyan;

    FOREACH($Binding in $Bindings.GetEnumerator())
    {
        Register-Binding `
        -WebsiteName $WebsiteName `
        -HostHeader $Binding.HostHeader `
        -Ip $Binding.Ip `
        -Port $Binding.Port `
        -CertificateThumbprint $Binding.CertificateThumbprint;
    }
}

FUNCTION Register-Website
{
    param
    (    
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $WebsiteName,  
          
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $ApplicationPool,  
          
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $PhysicalPath,  
          
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $URL,  
          
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [AllowNull()]
        [System.Nullable[int]]
        $Port,  
          
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [string]
        $CertificateThumbprint,

        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [psobject[]]
        $VirtualDirectories,

        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [psobject[]]
        $WebApplications,

        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [psobject[]]
        $Bindings
    );
    
    Write-Host "Creating new Web Site " -ForegroundColor Yellow -NoNewline;
    Write-Host $WebsiteName -ForegroundColor White;

    Set-Location IIS:;

    $RootDirectory = 'IIS:\Sites\';

    $Path = [System.IO.Path]::Combine($RootDirectory,  $WebsiteName);

    $Secure = ![string]::IsNullOrWhiteSpace($CertificateThumbprint);

    IF($null -eq $Port)
    {
        IF($Secure)
        {
            $Port = 443;
        }
        ELSE
        {
            $Port = 80;
        }
    }

    if(Test-Path $Path)  
    {
        Write-Host "Web Site $WebsiteName already exists and will be removed." -ForegroundColor Magenta;

        IF($Secure){  Remove-Item -Path "IIS:\SslBindings\!$Port!$URL" -ErrorAction SilentlyContinue; }
        
        Remove-Website $WebsiteName;
        
        #gci IIS:\Sites;
    }
    
    New-Website `
    -Name $WebsiteName `
    -PhysicalPath $PhysicalPath `
    -ApplicationPool $ApplicationPool `
    -HostHeader $URL `
    -Ssl:$Secure `
    -SslFlags 1 `
    -Port $Port;

    IF($Secure)
    {
        $Certificate = Get-ChildItem -Path Cert:\LocalMachine\WebHosting | Where-Object { $_.Thumbprint -eq $CertificateThumbprint; };
        
        IF($null -ne $Certificate)
        {
            New-Item -Path "IIS:\SslBindings\!$Port!$URL" -Value $Certificate -SSLFlags 1 -Force;
        }
    }    

    IF($null -ne $VirtualDirectories)
    {
        Register-VirtualDirectories -WebsiteName $WebSite.ApplicationName -VirtualDirectories $VirtualDirectories;
    }

    IF($null -ne $WebApplications)
    {
        Register-WebApplications -WebsiteName $WebSite.ApplicationName -ApplicationPool $WebSite.ApplicationPool.Name -WebApplications $WebApplications;
    }

    IF($null -ne $Bindings)
    {
        Register-Bindings -WebsiteName $WebSite.ApplicationName -Bindings $Bindings;
    }
    
    Write-Host "$WebsiteName Web Site has been created" -ForegroundColor Green;

    Set-Location $PSScriptRoot;
}

FUNCTION Register-Websites
{
    param
    (      
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [psobject[]]
        $WebSites,

        [Parameter(Mandatory = $false, ValueFromPipeline=$true)]
        [Alias('Progress')]
        [switch]
        $WithProgress
    );

    IF($null -eq $WebSites)
    {
        Write-Message "Applications is required!!!" -ForegroundColor Red;
        Write-Message "Please provide an array of [psobject].`nAn Example of [psobject] is defined below." -ForegroundColor DarkYellow;
        Write-Message '[psobject]$Application = @{ [string]ApplicationId = "unique application id"; [string]ApplicationName = "Application Name"; [psobject]ApplicationPool = @{ [string]Name = "Application Pool Name"; [pscredential]Credentials = Get-Credential; [switch]Enable32BitApplication = $false; }; [string]PhysicalPath = "Application Physical Path"; [string]URL = "Application Url"; [string]CertificateThumbprint = "Certificate Id"; [Hashtable]VirtualDirectories = @{ "Key" = "Value"; }; }' -ForegroundColor Yellow;
        return;
    }

    Write-Host "Creating new Web Applications" -ForegroundColor Cyan;
    
    IF($WithProgress)
    {
        $Total = $WebSites.Count;
        $Index = 0;
        $Progress = 0;
        IF($Total -gt 0) 
        {
            $Progress = $Index / $Total * 100;
        }
        Write-Progress -Activity "Creating new Web Applications" -Status "----" -PercentComplete 0;
    }

    FOREACH($WebSite in $WebSites)
    {
        IF($WithProgress)
        {
            IF($Total -gt 0) 
            {
                $Progress = $Index / $Total * 100;
            }
            Write-Progress -Activity "Creating New Web Application" -Status "$($WebSite.ApplicationName)" -PercentComplete $Progress;
        }
        
        Register-Website `
        -WebsiteName $WebSite.ApplicationName `
        -ApplicationPool $WebSite.ApplicationPool.Name `
        -PhysicalPath $WebSite.PhysicalPath `
        -URL $WebSite.URL `
        -Port $WebSite.Port `
        -CertificateThumbprint $WebSite.CertificateThumbprint `
        -VirtualDirectories $WebSite.VirtualDirectories `
        -WebApplications $WebSite.WebApplications `
        -Bindings $WebSite.Bindings;

        IF($WithProgress)
        {
            $Index ++;
        }
    }

    IF($WithProgress)
    {
        Write-Progress -Activity "Creating new Web Applications" -Status "Completed" -PercentComplete 100 -Completed:$true;
    }

    Write-Host "Creating new Web Applications Completed" ;
}

FUNCTION Unregister-Website
{
    param
    (    
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $ApplicationName,  
          
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $URL
    );
    
    Write-Host "Deleting Web Application" -ForegroundColor Yellow -NoNewline;
    Write-Host $ApplicationName -ForegroundColor White;

    Set-Location IIS:;

    $RootDirectory = 'IIS:\Sites\';

    $Path = [System.IO.Path]::Combine($RootDirectory,  $ApplicationName);

    if(Test-Path $Path)  
    {
        Write-Host "Web Application $ApplicationName already exists and will be removed." -ForegroundColor Magenta;
        
        Remove-WebSite $ApplicationName;

        Remove-Item -Path "IIS:\SslBindings\!443!$URL";
    }
    
    Write-Host "$ApplicationName Web Application has been deleted" -ForegroundColor Green;

    Set-Location $PSScriptRoot;
}

FUNCTION Unregister-Websites
{
    param
    (      
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [psobject[]]
        $Applications,

        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [Alias('Progress')]
        [switch]
        $WithProgress
    );

    Write-Host "Deleting Web Applications" -ForegroundColor Cyan;
    
    IF($WithProgress)
    {
        $Total = $Applications.Count;
        $Index = 0;
        $Progress = 0;
        IF($Total -gt 0) 
        {
            $Progress = $Index / $Total * 100;
        }
        Write-Progress -Activity "Deleting Web Applications" -Status "----" -PercentComplete 0;
    }

    FOREACH($Application in $Applications)
    {
        IF($WithProgress)
        {
            IF($Total -gt 0) 
            {
                $Progress = $Index / $Total * 100;
            }
            Write-Progress -Activity "Deleting Web Application" -Status "$($Application.ApplicationName)" -PercentComplete $Progress;
        }
        
        Unregister-Website `
        -ApplicationName $Application.ApplicationName `
        -URL $Application.URL;

        IF($WithProgress)
        {
            $Index ++;
        }
    }
    IF($WithProgress)
    {
        Write-Progress -Activity "Deleting Web Applications" -Status "Completed" -PercentComplete 100 -Completed:$true;
    }

    Write-Host "Deleting Web Applications Completed";
}

FUNCTION Register-Hosts
{    
    #region Parameters
    [CmdletBinding()]
    param
    (
        [Parameter(ValueFromPipeline=$true)]
        [Alias('H')]
        [string[]]
        $Hosts,

        [Parameter(ValueFromPipeline=$true)]
        [Alias('Address')]
        [ipaddress]
        $IP,

        [Parameter(ValueFromPipeline = $true)]
        [Alias('S')]
        [ValidateNotNullOrEmpty()]
        [switch]
        $Silent = $false
    )
    #endregion
    Write-Host "Writing Hosts to System Host File." -ForegroundColor Cyan;
    
    $IPString = $IP.IPAddressToString; 
    IF([string]::IsNullOrWhiteSpace($IPString))
    {
        $IPString = '127.0.0.1';
    }
    $Dictionary = New-Object "System.Collections.Generic.Dictionary[[string], [string]]";
    $HostFilePath = 'C:\Windows\System32\drivers\etc\hosts';
    
    IF([System.IO.File]::Exists($HostFilePath))
    {
        IF(!$Silent)
        {
            Write-Host "Backing up Hosts... " -NoNewline -ForegroundColor Yellow;
            Write-Host $HostFilePath -ForegroundColor White;
        }

        $HostBackupFilePath = "$HostFilePath.$([datetime]::Now.ToString("yyyy_MM_dd_HH_mm_ss")).bak";
        [System.IO.File]::Copy($HostFilePath, $HostBackupFilePath, $true);
        
        IF(!$Silent)
        {
            Write-Host "Reading Hosts from System Host File: " -NoNewline -ForegroundColor Yellow;
            Write-Host $HostFilePath -ForegroundColor White;
        }

        $SystemHosts = [System.IO.File]::ReadAllLines($HostFilePath);
        FOREACH($Record in $SystemHosts)
        {
            IF($Record.StartsWith('#'))
            {
                $Dictionary[$Record.TrimStart('#')] = '#';
            }
            IF(![string]::IsNullOrWhiteSpace($Record) -and !$Record.StartsWith('#'))
            {
                $Value = $Record -split { $_ -eq ' ' -or $_ -eq ' ' }, 2;
                IF($Value -ne $null -and $Value.Length -eq 2)
                {
                    $Dictionary[$Value[1].Trim()] = $Value[0];
                }
            }
        }
    }
    
    IF($Hosts -eq $null -or $Hosts.Length -eq 0)
    {
        $Hosts = (Get-Website).Bindings.Collection.bindingInformation | % { $_.Split(':')[2] }
        IF(!$Silent)
        {
            Write-Host "Getting Hostheaders from IIS site bindings..." -ForegroundColor Yellow;
            Write-Host $Hosts -ForegroundColor White;
        }
    }    

    FOREACH($Host in $Hosts)
    {
        IF(!$Silent)
        {
            Write-Host "Adding|Ensuring Host Record" -ForegroundColor Yellow;
            Write-Host "Host = " -NoNewline -ForegroundColor Magenta;
            Write-Host $Host -NoNewline -ForegroundColor White;
            Write-Host " | IP = " -NoNewline -ForegroundColor Magenta;
            Write-Host $IPString -ForegroundColor White;
        }
        IF(![string]::IsNullOrWhiteSpace($Host))
        {
            $Dictionary[$Host] = $IPString;
        }
    }

    $Writer = New-Object System.Text.StringBuilder;
    $Dictionary.GetEnumerator() | %{ $__ = $Writer.AppendFormat('{0} {1}', $_.Value, $_.Key).AppendLine(); };
    $Value = $Writer.ToString();
    
    IF(!$Silent)
    {
        Write-Host "Saving Hosts to System Host File: " -NoNewline -ForegroundColor Yellow;
        Write-Host $HostFilePath -ForegroundColor White;
    }
    [System.IO.File]::WriteAllText($HostFilePath, $Value);
}

FUNCTION Uninstall-SelfHostedCertificate
{
    param
    ( 
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $DnsName
    );

    $Subject = "CN=$($DnsName)";

    $Certificate = Get-ChildItem -Path Cert:\LocalMachine\WebHosting | Where-Object { $_.Subject -eq $Subject } | Select -First 1;
    IF($null -ne $Certificate) 
    {
        Remove-Item -Path "Cert:\LocalMachine\WebHosting\$($Certificate.Thumbprint)" -Force; 
    }    

    $Certificate = Get-ChildItem -Path Cert:\LocalMachine\Root | Where-Object { $_.Subject -eq $Subject } | Select -First 1;
    IF($null -ne $Certificate) 
    {
        Remove-Item -Path "Cert:\LocalMachine\Root\$($Certificate.Thumbprint)" -Force; 
    }    

    $Certificate = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Subject -eq $Subject } | Select -First 1;
    IF($null -ne $Certificate) 
    {
        Remove-Item -Path "Cert:\LocalMachine\My\$($Certificate.Thumbprint)" -Force; 
    }
}

FUNCTION Install-SelfHostedCertificate
{
    param
    (    
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $DnsName
    );

    $Subject = "CN=$($DnsName)";
    $SourceStoreScope = 'LocalMachine';
    $SourceStorename = 'Root';
    $DestStoreScope = 'LocalMachine';
    $DestStoreName = 'WebHosting';

    $Certificate = Get-ChildItem -Path Cert:\LocalMachine\Root | Where-Object { $_.Subject -eq $Subject } | Select -First 1;
    IF($null -ne $Certificate) { RETURN $Certificate; }

    $Certificate = New-SelfSignedCertificate -DnsName $DnsName -CertStoreLocation Cert:\LocalMachine\My -FriendlyName $DnsName;    
 
    Move-Item -Path "Cert:\LocalMachine\My\$($Certificate.Thumbprint)" -Destination "Cert:\LocalMachine\Root" -Force;
     
    $SourceStore = [System.Security.Cryptography.X509Certificates.X509Store]::new('Root', 'LocalMachine');
    $SourceStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly);
 
    $Certificate = $SourceStore.Certificates | Where-Object { $_.Subject -eq $Subject } | Select -First 1; 
   
    $DestStore = [System.Security.Cryptography.X509Certificates.X509Store]::new($DestStoreName, 'LocalMachine');
    $DestStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite);
    $DestStore.Add($Certificate); 
 
    $SourceStore.Close();
    $DestStore.Close();
    Return $Certificate;
}