Unpacking Software Livestream

Join our monthly Unpacking Software livestream to hear about the latest news, chat and opinion on packaging, software deployment and lifecycle management!

Learn More

Chocolatey Product Spotlight

Join the Chocolatey Team on our regular monthly stream where we put a spotlight on the most recent Chocolatey product releases. You'll have a chance to have your questions answered in a live Ask Me Anything format.

Learn More

Chocolatey Coding Livestream

Join us for the Chocolatey Coding Livestream, where members of our team dive into the heart of open source development by coding live on various Chocolatey projects. Tune in to witness real-time coding, ask questions, and gain insights into the world of package management. Don't miss this opportunity to engage with our team and contribute to the future of Chocolatey!

Learn More

Calling All Chocolatiers! Whipping Up Windows Automation with Chocolatey Central Management

Webinar from
Wednesday, 17 January 2024

We are delighted to announce the release of Chocolatey Central Management v0.12.0, featuring seamless Deployment Plan creation, time-saving duplications, insightful Group Details, an upgraded Dashboard, bug fixes, user interface polishing, and refined documentation. As an added bonus we'll have members of our Solutions Engineering team on-hand to dive into some interesting ways you can leverage the new features available!

Watch On-Demand
Chocolatey Community Coffee Break

Join the Chocolatey Team as we discuss all things Community, what we do, how you can get involved and answer your Chocolatey questions.

Watch The Replays
Chocolatey and Intune Overview

Webinar Replay from
Wednesday, 30 March 2022

At Chocolatey Software we strive for simple, and teaching others. Let us teach you just how simple it could be to keep your 3rd party applications updated across your devices, all with Intune!

Watch On-Demand
Chocolatey For Business. In Azure. In One Click.

Livestream from
Thursday, 9 June 2022

Join James and Josh to show you how you can get the Chocolatey For Business recommended infrastructure and workflow, created, in Azure, in around 20 minutes.

Watch On-Demand
The Future of Chocolatey CLI

Livestream from
Thursday, 04 August 2022

Join Paul and Gary to hear more about the plans for the Chocolatey CLI in the not so distant future. We'll talk about some cool new features, long term asks from Customers and Community and how you can get involved!

Watch On-Demand
Hacktoberfest Tuesdays 2022

Livestreams from
October 2022

For Hacktoberfest, Chocolatey ran a livestream every Tuesday! Re-watch Cory, James, Gary, and Rain as they share knowledge on how to contribute to open-source projects such as Chocolatey CLI.

Watch On-Demand

Downloads:

31,994

Downloads of v 1.0.0.75:

693

Last Update:

02 Dec 2014

Package Maintainer(s):

Software Author(s):

  • SEEK Ltd.

Tags:

admin dsc

SEEK DSC WebAdministration

This is not the latest version of SEEK DSC WebAdministration available.

  • 1
  • 2
  • 3

1.0.0.75 | Updated: 02 Dec 2014

Downloads:

31,994

Downloads of v 1.0.0.75:

693

Software Author(s):

  • SEEK Ltd.

Tags:

admin dsc

SEEK DSC WebAdministration 1.0.0.75

This is not the latest version of SEEK DSC WebAdministration available.

  • 1
  • 2
  • 3

Some Checks Have Failed or Are Not Yet Complete

Not All Tests Have Passed


Validation Testing Unknown


Verification Testing Unknown


Scan Testing Successful:

No detections found in any package files

Details
Learn More

Deployment Method: Individual Install, Upgrade, & Uninstall

To install SEEK DSC WebAdministration, run the following command from the command line or from PowerShell:

>

To upgrade SEEK DSC WebAdministration, run the following command from the command line or from PowerShell:

>

To uninstall SEEK DSC WebAdministration, run the following command from the command line or from PowerShell:

>

Deployment Method:

NOTE

This applies to both open source and commercial editions of Chocolatey.

1. Enter Your Internal Repository Url

(this should look similar to https://community.chocolatey.org/api/v2/)


2. Setup Your Environment

1. Ensure you are set for organizational deployment

Please see the organizational deployment guide

2. Get the package into your environment

  • Open Source or Commercial:
    • Proxy Repository - Create a proxy nuget repository on Nexus, Artifactory Pro, or a proxy Chocolatey repository on ProGet. Point your upstream to https://community.chocolatey.org/api/v2/. Packages cache on first access automatically. Make sure your choco clients are using your proxy repository as a source and NOT the default community repository. See source command for more information.
    • You can also just download the package and push it to a repository Download

3. Copy Your Script

choco upgrade seek-dsc-webadministration -y --source="'INTERNAL REPO URL'" --version="'1.0.0.75'" [other options]

See options you can pass to upgrade.

See best practices for scripting.

Add this to a PowerShell script or use a Batch script with tools and in places where you are calling directly to Chocolatey. If you are integrating, keep in mind enhanced exit codes.

If you do use a PowerShell script, use the following to ensure bad exit codes are shown as failures:


choco upgrade seek-dsc-webadministration -y --source="'INTERNAL REPO URL'" --version="'1.0.0.75'" 
$exitCode = $LASTEXITCODE

Write-Verbose "Exit code was $exitCode"
$validExitCodes = @(0, 1605, 1614, 1641, 3010)
if ($validExitCodes -contains $exitCode) {
  Exit 0
}

Exit $exitCode

- name: Install seek-dsc-webadministration
  win_chocolatey:
    name: seek-dsc-webadministration
    version: '1.0.0.75'
    source: INTERNAL REPO URL
    state: present

See docs at https://docs.ansible.com/ansible/latest/modules/win_chocolatey_module.html.


chocolatey_package 'seek-dsc-webadministration' do
  action    :install
  source   'INTERNAL REPO URL'
  version  '1.0.0.75'
end

See docs at https://docs.chef.io/resource_chocolatey_package.html.


cChocoPackageInstaller seek-dsc-webadministration
{
    Name     = "seek-dsc-webadministration"
    Version  = "1.0.0.75"
    Source   = "INTERNAL REPO URL"
}

Requires cChoco DSC Resource. See docs at https://github.com/chocolatey/cChoco.


package { 'seek-dsc-webadministration':
  ensure   => '1.0.0.75',
  provider => 'chocolatey',
  source   => 'INTERNAL REPO URL',
}

Requires Puppet Chocolatey Provider module. See docs at https://forge.puppet.com/puppetlabs/chocolatey.


4. If applicable - Chocolatey configuration/installation

See infrastructure management matrix for Chocolatey configuration elements and examples.

Package Approved

This package was approved as a trusted package on 02 Dec 2014.

Description

Custom DSC Resources for administration of an IIS web server


lib\cWebAdministration\cWebAdministration.psd1
 
lib\cWebAdministration\DSCResources\SEEK_cBindings\SEEK_cBindings.psm1
Import-Module WebAdministration

function Synchronized
{
    [CmdletBinding()]
    param
    (
        [ValidateNotNullOrEmpty()]
        [ValidatePattern("^[^\\]?")]
        [parameter(Mandatory = $true)]
        [string] $Name,

        [parameter(Mandatory = $true)]
        [ScriptBlock] $ScriptBlock,

        [parameter(Mandatory = $false)]
        [int] $MillisecondsTimeout = 5000,

        [parameter(Mandatory = $false)]
        [boolean] $InitiallyOwned = $false,

        [parameter(Mandatory = $false)]
        [Object[]] $ArgumentList = @(),

        [parameter(Mandatory = $false)]
        [ValidateSet("Global","Local","Session")]
        [Object[]] $Scope = "Global"
    )

    $mutex = New-Object System.Threading.Mutex($InitiallyOwned, "${Scope}\${Name}")
    
    if ($mutex.WaitOne($MillisecondsTimeout)) {
        try {
            Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $ArgumentList
        }
        finally {
            $mutex.ReleaseMutex()
        }
    }
    else { throw "Cannot aquire mutex: $Name"}
}

function Get-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String] $Site
    )

    get-BindingsResource (get-BindingConfigElements $Site) $Site
}

function Test-TargetResource
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String] $Site,

        [ValidateSet("Present","Absent")]
        [System.String]
        $Ensure  = "Present",

        [Microsoft.Management.Infrastructure.CimInstance[]]
        $Bindings = @(),

        [System.Boolean]
        $Clear = $false
    )

    $currentCimBindings = get-CurrentCimBindings $Site
    $commonCimBindings = select-CommonCimBindings (new-CimBindingsWithBindingInformation $Bindings) $currentCimBindings

    if (($Ensure -eq "Absent") -and $Clear) { return (@($currentCimBindings).count -eq 0) -and (@($commonCimBindings).count -eq 0) }
    if ($Ensure -eq "Absent") { return @($commonCimBindings).count -eq 0 }

    if ($Clear) { return $currentCimBindings.count -eq $commonCimBindings.count }
    return (@($commonCimBindings).count -eq $Bindings.count)
}

function Set-TargetResource
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String] $Site,

        [ValidateSet("Present","Absent")]
        [System.String]
        $Ensure  = "Present",

        [Microsoft.Management.Infrastructure.CimInstance[]]
        $Bindings = @(),

        [System.Boolean]
        $Clear = $false
    )



    $newCimBindings = new-CimBindingsForSite $Ensure $Bindings $Site $Clear
    $sitePath = $("IIS:\Sites\${Site}")
    Synchronized -Name "IIS" -ArgumentList $sitePath, (new-BindingsValue $newCimBindings) {
        param($path, $bindings)
        Set-ItemProperty -Path $path -Name bindings -Value $bindings
    }
    $newCimBindings | Where-Object Protocol -eq "https" | ForEach-Object { add-SslCertificateForHttpsCimBinding $_ }

    $protocols = $newCimBindings | Select-Object -ExpandProperty Protocol -Unique
    Synchronized -Name "IIS" -ArgumentList $sitePath, $protocols {
        param($path, $enabledProtocols)
        Set-ItemProperty $path -Name EnabledProtocols -Value ($enabledProtocols -join ',')
    }
}

function New-CimBinding
{
    [CmdletBinding()]
    param
    (
        [System.String] $BindingInformation,
        [System.String] $Protocol
    )

    New-CimInstance -ClassName SEEK_cBinding -ClientOnly -Property @{
        BindingInformation = $BindingInformation
        Protocol = $Protocol
    }
}

function New-HttpCimBinding {
    [CmdletBinding()]
    param
    (
        [System.String] $HostName,
        [System.String] $IPAddress,
        [System.UInt16] $Port
    )

    New-CimInstance -ClassName SEEK_cBinding -ClientOnly -Property @{
        HostName = $HostName
        IPAddress = $IPAddress
        Port = $Port
        Protocol = "http"
    }
}

function New-HttpsCimBinding {
    [CmdletBinding()]
    param
    (
        [System.String] $CertificatePath,
        [System.String] $CertificateSubject,
        [System.String] $IPAddress,
        [System.UInt16] $Port
    )

    New-CimInstance -ClassName SEEK_cBinding -ClientOnly -Property @{
        CertificatePath = $CertificatePath
        CertificateSubject = $CertificateSubject
        IPAddress = $IPAddress
        Port = $Port
        Protocol = "https"
    }
}

function add-SslCertificateForHttpsCimBinding
{
    [CmdletBinding()]
    param($httpsCimBinding)

    $ip = get-HttpSysIp $httpsCimBinding.IPAddress
    $path = $httpsCimBinding.CertificatePath
    $port = $httpsCimBinding.Port
    $thumbprint = get-CertificateThumbprint $httpsCimBinding

    $sslBindingPath = "IIS:\SslBindings\${ip}!${port}"

    if (Test-Path $sslBindingPath) {
        Write-Verbose "SSL binding for endpoint ${ip}:${port} alerady exists."
        Write-Verbose "Clobbering with new SSL binding."
        Remove-Item $sslBindingPath
    }

    Get-Item "${path}\${thumbprint}" | New-Item $sslBindingPath
}

function compare-CimBindings {
    [CmdletBinding()]
    param
    (
        $cimBinding,
        $otherCimBinding
    )

    $matchingBindingInformation = $cimBinding.BindingInformation -eq $otherCimBinding.BindingInformation
    $matchingProtocol = $cimBinding.Protocol -eq $otherCimBinding.Protocol

    if (-not ($matchingBindingInformation -and $matchingProtocol)) { return $false }

    $true
}

function containsCimBinding {
    [CmdletBinding()]
    param($bindings, $binding)

    $result = $false
    $bindings | ForEach-Object { if(compare-CimBindings $_ $binding) { $result = $true } }
    $result
}

function get-BindingConfigElements
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String] $Site
    )

    (Get-ItemProperty "IIS:\Sites\${Site}" -Name bindings)
}

function get-BindingInformation
{
    [CmdletBinding()]
    param($binding)

    if($binding.BindingInformation -ne $null) { return $binding.BindingInformation }

    switch ($binding.Protocol)
    {
        "http"
        { get-HttpBindingInformation $binding }
        "https"
        { get-HttpsBindingInformation $binding }
    }
}

function get-BindingsResource
{
    [CmdletBinding()]
    param($bindingConfigElements, $site)

    $result = @{
        Bindings = @()
        Ensure = "Absent"
        Site = $site
    }

    if($bindingConfigElements.count -ne 0) {
        $result.Bindings = new-CimBindingsFromConfigElements $bindingConfigElements
        $result.Ensure = "Present"
    }

    $result
}

function get-CertificateThumbprint
{
    [CmdletBinding()]
    param($httpsCimBinding)

    (Get-ChildItem -Path $httpsCimBinding.CertificatePath | Where Subject -eq $httpsCimBinding.CertificateSubject).Thumbprint
}

function get-CurrentCimBindings
{
    [CmdletBinding()]
    param($site)

    (Get-TargetResource -Site $site).Bindings
}

function get-HttpBindingInformation
{
    [CmdletBinding()]
    param($httpBinding)

    $hostName = $httpBinding.HostName
    $ipAddress = $httpBinding.IPAddress
    $port = $httpBinding.Port

    "${ipAddress}:${port}:${hostName}"
}

function get-HttpsBindingInformation
{
    [CmdletBinding()]
    param($httpsBinding)

    $ipAddress = $httpsBinding.IPAddress
    $port = $httpsBinding.Port

    "${ipAddress}:${port}:"
}

function get-HttpSysIp
{
    [CmdletBinding()]
    param($ip)

    if ($ip -eq "*") { return "0.0.0.0" }
    $ip
}

function new-CimBindingsForSite {
    [CmdletBinding()]
    param($ensure, $cimBindings, $site, $clear = $false)

    $currentCimBindings = @()

    if (!$clear) { $currentCimBindings = @(get-CurrentCimBindings $site) }

    if ($Ensure -eq "Absent") {
        return select-FromCimBindingsWithoutCimBindings -From $currentCimBindings -Without $cimBindings
    }

    $newBindings = $currentCimBindings
    $newBindings += $cimBindings
    return $newBindings
}

function new-BindingsValue
{
    [CmdletBinding()]
    param($bindings)

    (new-CimBindingsWithBindingInformation $bindings) | ForEach-Object {
        @{
            bindingInformation = $_.BindingInformation
            protocol = $_.Protocol
        }
    }
}

function new-CimBindingsWithBindingInformation
{
    [CmdletBinding()]
    param($cimBindings)

    $cimBindings | ForEach-Object {
        new-CimBindingFromHash @{
            BindingInformation = get-BindingInformation $_
            CertificatePath = $_.CertificatePath
            CertificateSubject = $_.CertificateSubject
            HostName = $_.HostName
            IPAddress = $_.IPAddress
            Port = $_.Port
            Protocol = $_.Protocol
        }
    }
}

function new-CimBindingFromConfigElement
{
    [CmdletBinding()]
    param($bindingConfigElement)

    $bindingHash = @{
        BindingInformation = $bindingConfigElement.bindingInformation
        Protocol = $bindingConfigElement.protocol
    }

    if ($bindingHash.Protocol -eq "https") {
        $bindingHash.CertificatePath = $bindingConfigElement.certificatePath
        $bindingHash.CertificateSubject = $bindingConfigElement.certificateSubject
    }

    new-CimBindingFromHash $bindingHash
}

function new-CimBindingsFromConfigElements
{
    [CmdletBinding()]
    param($bindingConfigElements)

    $bindingConfigElements.collection | ForEach-Object { new-CimBindingFromConfigElement $_ }
}

function new-CimBindingFromHash
{
    [CmdletBinding()]
    param($bindingHash)

    New-CimInstance -ClassName SEEK_cBinding -ClientOnly -Property (new-HashWithoutNullValues $bindingHash)
}

function new-HashWithoutNullValues
{
    [CmdletBinding()]
    param($hashtable)

    $result = @{}
    $hashtable.Keys | Where { $hashtable.$_ -ne $null } | ForEach { $result.$_ = ($hashtable.$_) }
    $result
}

function select-CommonCimBindings
{
    [CmdletBinding()]
    param($cimBindings, $otherCimBindings)

    $cimBindings | Where-Object { containsCimBinding $otherCimBindings $_ }
}

function select-FromCimBindingsWithoutCimBindings
{
    [CmdletBinding()]
    param($from, $without)

    $from | Where-Object { -not (containsCimBinding $without $_) }
}

Export-ModuleMember -Function *-TargetResource

lib\cWebAdministration\DSCResources\SEEK_cBindings\SEEK_cBindings.schema.mof
 
lib\cWebAdministration\DSCResources\SEEK_cFeatureDelegation\SEEK_cFeatureDelegation.psm1
Import-Module WebAdministration

function Get-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]$Section
    )

    $configuration = Get-WebConfiguration -Filter $Section -PSPath "IIS:"

    if($configuration -ne $null -and $configuration.OverrideMode -eq "Allow") {
        return @{
            Ensure = "Present"
            Section = $Section
        }
    }

    return @{Ensure = "Absent"}
}

function Test-TargetResource
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]
        $Section,

        [ValidateSet("Present","Absent")]
        [System.String]
        $Ensure  = "Present"
    )

    $actualState = Get-TargetResource -Section $Section

    if ($Ensure -eq $actualState.Ensure) { return $true }

    return $false
}

function Set-TargetResource
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]
        $Section,

        [ValidateSet("Present","Absent")]
        [System.String]
        $Ensure  = "Present"
    )

    if($Ensure -eq "Absent") {
        $overrideMode = "Deny"
    } 
    else {
        $overrideMode = "Allow"
    }

    Set-WebConfiguration -Filter $Section -PSPath "IIS:" -MetaData "overrideMode" -Value $overrideMode
}

Export-ModuleMember -Function *-TargetResource
lib\cWebAdministration\DSCResources\SEEK_cFeatureDelegation\SEEK_cFeatureDelegation.schema.mof
 
lib\cWebAdministration\DSCResources\SEEK_cWebAppAndPool\SEEK_cWebAppAndPool.psd1
 
lib\cWebAdministration\DSCResources\SEEK_cWebAppAndPool\SEEK_cWebAppAndPool.schema.psm1
Configuration cWebAppAndPool
{
    param
    (
        [String]$Name,
        [String[]]$WebSiteName,
        [String]$AppPoolName,
        [HashTable]$AppPoolCredentials,
        [String]$AppPoolManagedRuntimeVersion = "v4.0",
        [String]$AppPoolIdentityType = "SpecificUser",
        [String]$AppPoolManagedPipelineMode = "Integrated",
        [String]$AppPoolEnable32BitAppOnWin64 = "false",
        [HashTable]$AuthenticationInfo = @{Anonymous = "true"; Basic = "false"; Digest = "false"; Windows = "false"},
        [String]$PhysicalPath
    )

    Import-DscResource -Module cWebAdministration -Name SEEK_cWebAppPool, SEEK_cWebApplication

    cWebAppPool AppPool
    {
        Name = $AppPoolName
        ApplicationName = $Name
        UserName = $AppPoolCredentials.Username
        Password = $AppPoolCredentials.Password
        ManagedRuntimeVersion = $AppPoolManagedRuntimeVersion
        IdentityType = $AppPoolIdentityType
        ManagedPipelineMode = $AppPoolManagedPipelineMode
        Enable32BitAppOnWin64 = $AppPoolEnable32BitAppOnWin64
    }

    Foreach ($website in @($WebSiteName))
    {
        cWebApplication "${website}WebApplication"
        {
            Name = $Name
            Website = $website
            WebAppPool =  $AppPoolName
            PhysicalPath = $PhysicalPath
            AuthenticationInfo = SEEK_cWebAuthenticationInformation
                                {
                                    Anonymous = $AuthenticationInfo.Anonymous
                                    Basic = $AuthenticationInfo.Basic
                                    Digest = $AuthenticationInfo.Digest
                                    Windows = $AuthenticationInfo.Windows
                                }
            DependsOn = @("[cWebAppPool]AppPool")
        }
    }
}
lib\cWebAdministration\DSCResources\SEEK_cWebApplication\SEEK_cWebApplication.psm1
Import-Module WebAdministration

function Synchronized
{
    [CmdletBinding()]
    param
    (
        [ValidateNotNullOrEmpty()]
        [ValidatePattern("^[^\\]?")]
        [parameter(Mandatory = $true)]
        [string] $Name,

        [parameter(Mandatory = $true)]
        [ScriptBlock] $ScriptBlock,

        [parameter(Mandatory = $false)]
        [int] $MillisecondsTimeout = 5000,

        [parameter(Mandatory = $false)]
        [boolean] $InitiallyOwned = $false,

        [parameter(Mandatory = $false)]
        [Object[]] $ArgumentList = @(),

        [parameter(Mandatory = $false)]
        [ValidateSet("Global","Local","Session")]
        [Object[]] $Scope = "Global"
    )

    $mutex = New-Object System.Threading.Mutex($InitiallyOwned, "${Scope}\${Name}")
    
    if ($mutex.WaitOne($MillisecondsTimeout)) {
        try {
            Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $ArgumentList
        }
        finally {
            $mutex.ReleaseMutex()
        }
    }
    else { throw "Cannot aquire mutex: $Name"}
}

function Get-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]$Website,

        [parameter(Mandatory = $true)]
        [System.String]$Name
    )

    $webApplication = Find-UniqueWebApplication -Site $Website -Name $Name
    if ($webApplication -ne $null)
    {
        return @{
            Website = $Website
            Name = $Name
            WebAppPool = $webApplication.ApplicationPool
            PhysicalPath = $webApplication.PhysicalPath
            Ensure = "Present"
            AuthenticationInfo = Get-AuthenticationInfo -Website $Website -ApplicationName $Name
            SslFlags = (Get-SslFlags -Location "${Website}/${Name}")
            EnabledProtocols = (Get-ItemProperty "IIS:\Sites\${Website}\${Name}" -Name "EnabledProtocols").Value
        }
    }

    return @{
        Website = $Website
        Name = $Name
        WebAppPool = $null
        PhysicalPath = $null
        Ensure = "Absent"
        AuthenticationInfo = $null
        SslFlags = $null
        EnabledProtocols = $null
    }
}


function Set-TargetResource
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]$Website,

        [parameter(Mandatory = $true)]
        [System.String]$Name,

        [parameter(Mandatory = $true)]
        [System.String]$WebAppPool,

        [parameter(Mandatory = $true)]
        [System.String]$PhysicalPath,

        [ValidateNotNull()]
        [string]$SslFlags = "",

        [ValidateSet("Present","Absent")]
        [System.String]$Ensure = "Present",

        [System.String] $EnabledProtocols,

        [Parameter(Mandatory=$false, HelpMessage="Obsolete")]
        [System.String] $AutoStartMode,

        [Microsoft.Management.Infrastructure.CimInstance]$AuthenticationInfo
    )

    if ($AuthenticationInfo -eq $null) { $AuthenticationInfo = Get-DefaultAuthenticationInfo }

    $webApplication = Find-UniqueWebApplication -Site $Website -Name $Name
    $webappPath = "IIS:\Sites\${Website}\${Name}"
    if ($Ensure -eq "Present")
    {

        if ($webApplication -eq $null)
        {
            Write-Verbose "Creating new Web application $Name."
            New-WebApplication -Site $Website -Name $Name -PhysicalPath $PhysicalPath -ApplicationPool $WebAppPool
        }
        else
        {
            if ($webApplication.physicalPath -ne $PhysicalPath)
            {
                Write-Verbose "Updating physical path for Web application $Name."
                Synchronized -Name "IIS" -ArgumentList $webappPath, $physicalPath -ScriptBlock {
                    param($path, $physicalPath)
                    Set-ItemProperty -Path $path -Name physicalPath -Value $physicalPath
                }
            }
            if ($webApplication.applicationPool -ne $ApplicationPool)
            {
                Write-Verbose "Updating physical path for Web application $Name."
                Synchronized -Name "IIS" -ArgumentList $webappPath, $WebAppPool -ScriptBlock {
                    param($path, $applicationPool)
                    Set-ItemProperty -Path $path -Name applicationPool -Value $applicationPool
                }
            }
        }

        Set-AuthenticationInfo -Website $Website -ApplicationName $Name -AuthenticationInfo $AuthenticationInfo -ErrorAction Stop
        Set-WebConfiguration -Location "${Website}/${Name}" -Filter 'system.webserver/security/access' -Value $SslFlags

        if ($EnabledProtocols) {
            Synchronized -Name "IIS" -ArgumentList $webappPath, $EnabledProtocols -ScriptBlock {
                param($path, $enabledProtocols)
                Set-ItemProperty -Path $path -Name EnabledProtocols -Value $enabledProtocols
            }
        }
    }
    elseif (($Ensure -eq "Absent") -and ($webApplication -ne $null))
    {
        Write-Verbose "Removing existing Web Application $Name."
        Remove-WebApplication -Site $Website -Name $Name
    }
}


function Test-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]$Website,

        [parameter(Mandatory = $true)]
        [System.String]$Name,

        [parameter(Mandatory = $true)]
        [System.String]$WebAppPool,

        [parameter(Mandatory = $true)]
        [System.String]$PhysicalPath,

        [ValidateNotNull()]
        [string]$SslFlags = "",

        [ValidateSet("Present","Absent")]
        [System.String]$Ensure = "Present",

        [System.String] $EnabledProtocols,

        [Parameter(Mandatory=$false, HelpMessage="Obsolete")]
        [System.String] $AutoStartMode,

        [Microsoft.Management.Infrastructure.CimInstance]$AuthenticationInfo
    )

    if ($AuthenticationInfo -eq $null) { $AuthenticationInfo = Get-DefaultAuthenticationInfo }

    $webApplication = Get-TargetResource -Website $Website -Name $Name

    if($Ensure -eq "Present")
    {
        $enabledProtocolsMatch = if ($EnabledProtocols) { $webApplication.EnabledProtocols -eq $EnabledProtocols } else { $true }

        if(($webApplication.Ensure -eq $Ensure) `
            -and ($webApplication.PhysicalPath -eq $PhysicalPath) `
            -and ($webApplication.WebAppPool -eq $WebAppPool) `
            -and ((Get-SslFlags -Location "${Website}/${Name}") -eq $SslFlags) `
            -and (Test-AuthenticationInfo -Website $Website -ApplicationName $Name -AuthenticationInfo $AuthenticationInfo) `
            -and $enabledProtocolsMatch)
        {
            return $true
        }
    }
    elseif($webApplication.Ensure -eq $Ensure)
    {
        return $true
    }

    return $false
}

function Find-UniqueWebApplication
{
    Param
    (
        [parameter(Mandatory = $true)]
        [System.String]$Site,

        [parameter(Mandatory = $true)]
        [System.String]$Name
    )

    $webApplications = @(Get-WebApplication -Site $Site -Name $Name)

    if ($webApplications.Count -gt 1)
    {
        throw "Multiple web applications found for ""${Site}/${Name}"""
    }

    return $webApplications[0]
}

function Test-AuthenticationEnabled
{
    [OutputType([System.Boolean])]
    Param
    (
        [parameter(Mandatory = $true)]
        [System.String]$WebSite,

        [parameter(Mandatory = $true)]
        [System.String]$ApplicationName,

        [parameter(Mandatory = $true)]
        [ValidateSet("Anonymous","Basic","Digest","Windows")]
        [System.String]$Type
    )


    $prop = Get-WebConfigurationProperty `
        -Filter /system.WebServer/security/authentication/${Type}Authentication `
        -Name enabled `
        -Location "${WebSite}/${ApplicationName}"
    return $prop.Value
}

function Set-Authentication
{
    Param
    (
        [parameter(Mandatory = $true)]
        [System.String]$WebSite,

        [parameter(Mandatory = $true)]
        [System.String]$ApplicationName,

        [parameter(Mandatory = $true)]
        [ValidateSet("Anonymous","Basic","Digest","Windows")]
        [System.String]$Type,

        [System.Boolean]$Enabled
    )

    Set-WebConfigurationProperty -Filter /system.WebServer/security/authentication/${Type}Authentication `
        -Name enabled `
        -Value $Enabled `
        -Location "${WebSite}/${Name}"
}

function Get-AuthenticationInfo
{
    [OutputType([Microsoft.Management.Infrastructure.CimInstance])]
    Param
    (
        [parameter(Mandatory = $true)]
        [System.String]$WebSite,

        [parameter(Mandatory = $true)]
        [System.String]$ApplicationName
    )

    $authenticationProperties = @{}
    foreach ($type in @("Anonymous", "Basic", "Digest", "Windows"))
    {
        $authenticationProperties[$type] = [string](Test-AuthenticationEnabled -Website $Website -ApplicationName $Name -Type $type)
    }

    return New-CimInstance -ClassName SEEK_cWebAuthenticationInformation -ClientOnly -Property $authenticationProperties
}

function Test-AuthenticationInfo
{
    [OutputType([System.Boolean])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]$Website,

        [parameter(Mandatory = $true)]
        [System.String]$ApplicationName,

        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [Microsoft.Management.Infrastructure.CimInstance]$AuthenticationInfo
    )

    $result = $true

    foreach ($type in @("Anonymous", "Basic", "Digest", "Windows"))
    {

        $expected = $AuthenticationInfo.CimInstanceProperties[$type].Value
        $actual = Test-AuthenticationEnabled -Website $Website -ApplicationName $ApplicationName -Type $type
        if ($expected -ne $actual)
        {
            $result = $false
            break
        }
    }

    return $result
}

function Set-AuthenticationInfo
{
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]$WebSite,

        [parameter(Mandatory = $true)]
        [System.String]$ApplicationName,

        [parameter()]
        [ValidateNotNullOrEmpty()]
        [Microsoft.Management.Infrastructure.CimInstance]$AuthenticationInfo
    )

    foreach ($type in @("Anonymous", "Basic", "Digest", "Windows"))
    {
        $enabled = ($AuthenticationInfo.CimInstanceProperties[$type].Value -eq $true)
        Set-Authentication -Website $Website -ApplicationName $ApplicationName -Type $type -Enabled $enabled
    }
}

function Get-DefaultAuthenticationInfo
{
    New-CimInstance -ClassName SEEK_cWebAuthenticationInformation `
        -ClientOnly `
        -Property @{Anonymous="false";Basic="false";Digest="false";Windows="false"}
}

function Get-SslFlags
{
    [CmdletBinding()]
    param
    (
        [System.String]$Location
    )

    $sslFlags = Get-WebConfiguration -PSPath IIS:\Sites -Location $Location -Filter 'system.webserver/security/access' | % { $_.sslFlags }
    $sslFlags = if ($sslFlags -eq $null) { "" } else { $sslFlags }
    return $sslFlags
}

Export-ModuleMember -Function *-TargetResource

lib\cWebAdministration\DSCResources\SEEK_cWebApplication\SEEK_cWebApplication.schema.mof
 
lib\cWebAdministration\DSCResources\SEEK_cWebAppPool\SEEK_cWebAppPool.psm1
Import-Module WebAdministration

function Get-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]
        $Name,

        [parameter(Mandatory = $true)]
        [System.String]
        $ApplicationName
    )

    $AppPool = Get-AppPool($Name)
    if($AppPool -eq $null)
    {
        return @{Name = $Name; ApplicationName = $ApplicationName; Ensure = "Absent"; State = "Stopped"}
    }

    $returnValue = @{
        Name   = $Name
        ApplicationName = $ApplicationName
        Ensure = "Present"
        State  = $AppPool.State
        managedRuntimeVersion = $AppPool.managedRuntimeVersion
        managedPipelineMode = $AppPool.managedPipelineMode
        enable32BitAppOnWin64 = $AppPool.enable32BitAppOnWin64
        processModel = @{
            identityType = $AppPool.processModel.identityType
            userName = $AppPool.processModel.userName
            password = $AppPool.processModel.password
        }
    }

    return $returnValue
}


function Set-TargetResource
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]
        $Name,

        [parameter(Mandatory = $true)]
        [System.String]
        $ApplicationName,

        [ValidateSet("Present","Absent")]
        [System.String]
        $Ensure  = "Present",

        [ValidateSet("Started","Stopped")]
        [System.String]
        $State = "Started",

        [ValidateSet("v2.0","v4.0", "")]
        [System.String]
        $ManagedRuntimeVersion = "v4.0",

        [ValidateSet("Integrated","Classic")]
        [System.String]
        $ManagedPipelineMode = "Integrated",

        [ValidateSet("true","false")]
        [System.String]
        $Enable32BitAppOnWin64 = "false",

        [ValidateSet("ApplicationPoolIdentity","LocalSystem","LocalService","NetworkService","SpecificUser")]
        [System.String]
        $IdentityType = "SpecificUser",

        [parameter(Mandatory = $true)]
        [System.String]
        $UserName,

        [parameter(Mandatory = $true)]
        [System.String]
        $Password
    )

    if($Ensure -eq "Absent")
    {
        Write-Verbose("Removing the Web App Pool")
        Remove-WebAppPool $Name
    }
    else
    {
        $AppPool = Get-AppPool($Name)
        if($AppPool -eq $null)
        {
            Write-Verbose("Creating the Web App Pool")
            $AppPool = New-WebAppPool $Name
        }

        $AppPool.managedRuntimeVersion = $ManagedRuntimeVersion
        $AppPool.managedPipelineMode = $ManagedPipelineMode
        $AppPool.enable32BitAppOnWin64 = $Enable32BitAppOnWin64
        $AppPool.processModel.identityType = $IdentityType
        $AppPool.processModel.userName = $UserName
        $AppPool.processModel.password = $Password
        $AppPool | Set-Item

        if($AppPool.State -ne $State)
        {
            Execute-RequiredState -Name $Name -State $State
        }
    }
}


function Test-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]
        $Name,

        [parameter(Mandatory = $true)]
        [System.String]
        $ApplicationName,

        [ValidateSet("Present","Absent")]
        [System.String]
        $Ensure  = "Present",

        [ValidateSet("Started","Stopped")]
        [System.String]
        $State = "Started",

        [ValidateSet("v2.0","v4.0", "")]
        [System.String]
        $ManagedRuntimeVersion = "v4.0",

        [ValidateSet("Integrated","Classic")]
        [System.String]
        $ManagedPipelineMode = "Integrated",

        [ValidateSet("true","false")]
        [System.String]
        $Enable32BitAppOnWin64 = "false",

        [ValidateSet("ApplicationPoolIdentity","LocalSystem","LocalService","NetworkService","SpecificUser")]
        [System.String]
        $IdentityType = "SpecificUser",

        [parameter(Mandatory = $true)]
        [System.String]
        $UserName,

        [parameter(Mandatory = $true)]
        [System.String]
        $Password
    )
    $WebAppPool = Get-TargetResource -Name $Name -ApplicationName $ApplicationName

    if($Ensure -eq "Present")
    {
        if($WebAppPool.Ensure -eq $Ensure`
         -and $WebAppPool.State -eq $state`
         -and $WebAppPool.ManagedRuntimeVersion -eq $ManagedRuntimeVersion`
         -and $WebAppPool.ManagedPipelineMode -eq $ManagedPipelineMode`
         -and $WebAppPool.Enable32BitAppOnWin64.toString() -eq $Enable32BitAppOnWin64`
         -and $WebAppPool.ProcessModel.IdentityType -eq $IdentityType`
         -and $WebAppPool.ProcessModel.UserName -eq $UserName`
         -and $WebAppPool.ProcessModel.Password -eq $Password)
        {
            return $true
        }
    }
    elseif($WebAppPool.Ensure -eq $Ensure)
    {
        return $true
    }

    return $false
}


function Get-AppPool([string] $Name)
{
    return $AppPool = Get-Item -Path "IIS:\AppPools\*" | ? {$_.name -eq $Name}
}


function Execute-RequiredState([string] $Name, [string] $State)
{
    if($State -eq "Started")
    {
        Write-Verbose("Starting the Web App Pool")
        Start-WebAppPool -Name $Name
    }
    else
    {
        Write-Verbose("Stopping the Web App Pool")
        Stop-WebAppPool -Name $Name
    }
}

Export-ModuleMember -Function *-TargetResource
lib\cWebAdministration\DSCResources\SEEK_cWebAppPool\SEEK_cWebAppPool.schema.mof
 
lib\cWebAdministration\DSCResources\SEEK_cWebsite\SEEK_cWebsite.psm1
Import-Module WebAdministration

data LocalizedData
{
    # culture="en-US"
    ConvertFrom-StringData @'
SetTargetResourceInstallwhatIfMessage=Trying to create website "{0}".
SetTargetResourceUnInstallwhatIfMessage=Trying to remove website "{0}".
WebsiteNotFoundError=The requested website "{0}" is not found on the target machine.
WebsiteDiscoveryFailureError=Failure to get the requested website "{0}" information from the target machine.
WebsiteCreationFailureError=Failure to successfully create the website "{0}".
WebsiteRemovalFailureError=Failure to successfully remove the website "{0}".
WebsiteUpdateFailureError=Failure to successfully update the properties for website "{0}".
WebsiteBindingUpdateFailureError=Failure to successfully update the binding "{0}" for website "{1}".
WebsiteBindingInputInvalidationError=Desired website bindings not valid for website "{0}".
WebsiteCompareFailureError=Failure to successfully compare properties for website "{0}".
WebBindingCertifcateError=Failure to add certificate to web binding. Please make sure that the certificate thumbprint "{0}" is valid.
WebsiteStateFailureError=Failure to successfully set the state of the website {0}.
WebsiteBindingConflictOnStartError = Website "{0}" could not be started due to binding conflict. Ensure that the binding information for this website does not conflict with any existing website's bindings before trying to start it.
'@
}

function Synchronized
{
    [CmdletBinding()]
    param
    (
        [ValidateNotNullOrEmpty()]
        [ValidatePattern("^[^\\]?")]
        [parameter(Mandatory = $true)]
        [string] $Name,

        [parameter(Mandatory = $true)]
        [ScriptBlock] $ScriptBlock,

        [parameter(Mandatory = $false)]
        [int] $MillisecondsTimeout = 5000,

        [parameter(Mandatory = $false)]
        [boolean] $InitiallyOwned = $false,

        [parameter(Mandatory = $false)]
        [Object[]] $ArgumentList = @(),

        [parameter(Mandatory = $false)]
        [ValidateSet("Global","Local","Session")]
        [Object[]] $Scope = "Global"
    )

    $mutex = New-Object System.Threading.Mutex($InitiallyOwned, "${Scope}\${Name}")
    
    if ($mutex.WaitOne($MillisecondsTimeout)) {
        try {
            Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $ArgumentList
        }
        finally {
            $mutex.ReleaseMutex()
        }
    }
    else { throw "Cannot aquire mutex: $Name"}
}

# The Get-TargetResource cmdlet is used to fetch the status of role or Website on the target machine.
# It gives the Website info of the requested role/feature on the target machine.
function Get-TargetResource
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Name
    )

        $getTargetResourceResult = $null;

        $Website = Get-Website | where {$_.Name -eq $Name}

        if ($Website.count -eq 0) # No Website exists with this name.
        {
            $ensureResult = "Absent";
        }
        elseif ($Website.count -eq 1) # A single Website exists with this name.
        {
            $ensureResult = "Present"

            $SslFlags = Get-SslFlags -Location $Name

            [PSObject[]] $Bindings
            $Bindings = (Get-ItemProperty -path IIS:\Sites\$Name -Name Bindings).collection

            $CimBindings = foreach ($binding in $bindings)
            {
                $BindingObject = Get-WebBindingObject -Binding $binding

                if($BindingObject.Protocol -eq "http") {
                    New-CimInstance -ClassName SEEK_cWebBindingInformation -Property @{Port=[System.UInt16]$BindingObject.Port;Protocol=$BindingObject.Protocol;HostName=$BindingObject.HostName;IPAddress=$BindingObject.IPAddress} -ClientOnly
                }
                elseif($BindingObject.Protocol -eq "https") {
                    if (($BindingObject.CertificateThumbprint -eq $null) -or ($BindingObject.CertificateStoreName -eq $null)) {
                        New-CimInstance -ClassName SEEK_cWebBindingInformation -Property @{Port=[System.UInt16]$BindingObject.Port;Protocol=$BindingObject.Protocol;HostName=$BindingObject.HostName;IPAddress=$BindingObject.IPAddress} -ClientOnly
                    }
                    else {
                        New-CimInstance -ClassName SEEK_cWebBindingInformation -Property @{Port=[System.UInt16]$BindingObject.Port;Protocol=$BindingObject.Protocol;HostName=$BindingObject.HostName;IPAddress=$BindingObject.IPAddress;CertificateThumbprint=$BindingObject.CertificateThumbprint;CertificateStoreName=$BindingObject.CertificateStoreName} -ClientOnly
                    }
                }
                elseif($BindingObject.Protocol -eq "net.pipe") {
                    New-CimInstance -ClassName SEEK_cWebBindingInformation -Property @{Protocol=$BindingObject.Protocol;HostName=$BindingObject.HostName} -ClientOnly
                }
                elseif($BindingObject.Protocol -eq "net.tcp") {
                    New-CimInstance -ClassName SEEK_cWebBindingInformation -Property @{Port=[System.UInt16]$BindingObject.Port;Protocol=$BindingObject.Protocol;HostName=$BindingObject.HostName} -ClientOnly
                }
            }

            $CimAuthentication = Get-AuthenticationInfo -Website $Name

        }
        else # Multiple websites with the same name exist. This is not supported and is an error
        {
            ThrowTerminatingError `
                -ErrorId "WebsiteDiscoveryFailure" `
                -ErrorMessage  ($($LocalizedData.WebsiteDiscoveryFailure) -f ${Name}) `
                -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidResult)

        }

        # Add all Website properties to the hash table
        $getTargetResourceResult = @{
                                        Name = $Name
                                        Ensure = $ensureResult
                                        PhysicalPath = $Website.physicalPath
                                        State = $Website.state
                                        ID = $Website.id
                                        SslFlags = $SslFlags
                                        ApplicationPool = $Website.applicationPool
                                        BindingInfo = $CimBindings
                                        AuthenticationInfo = $CimAuthentication
                                        HostFileInfo = $null
                                    }

        return $getTargetResourceResult
}


# The Set-TargetResource cmdlet is used to create, delete or configuure a website on the target machine.
function Set-TargetResource
{
    [CmdletBinding()]
    param
    (
        [ValidateSet("Present", "Absent")]
        [string]$Ensure = "Present",

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$PhysicalPath,

        [ValidateSet("Started", "Stopped")]
        [string]$State = "Started",

        [string]$ApplicationPool,

        [ValidateNotNull()]
        [string]$SslFlags = "",

        [Microsoft.Management.Infrastructure.CimInstance[]]$BindingInfo,

        [Microsoft.Management.Infrastructure.CimInstance[]]$HostFileInfo,

        [Microsoft.Management.Infrastructure.CimInstance]$AuthenticationInfo
    )

    $getTargetResourceResult = $null;

    if($Ensure -eq "Present")
    {
        #Remove Ensure from parameters as it is not needed to create new website
        $Result = $psboundparameters.Remove("Ensure");
        #Remove State parameter form website. Will start the website after configuration is complete
        $Result = $psboundparameters.Remove("State");

        #Remove SslFlags parameter form website.
        #SslFlags will be added to site using separate cmdlet
        $Result = $psboundparameters.Remove("SslFlags");

        #Remove bindings from parameters if they exist
        #Bindings will be added to site using separate cmdlet
        $Result = $psboundparameters.Remove("BindingInfo");

        #Remove authentication settings from parameters if they exist
        #Authentication settings will be added to site using separate cmdlet
        $Result = $psboundparameters.Remove("AuthenticationInfo");

        #Remove host file settings from parameters if they exist
        #Host file settings will be added to site using separate cmdlet
        $Result = $psboundparameters.Remove("HostFileInfo");

        $website = Get-Website | where {$_.Name -eq $Name}


        if($website -ne $null)
        {
            #update parameters as required

            $UpdateNotRequired = $true

            #Update Physical Path if required
            if(ValidateWebsitePath -Name $Name -PhysicalPath $PhysicalPath)
            {
                $UpdateNotRequired = $false
                Synchronized -Name "IIS" -ArgumentList "IIS:\Sites\${Name}", $physicalPath {
                    param($path, $physicalPath)
                    Set-ItemProperty -Path $path -Name physicalPath -Value $physicalPath
                }
                Write-Verbose("Physical path for website $Name has been updated to $PhysicalPath");
            }

            #Update Bindings if required
            if ($BindingInfo -ne $null)
            {
                if(ValidateWebsiteBindings -Name $Name -BindingInfo $BindingInfo)
                {
                    $UpdateNotRequired = $false

                    #Update Bindings
                    UpdateBindings -Name $Name -BindingInfo $BindingInfo

                    Write-Verbose("Bindings for website $Name have been updated.");
                }
            }

            if (!(Test-AuthenticationInfo -Website $Name -AuthenticationInfo $AuthenticationInfo))
            {
                Set-AuthenticationInfo -Website $Name -AuthenticationInfo $AuthenticationInfo
                Write-Verbose ("Authentication information for website $Name has been updated.")
            }

            #Update host entry if required
            if ($HostFileInfo -ne $null)
            {
                if(ValidateHostFileEntry -HostFileInfo $HostFileInfo)
                {
                    UpdateHostFileEntry -HostFileInfo $HostFileInfo

                    Write-Verbose("Hostfile for website $Name has been updated.");
                }
            }

            #Update Application Pool if required
            if(($website.applicationPool -ne $ApplicationPool) -and ($ApplicationPool -ne ""))
            {
                $UpdateNotRequired = $false
                Synchronized -Name "IIS" -ArgumentList "IIS:\Sites\${Name}", $applicationPool {
                    param($path, $applicationPool)
                    Set-ItemProperty -Path $path -Name applicationPool -Value $applicationPool
                }
                Write-Verbose("Application Pool for website $Name has been updated to $ApplicationPool")
            }

            Set-WebConfiguration -PSPath IIS:\Sites -Location $Name -Filter 'system.webserver/security/access' -Value $SslFlags

            #Update State if required
            if($website.state -ne $State -and $State -ne "")
            {
                $UpdateNotRequired = $false
                if($State -eq "Started")
                {
                    # Ensure that there are no other websites with binding information that will conflict with this site before starting
                    $existingSites = Get-Website | Where Name -ne $Name

                    foreach($site in $existingSites)
                    {
                        $siteInfo = Get-TargetResource -Name $site.name

                        foreach ($binding in $BindingInfo)
                        {
                            #Normalize empty IPAddress to "*"
                            if($binding.IPAddress -eq "" -or $binding.IPAddress -eq $null)
                            {
                                $NormalizedIPAddress = "*"
                            }
                            else
                            {
                                $NormalizedIPAddress = $binding.IPAddress
                            }

                            if( !(EnsurePortIPHostUnique -Port $Binding.Port -IPAddress $NormalizedIPAddress -HostName $binding.HostName -BindingInfo $siteInfo.BindingInfo -UniqueInstances 1))
                            {
                                ThrowTerminatingError `
                                    -ErrorId "WebsiteBindingConflictOnStart" `
                                    -ErrorMessage  ($($LocalizedData.WebsiteBindingConflictOnStartError) -f ${Name}) `
                                    -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidResult)
                            }
                        }
                    }

                    try
                    {

                    Start-Website -Name $Name

                    }
                    catch
                    {
                        ThrowTerminatingError `
                            -ErrorId "WebsiteStateFailure" `
                            -ErrorMessage  ($($LocalizedData.WebsiteStateFailureError) -f ${Name}) `
                            -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidResult) `
                            -Exception ($_.exception)
                    }

                }
                else
                {
                    try
                    {

                    Stop-Website -Name $Name

                    }
                    catch
                    {
                        ThrowTerminatingError `
                            -ErrorId "WebsiteStateFailure" `
                            -ErrorMessage  ($($LocalizedData.WebsiteStateFailureError) -f ${Name}) `
                            -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidResult) `
                            -Exception ($_.exception)
                    }
                }

                Write-Verbose("State for website $Name has been updated to $State");

            }

            if($UpdateNotRequired)
            {
                Write-Verbose("Website $Name already exists and properties do not need to be udpated.");
            }


        }
        else #Website doesn't exist so create new one
        {
            try
            {
                #Workaround for bug when there are no websites then New-Website fails
                if ((Get-Website).count -eq 0) {
                    $psboundparameters.Add("Id", 1)
                }
                $Website = New-Website @psboundparameters
                $Result = Stop-Website $Website.name -ErrorAction Stop

                Set-WebConfiguration -PSPath IIS:\Sites -Location $Name -Filter 'system.webserver/security/access' -Value $SslFlags

                #Clear default bindings if new bindings defined and are different
                if($BindingInfo -ne $null)
                {
                    if(ValidateWebsiteBindings -Name $Name -BindingInfo $BindingInfo)
                    {
                        UpdateBindings -Name $Name -BindingInfo $BindingInfo

                        Write-Verbose ("Binding information for website $Name added")
                    }
                }

                Write-Verbose ("Begin Authentication information update for website $Name, $AuthenticationInfo")

                Set-AuthenticationInfo -Website $Name -AuthenticationInfo $AuthenticationInfo

                #Update host entry if required
                if ($HostFileInfo -ne $null)
                {
                  UpdateHostFileEntry -HostFileInfo $HostFileInfo

                  Write-Verbose("Hostfile for website $Name has been updated.")
                }

                Write-Verbose("successfully created website $Name")

                #Start site if required
                if($State -eq "Started")
                {
                    #Wait 1 sec for bindings to take effect
                    #I have found that starting the website results in an error if it happens to quickly
                    Start-Sleep -s 1
                    Start-Website -Name $Name -ErrorAction Stop
                }

                Write-Verbose("successfully started website $Name")
            }
            catch
            {
                ThrowTerminatingError `
                    -ErrorId "WebsiteCreationFailure" `
                    -ErrorMessage  ($($LocalizedData.FeatureCreationFailureError) -f ${Name}) `
                    -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidResult) `
                    -Exception ($_.exception)
            }
        }
    }
    else #Ensure is set to "Absent" so remove website
    {
        try
        {
            $website = Get-Website | where {$_.Name -eq $Name}
            if($website -ne $null)
            {
                Remove-website -name $Name

                Write-Verbose("Successfully removed Website $Name.")
            }
            else
            {
                Write-Verbose("Website $Name does not exist.")
            }
        }
        catch
        {
            ThrowTerminatingError `
                -ErrorId "WebsiteRemovalFailure" `
                -ErrorMessage  ($($LocalizedData.WebsiteRemovalFailureError) -f ${Name}) `
                -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidResult) `
                -Exception ($_.exception)
        }

    }
}


# The Test-TargetResource cmdlet is used to validate if the role or feature is in a state as expected in the instance document.
function Test-TargetResource
{
    [CmdletBinding()]
    param
    (
        [ValidateSet("Present", "Absent")]
        [string]$Ensure = "Present",

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$PhysicalPath,

        [ValidateSet("Started", "Stopped")]
        [string]$State = "Started",

        [string]$ApplicationPool,

        [ValidateNotNull()]
        [string]$SslFlags = "",

        [Microsoft.Management.Infrastructure.CimInstance[]]$BindingInfo,

        [Microsoft.Management.Infrastructure.CimInstance[]]$HostFileInfo,

        [Microsoft.Management.Infrastructure.CimInstance]$AuthenticationInfo
    )

    $DesiredConfigurationMatch = $true;

    $website = Get-Website | where {$_.Name -eq $Name}
    $Stop = $true

    Do
    {
        #Check Ensure
        if(($Ensure -eq "Present" -and $website -eq $null) -or ($Ensure -eq "Absent" -and $website -ne $null))
        {
            $DesiredConfigurationMatch = $false
            Write-Verbose("The Ensure state for website $Name does not match the desired state.");
            break
        }

        # Only check properties if $website exists
        if ($website -ne $null)
        {
            #Check Physical Path property
            if(ValidateWebsitePath -Name $Name -PhysicalPath $PhysicalPath)
            {
                $DesiredConfigurationMatch = $false
                Write-Verbose("Physical Path of Website $Name does not match the desired state.");
                break
            }

            #Check State
            if($website.state -ne $State -and $State -ne $null)
            {
                $DesiredConfigurationMatch = $false
                Write-Verbose("The state of Website $Name does not match the desired state.");
                break
            }

            #Check Application Pool property
            if(($ApplicationPool -ne "") -and ($website.applicationPool -ne $ApplicationPool))
            {
                $DesiredConfigurationMatch = $false
                Write-Verbose("Application Pool for Website $Name does not match the desired state.");
                break
            }

            if((Get-SslFlags -Location $Name) -ne $SslFlags)
            {
                $DesiredConfigurationMatch = $false
                Write-Verbose("SSL Flags for Website $Name does not match the desired state.");
                break
            }

            #Check Binding properties
            if($BindingInfo -ne $null)
            {
                if(ValidateWebsiteBindings -Name $Name -BindingInfo $BindingInfo)
                {
                    $DesiredConfigurationMatch = $false
                    Write-Verbose("Bindings for website $Name do not mach the desired state.");
                    break
                }
            }

            if (!(Test-AuthenticationInfo -Website $Name -AuthenticationInfo $AuthenticationInfo))
            {
                $DesiredConfigurationMatch = $false
                Write-Verbose("Authentication for website $Name do not mach the desired state.");
                break
            }

            #Check Host file entry properties
            if($HostFileInfo -ne $null)
            {
                if(ValidateHostFileEntry -HostFileInfo $HostFileInfo)
                {
                    $DesiredConfigurationMatch = $false
                    Write-Verbose("Host file entries for website $Name do not mach the desired state.");
                    break
                }
            }
        }

        $Stop = $false
    }
    While($Stop)

    $DesiredConfigurationMatch;
}

#region HelperFunctions

function ValidateHostFileEntry
{
    [CmdletBinding()]
    param
    (
        [parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $HostFileInfo
    )

    $result = $true

    $hostFile = [Environment]::SystemDirectory + "\drivers\etc\hosts"

    foreach($aHostFileInfo in $HostFileInfo)
    {
        $HostEntryIPAddress = $aHostFileInfo.CimInstanceProperties["HostIpAddress"].Value
        $HostEntryName = $aHostFileInfo.CimInstanceProperties["HostEntryName"].Value
        $RequireHostFileEntry = [bool]::Parse([string]$aHostFileInfo.CimInstanceProperties["RequireHostFileEntry"].Value)

        if ($RequireHostFileEntry)
        {
            if (-not (Select-String $hostFile -pattern "^${HostEntryIPAddress}\s+${HostEntryName}\s*$"))
            {
                $result = $true
            }
            else
            {
                $result = $false
            }
        }
        else
        {
            $result = $false
        }
    }

    return $result
}

function UpdateHostFileEntry
{
    [CmdletBinding()]
    param
    (
        [parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $HostFileInfo
    )

    $hostFile = Get-HostsFilePath

    foreach($aHostFileInfo in $HostFileInfo)
    {
        $HostEntryIPAddress = $aHostFileInfo.CimInstanceProperties["HostIpAddress"].Value
        $HostEntryName = $aHostFileInfo.CimInstanceProperties["HostEntryName"].Value
        $RequireHostFileEntry = [bool]::Parse([string]$aHostFileInfo.CimInstanceProperties["RequireHostFileEntry"].Value)

        try
        {
            if ($RequireHostFileEntry)
            {
                if ($HostEntryIPAddress -ne $null -and $HostEntryName -ne $null)
                {
                    Synchronized -Name [System.Uri]::EscapeDataString($hostsFile) -ArgumentList $hostFile, $HostEntryName, $HostEntryIPAddress -ScriptBlock {
                        param($hostFile, $hostEntryName, $hostEntryIPAddress)
                        if (-not (Select-String $hostFile -pattern "\s+${hostEntryName}\s*$"))
                        {
                            Add-Content $hostFile "`n$hostEntryIPAddress    $hostEntryName"
                            (Get-Content($hostFile)) | Set-Content($hostFile)
                        }
                        else {
                            (Get-Content($hostFile)) | ForEach-Object {$_ -replace "^\d+.\d+.\d+.\d+\s+${hostEntryName}\s*$", "$hostEntryIPAddress    $hostEntryName" } | Set-Content($hostFile)
                        }
                    }
                }
            }
        }
        Catch
        {
            ThrowTerminatingError `
                -ErrorId "HostEntryUpdateFailure" `
                -ErrorMessage  ($($LocalizedData.HostEntryUpdateFailure) -f ${HostEntryName, HostEntryIPAddress}) `
                -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidResult) `
                -Exception ($_.exception)
        }
    }
}

# ValidateWebsite is a helper function used to validate the results
function ValidateWebsite
{
    [CmdletBinding()]
    param
    (
        [object] $Website,

        [string] $Name
    )

    # If a wildCard pattern is not supported by the website provider.
    # Hence we restrict user to request only one website information in a single request.
    if($Website.Count-gt 1)
    {
        ThrowTerminatingError `
                -ErrorId "WebsiteDiscoveryFailure" `
                -ErrorMessage  ($($LocalizedData.WebsiteDiscoveryFailureError) -f ${Name}) `
                -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidResult)
    }
}

# Helper function used to validate website path
function ValidateWebsitePath
{
    [CmdletBinding()]
    param
    (
        [string] $Name,

        [string] $PhysicalPath
    )

    $PathNeedsUpdating = $false

    if((Get-ItemProperty "IIS:\Sites\$Name" -Name physicalPath) -ne $PhysicalPath)
    {
        $PathNeedsUpdating = $true
    }

    $PathNeedsUpdating

}

# Helper function used to validate website bindings
# Returns true if bindings are valid (ie. port, IPAddress & Hostname combinations are unique).

function ValidateWebsiteBindings
{
    [CmdletBinding()]
    Param
    (
        [parameter()]
        [string]
        $Name,

        [parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $BindingInfo
    )

    $Valid = $true

    foreach($binding in $BindingInfo)
    {
        # First ensure that desired binding information is valid ie. No duplicate IPAddres, Port, Host name combinations.
        if (!(EnsurePortIPHostUnique -Port $binding.Port -IPAddress $binding.IPAddress -HostName $Binding.Hostname -BindingInfo $BindingInfo) )
        {
            ThrowTerminatingError `
                -ErrorId "WebsiteBindingInputInvalidation" `
                -ErrorMessage  ($($LocalizedData.WebsiteBindingInputInvalidationError) -f ${Name}) `
                -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidResult)
        }
    }

    return compareWebsiteBindings -Name $Name -BindingInfo $BindingInfo
}

function Test-AuthenticationEnabled
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    Param
    (
        [parameter(Mandatory = $true)]
        [System.String]$WebSite,

        [parameter(Mandatory = $true)]
        [ValidateSet("Anonymous","Basic","Digest","Windows")]
        [System.String]$Type
    )


    $prop = Get-WebConfigurationProperty `
        -Filter /system.WebServer/security/authentication/${Type}Authentication `
        -Name enabled `
        -Location $WebSite
    return $prop.Value
}

function Set-Authentication
{
    [CmdletBinding()]
    Param
    (
        [parameter(Mandatory = $true)]
        [System.String]$WebSite,

        [parameter(Mandatory = $true)]
        [ValidateSet("Anonymous","Basic","Digest","Windows")]
        [System.String]$Type,

        [System.Boolean]$Enabled
    )

    Set-WebConfigurationProperty -Filter /system.WebServer/security/authentication/${Type}Authentication `
        -Name enabled `
        -Value $Enabled `
        -Location $WebSite
}

function Get-AuthenticationInfo
{
    [CmdletBinding()]
    [OutputType([Microsoft.Management.Infrastructure.CimInstance])]
    Param
    (
        [parameter(Mandatory = $true)]
        [System.String]$WebSite
    )

    $authenticationProperties = @{}
    foreach ($type in @("Anonymous", "Basic", "Digest", "Windows"))
    {
        $authenticationProperties[$type] = [string](Test-AuthenticationEnabled -Website $Website -Type $type)
    }

    return New-CimInstance -ClassName SEEK_cWebAuthenticationInformation -ClientOnly -Property $authenticationProperties
}

function Test-AuthenticationInfo
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]$Website,

        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [Microsoft.Management.Infrastructure.CimInstance]$AuthenticationInfo
    )

    $result = $true

    foreach ($type in @("Anonymous", "Basic", "Digest", "Windows"))
    {
        $expected = $AuthenticationInfo.CimInstanceProperties[$type].Value
        $actual = Test-AuthenticationEnabled -Website $Website -Type $type
        if ($expected -ne $actual)
        {
            $result = $false
            break
        }
    }

    return $result
}

function Set-AuthenticationInfo
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]$WebSite,

        [parameter()]
        [ValidateNotNullOrEmpty()]
        [Microsoft.Management.Infrastructure.CimInstance]$AuthenticationInfo
    )

    foreach ($type in @("Anonymous", "Basic", "Digest", "Windows"))
    {
        $enabled = ($AuthenticationInfo.CimInstanceProperties[$type].Value -eq $true)
        Set-Authentication -Website $Website -Type $type -Enabled $enabled
    }
}

function Get-DefaultAuthenticationInfo
{
    New-CimInstance -ClassName SEEK_cWebAuthenticationInformation `
        -ClientOnly `
        -Property @{Anonymous="false";Basic="false";Digest="false";Windows="false"}
}

function EnsurePortIPHostUnique
{
    [CmdletBinding()]
    param
    (
        [parameter()]
        [System.UInt16]
        $Port,

        [parameter()]
        [string]
        $IPAddress,

        [parameter()]
        [string]
        $HostName,

        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $BindingInfo,

        [parameter()]
        $UniqueInstances = 0
    )

    foreach ($Binding in $BindingInfo)
    {
        if($binding.Port -eq $Port -and [string]$Binding.IPAddress -eq $IPAddress -and [string]$Binding.HostName -eq $HostName)
        {
            $UniqueInstances += 1
        }
    }

    if($UniqueInstances -gt 1)
    {
        return $false
    }
    else
    {
        return $true
    }
}

# Helper function used to compare website bindings of actual to desired
# Returns true if bindings need to be updated and false if not.
function compareWebsiteBindings
{
    [CmdletBinding()]
    param
    (
        [parameter()]
        [string]
        $Name,

        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $BindingInfo
    )
    #Assume bindingsNeedUpdating
    $BindingNeedsUpdating = $false

    #check to see if actual settings have been passed in. If not get them from website
    if($ActualBindings -eq $null)
    {
        $ActualBindings = (Get-ItemProperty -path "IIS:\Sites\$Name" -Name Bindings).collection

        #Format Binding information: Split BindingInfo into individual Properties (IPAddress:Port:HostName)
        $ActualBindingObjects = @()
        foreach ($ActualBinding in $ActualBindings)
        {
            $ActualBindingObjects += Get-WebBindingObject -Binding $ActualBinding
        }
    }

    #Compare Actual Binding info ($FormatActualBindingInfo) to Desired($BindingInfo)
    try
    {
        if($BindingInfo.Count -le $ActualBindingObjects.Count)
        {
            foreach($Binding in $BindingInfo)
            {
                $ActualBinding = $ActualBindingObjects | ?{$_.Port -eq $Binding.CimInstanceProperties["Port"].Value}
                if ($ActualBinding -ne $null)
                {
                    if([string]$ActualBinding.Protocol -ne [string]$Binding.CimInstanceProperties["Protocol"].Value)
                    {
                        $BindingNeedsUpdating = $true
                        break
                    }

                    if([string]$ActualBinding.IPAddress -ne [string]$Binding.CimInstanceProperties["IPAddress"].Value)
                    {
                        # Special case where blank IPAddress is saved as "*" in the binding information.
                        if([string]$ActualBinding.IPAddress -eq "*" -AND [string]$Binding.CimInstanceProperties["IPAddress"].Value -eq "")
                        {
                            #Do nothing
                        }
                        else
                        {
                            $BindingNeedsUpdating = $true
                            break
                        }
                    }

                    if([string]$ActualBinding.HostName -ne [string]$Binding.CimInstanceProperties["HostName"].Value)
                    {
                        $BindingNeedsUpdating = $true
                        break
                    }

                    if([string]$ActualBinding.CertificateThumbprint -ne [string]$Binding.CimInstanceProperties["CertificateThumbprint"].Value)
                    {
                        $BindingNeedsUpdating = $true
                        break
                    }

                    if([string]$ActualBinding.CertificateStoreName -ne [string]$Binding.CimInstanceProperties["CertificateStoreName"].Value)
                    {
                        $BindingNeedsUpdating = $true
                        break
                    }
                }
                else
                {
                    {
                        $BindingNeedsUpdating = $true
                        break
                    }
                }
            }
        }
        else
        {
            $BindingNeedsUpdating = $true
        }

        $BindingNeedsUpdating

    }
    catch
    {
        ThrowTerminatingError `
                -ErrorId "WebsiteCompareFailure" `
                -ErrorMessage  ($($LocalizedData.WebsiteCompareFailureError) -f ${Name}) `
                -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidResult) `
                -Exception ($_.exception)
    }
}

function UpdateBindings
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Name,

        [parameter()]
        [Microsoft.Management.Infrastructure.CimInstance[]]
        $BindingInfo
    )

    #Enable all protocols specified in bindings
    $SiteEnabledProtocols = $BindingInfo  | Select-Object -ExpandProperty Protocol -Unique
    Synchronized -Name "IIS" -ArgumentList "IIS:\Sites\${Name}", $SiteEnabledProtocols {
        param($path, $enabledProtocols)
        Set-ItemProperty -Path $path -Name EnabledProtocols -Value ($enabledProtocols -join ',')
    }

    $bindingParams = @()
    foreach($binding in $BindingInfo)
    {
        $Protocol = $Binding.CimInstanceProperties["Protocol"].Value
        if($Protocol -eq $null){$Protocol = 'http'} #Default to Http
        $IPAddress = $Binding.CimInstanceProperties["IPAddress"].Value
        if($IPAddress -eq $null){$IPAddress = '*'} # Default to any/all IP Addresses
        $Port = $Binding.CimInstanceProperties["Port"].Value
        $HostName = $Binding.CimInstanceProperties["HostName"].Value


        if ($Protocol -eq 'net.pipe')
        {
            $bindingInformation = "$HostName"
        }
        elseif ($Protocol -eq 'net.tcp')
        {
            $bindingInformation = "$($Port):$HostName"
        }
        else
        {
            $bindingInformation = "$($IPAddress):$($Port):$HostName"
        }

        $bindingParams += @{Protocol = $Protocol; BindingInformation = $bindingInformation}
    }

    try
    {
        Synchronized -Name "IIS" -ArgumentList "IIS:\Sites\${Name}", $bindingParams {
            param($path, $bindings)
            Set-ItemProperty -Path $path -Name bindings -value $bindings
        }
    }
    Catch
    {
        ThrowTerminatingError `
            -ErrorId "WebsiteBindingUpdateFailure" `
            -ErrorMessage  ($($LocalizedData.WebsiteBindingUpdateFailureError) -f ${HostName}, ${Name}) `
            -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidResult) `
            -Exception ($_.exception)
    }

    $HttpsBindingInfo = $BindingInfo | ? { $_.CimInstanceProperties["Protocol"].Value -eq "https" }
    foreach($binding in $HttpsBindingInfo)
    {
        $Port = $Binding.CimInstanceProperties["Port"].Value
        $IpAddress = $Binding.CimInstanceProperties["IPAddress"].Value
        $SslSubject = $Binding.CimInstanceProperties["SslSubject"].Value
        $SslCertPath = $Binding.CimInstanceProperties["SslCertPath"].Value

        try
        {
            if ($SslSubject -ne $null -and $SslCertPath -ne $null)
            {
                $theCert = Get-ChildItem -path $SslCertPath | Where-Object {$_.Subject -eq $SslSubject }

                Set-BindingCertificate `
                    -IpAddress $IpAddress `
                    -Port $Port `
                    -Certificate $theCert
            }
        }
        catch
        {
            throw $_
            ThrowTerminatingError `
                -ErrorId "WebBindingCertifcateError" `
                -ErrorMessage  ($($LocalizedData.WebBindingCertifcateError) -f ${CertificateThumbprint}) `
                -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidResult) `
                -Exception ($_.exception)
        }
    }

}

function Set-BindingCertificate
{
    [CmdletBinding()]
    Param
    (
        [parameter(Mandatory=$true)]
        [System.Object]$Certificate,

        [System.String]$IpAddress = "0.0.0.0",

        [System.String]$Port = 443
    )
    $path = "IIS:\SslBindings\${IpAddress}!${Port}"

    if (Test-Path $path)
    {
        $thumbprint = (Get-Item $path).Thumbprint
        if ($Certificate.Thumbprint -eq $thumbprint)
        {
            return
        }
        else
        {
            Remove-Item $path
        }
    }

    New-Item -Path $path -Value $Certificate
}

function Get-WebBindingObject
{
    [CmdletBinding()]
    Param
    (
        [parameter(Mandatory=$true)]
        [System.Object]$Binding
    )

    $bindingProperties = @{Protocol = $Binding.protocol}

    switch -wildcard ($Binding.protocol)
    {
        "http*"
        {
            $Matches = $null
            if ($Binding.BindingInformation -match "^\[?(?<IPAddress>[\*\w\d\.:]*)\]?:(?<Port>[\*\d]+):(?<HostName>.*)$")
            {
                $bindingProperties["IPAddress"] = $Matches["IPAddress"]
                $bindingProperties["Port"] = $Matches["Port"]
                $bindingProperties["HostName"] = $Matches["HostName"]
            }
            else { throw "BindingInformation format is invalid for protocol ""$($Binding.protocol)"" {$($Binding.BindingInformation)}" }
        }
        "https"
        {
            $bindingProperties["CertificateThumbprint"] = $Binding.CertificateHash
            $bindingProperties["CertificateStoreName"] = $Binding.CertificateStoreName
        }
        "net.tcp"
        {
            $Matches = $null
            if ($Binding.BindingInformation -match "^(?<Port>[\*\d]+):(?<HostName>.*)$")
            {
                $bindingProperties["Port"] = $Matches["Port"]
                $bindingProperties["HostName"] = $Matches["HostName"]
            }
            else { throw "BindingInformation format is invalid for protocol ""$($Binding.protocol)"" {$($Binding.BindingInformation)}" }
        }
        "net.pipe"
        {
            $bindingProperties["HostName"] = $Binding.BindingInformation
        }
        "net.msmq"
        {
            $bindingProperties["HostName"] = $Binding.BindingInformation.Split("/")[0]
        }
        default { throw "Invalid protocol ""$($Binding.protocol)""" }
    }

    return (New-Object PSObject -Property $bindingProperties)
}

function Get-HostsFilePath
{
    return [Environment]::SystemDirectory + "\drivers\etc\hosts"
}

function ThrowTerminatingError
{
    [CmdletBinding()]
    param
    (
        [System.String]$ErrorId,
        [System.String]$ErrorMessage,
        [System.Management.Automation.ErrorCategory]$ErrorCategory,
        [System.Exception]$Exception = $null
    )

    $exception = New-Object System.InvalidOperationException $ErrorMessage, $Exception
    $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $ErrorId, $ErrorCategory, $null
    throw $errorRecord
}

function Get-SslFlags
{
    [CmdletBinding()]
    param
    (
        [System.String]$Location
    )

    $sslFlags = Get-WebConfiguration -PSPath IIS:\Sites -Location $Location -Filter 'system.webserver/security/access' | % { $_.sslFlags }
    $sslFlags = if ($sslFlags -eq $null) { "" } else { $sslFlags }
    return $sslFlags
}

#endregion
lib\cWebAdministration\DSCResources\SEEK_cWebsite\SEEK_cWebsite.schema.mof
 
lib\cWebAdministration\DSCResources\SEEK_cWebVirtualDirectory\SEEK_cWebVirtualDirectory.psm1
Import-Module WebAdministration

$LogonMethodEnum = @("Batch","Interactive","Network","ClearText")

function Synchronized
{
    [CmdletBinding()]
    param
    (
        [ValidateNotNullOrEmpty()]
        [ValidatePattern("^[^\\]?")]
        [parameter(Mandatory = $true)]
        [string] $Name,

        [parameter(Mandatory = $true)]
        [ScriptBlock] $ScriptBlock,

        [parameter(Mandatory = $false)]
        [int] $MillisecondsTimeout = 5000,

        [parameter(Mandatory = $false)]
        [boolean] $InitiallyOwned = $false,

        [parameter(Mandatory = $false)]
        [Object[]] $ArgumentList = @(),

        [parameter(Mandatory = $false)]
        [ValidateSet("Global","Local","Session")]
        [Object[]] $Scope = "Global"
    )

    $mutex = New-Object System.Threading.Mutex($InitiallyOwned, "${Scope}\${Name}")
    
    if ($mutex.WaitOne($MillisecondsTimeout)) {
        try {
            Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $ArgumentList
        }
        finally {
            $mutex.ReleaseMutex()
        }
    }
    else { throw "Cannot aquire mutex: $Name"}
}

function Get-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]
        $Website,

        [System.String]
        $WebApplication = $null,

        [parameter(Mandatory = $true)]
        [System.String]
        $Name
    )

    if (test-VirtualDirectoryExists $WebSite $Name $WebApplication)
    {
        $virtualDirectoryPath = Get-VirtualDirectoryPath -Site $Website -Name $Name -Application $WebApplication
        $virtualDirectory = Get-Item -Path $virtualDirectoryPath
        return @{
            Name = $Name
            Website = $Website
            WebApplication = $WebApplication
            PhysicalPath = $virtualDirectory.PhysicalPath
            LogonMethod = $virtualDirectory.logonMethod
            Username = $virtualDirectory.username
            Password = $virtualDirectory.password
            Ensure = "Present"
        }
    }

    return @{
        Name = $Name
        Website = $Website
        WebApplication = $WebApplication
        PhysicalPath = $null
        LogonMethod = $null
        Username = $null
        Password = $null
        Ensure = "Absent"
    }
}

function Set-TargetResource
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]
        $Website,

        [System.String]
        $WebApplication = $null,

        [parameter(Mandatory = $true)]
        [System.String]
        $Name,

        [parameter(Mandatory = $true)]
        [System.String]
        $PhysicalPath,

        [ValidateSet("Batch","Interactive","Network","ClearText")]
        [System.String]
        $LogonMethod = "ClearText",

        [System.String]
        $Username = "",

        [System.String]
        $Password = "",


        [ValidateSet("Present","Absent")]
        [System.String]
        $Ensure = "Present"
    )

    $virtualDirectory = Get-TargetResource -Website $Website -Name $Name -WebApplication $WebApplication

    if ($Ensure -eq "Present")
    {
        $path = Get-VirtualDirectoryPath -Site $Website -Application $WebApplication -Name $Name

        if ($virtualDirectory.Ensure -eq "Absent")
        {
            Write-Verbose "Creating new Web Virtual Directory $Name."
            New-WebVirtualDirectory -Site $Website -Application $WebApplication -Name $Name -PhysicalPath $PhysicalPath
        }
        else
        {
            Write-Verbose "Updating physical path for web virtual directory $Name."
            Synchronized -Name "IIS" -ArgumentList $path, $PhysicalPath {
                param($path, $physicalPath)
                Set-ItemProperty -Path $path -Name physicalPath -Value $physicalPath
            }
        }

        Synchronized -Name "IIS" -ArgumentList $path, ($LogonMethodEnum.IndexOf($LogonMethod)) {
            param($path, $logonMethod)
            Set-ItemProperty -Path $path -Name logonMethod -Value $logonMethod
        }

         Synchronized -Name "IIS" -ArgumentList $path, $Username, $Password {
            param($path, $username, $password)
            Set-ItemProperty -Path $path -Name username -Value $username
            Set-ItemProperty -Path $path -Name password -Value $password
        }
    }

    if ($virtualDirectory.Ensure -eq "Present" -and $Ensure -eq "Absent")
    {
        Write-Verbose "Removing existing Virtual Directory $Name."
        Remove-WebVirtualDirectory -Site $Website -Application $WebApplication -Name $Name
    }
}

function Test-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]
        $Website,

        [System.String]
        $WebApplication = $null,

        [parameter(Mandatory = $true)]
        [System.String]
        $Name,

        [parameter(Mandatory = $true)]
        [System.String]
        $PhysicalPath,

        [ValidateSet("ClearText","Network","Interactive","Batch")]
        [System.String]
        $LogonMethod = "ClearText",

        [System.String]
        $Username = "",

        [System.String]
        $Password = "",

        [ValidateSet("Present","Absent")]
        [System.String]
        $Ensure = "Present"
    )

    Write-Verbose "Checking the virtual directories for the website."

    $virtualDirectory = Get-TargetResource -Website $Website -Name $Name -WebApplication $WebApplication

    if ($virtualDirectory.Ensure -eq "Absent" -and $Ensure -eq "Absent")
    {
        Write-Verbose "Web virtual direcotry $Name should be absent and is absent"
        return $true
    }

    if ($virtualDirectory.Ensure -eq "Present" `
        -and $Ensure -eq "Present" `
        -and $virtualDirectory.physicalPath -eq $PhysicalPath `
        -and $virtualDirectory.logonMethod -eq $LogonMethod `
        -and $virtualDirectory.username -eq $Username `
        -and $virtualDirectory.password -eq $Password)
    {
        Write-Verbose "Web virtual directory is in required state"
        return $true
    }

    Write-Verbose "Web virtual directory $Name does not match desired state."

    return $false
}

function Get-VirtualDirectoryPath
{
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]
        $Name,

        [parameter(Mandatory = $true)]
        [System.String]
        $Site,

        [System.String]
        $Application = $null
    )

    if (-not $Application)
    {
        return "IIS:\Sites\${Site}\${Name}"
    }

    return "IIS:\Sites\${Site}\${Application}\${Name}"
}

function test-VirtualDirectoryExists
{
    param
    (
        [System.String] $Website,
        [System.String] $Name,
        [System.String] $WebApplication
    )

    $virtualDirectoryPath = Get-VirtualDirectoryPath -Site $Website -Name $Name -Application $WebApplication

    if(-not (Test-Path $virtualDirectoryPath)) { return $false}

    $virtualDirectory = Get-Item -Path $virtualDirectoryPath

    $virtualDirectory.PhysicalPath -ne $null
}

Export-ModuleMember -Function *-TargetResource

lib\cWebAdministration\DSCResources\SEEK_cWebVirtualDirectory\SEEK_cWebVirtualDirectory.schema.mof
 
lib\cWebAdministration\Mutex.psm1
function Synchronized
{
    [CmdletBinding()]
    param
    (
        [ValidateNotNullOrEmpty()]
        [ValidatePattern("^[^\\]?")]
        [parameter(Mandatory = $true)]
        [string] $Name,

        [parameter(Mandatory = $true)]
        [ScriptBlock] $ScriptBlock,

        [parameter(Mandatory = $false)]
        [int] $MillisecondsTimeout = 5000,

        [parameter(Mandatory = $false)]
        [boolean] $InitiallyOwned = $false,

        [parameter(Mandatory = $false)]
        [Object[]] $ArgumentList = @(),

        [parameter(Mandatory = $false)]
        [ValidateSet("Global","Local","Session")]
        [Object[]] $Scope = "Global"
    )

    $mutex = New-Object System.Threading.Mutex($InitiallyOwned, "${Scope}\${Name}")
    
    if ($mutex.WaitOne($MillisecondsTimeout)) {
        try {
            Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $ArgumentList
        }
        finally {
            $mutex.ReleaseMutex()
        }
    }
    else { throw "Cannot aquire mutex: $Name"}
}
tools\chocolateyInstall.ps1
try
{
	$DSCResourcesRoot = Join-Path $env:ProgramFiles "WindowsPowerShell\Modules"
	$DSCResourceTarget = Join-Path $env:chocolateyPackageFolder "lib"

	# remove DSC resources that may have been manually installed
	if (Test-Path "$DSCResourcesRoot\SEEK - Modules") {
		cmd /c rmdir "$DSCResourcesRoot\SEEK - Modules"
	}

	# remove previous installation of this package
	Get-ChildItem $DSCResourceTarget | Foreach-Object {
		if (Test-Path "$DSCResourcesRoot\$_") {
			cmd /c rmdir "$DSCResourcesRoot\$_"
		}
		cmd /c mklink /j "$DSCResourcesRoot\$_" "$DSCResourceTarget\$_"
		Get-ChildItem -Path "$DSCResourcesRoot\$_" -File -Recurse | Unblock-File
	}

	Write-ChocolateySuccess 'SEEK PowerShell DSC Resources'
} catch {
	Write-ChocolateyFailure 'SEEK PowerShell DSC Resources' $($_.Exception.Message)
	$host.SetShouldExit(1)
	throw $_
}
tools\chocolateyUninstall.ps1
try
{
	$DSCResourcesRoot = Join-Path $env:ProgramFiles "WindowsPowerShell\Modules"
	$DSCResourceTarget = Join-Path $env:chocolateyPackageFolder "lib"
	Get-ChildItem $DSCResourceTarget | Foreach-Object { cmd /c rmdir "$DSCResourcesRoot\$_" }

	Write-ChocolateySuccess 'SEEK PowerShell DSC Resources'
} catch {
	Write-ChocolateyFailure 'SEEK PowerShell DSC Resources' $($_.Exception.Message)
	throw $_
}

Log in or click on link to see number of positives.

In cases where actual malware is found, the packages are subject to removal. Software sometimes has false positives. Moderators do not necessarily validate the safety of the underlying software, only that a package retrieves software from the official distribution point and/or validate embedded software against official distribution point (where distribution rights allow redistribution).

Chocolatey Pro provides runtime protection from possible malware.

Add to Builder Version Downloads Last Updated Status
SEEK DSC WebAdministration 2.0.0.20230301-alpha9 52 Tuesday, January 3, 2023 Exempted
SEEK DSC WebAdministration 2.0.0-alpha9 561 Thursday, July 30, 2015 Approved
SEEK DSC WebAdministration 2.0.0-alpha7 477 Friday, May 1, 2015 Approved
SEEK DSC WebAdministration 2.0.0-alpha6 460 Wednesday, April 22, 2015 Approved
SEEK DSC WebAdministration 2.0.0-alpha5 448 Tuesday, April 21, 2015 Approved
SEEK DSC WebAdministration 2.0.0-alpha4 458 Tuesday, April 21, 2015 Approved
SEEK DSC WebAdministration 2.0.0-alpha2 439 Tuesday, February 24, 2015 Approved
SEEK DSC WebAdministration 2.0.0-alpha1 427 Monday, February 23, 2015 Approved
SEEK DSC WebAdministration 1.0.9-alpha6 393 Tuesday, June 9, 2015 Approved
SEEK DSC WebAdministration 1.0.9-alpha5 414 Tuesday, June 9, 2015 Approved
SEEK DSC WebAdministration 1.0.9-alpha4 395 Tuesday, June 9, 2015 Approved
SEEK DSC WebAdministration 1.0.9-alpha3 421 Tuesday, May 26, 2015 Approved
SEEK DSC WebAdministration 1.0.9-alpha2 438 Tuesday, May 26, 2015 Approved
SEEK DSC WebAdministration 1.0.9-alpha1 409 Friday, May 22, 2015 Approved
SEEK DSC WebAdministration 1.0.4 505 Friday, May 1, 2015 Approved
SEEK DSC WebAdministration 1.0.3 443 Wednesday, April 22, 2015 Approved
SEEK DSC WebAdministration 1.0.2 416 Tuesday, April 21, 2015 Approved
SEEK DSC WebAdministration 1.0.0.87 621 Sunday, February 22, 2015 Approved
SEEK DSC WebAdministration 1.0.0.77 453 Sunday, January 25, 2015 Approved
SEEK DSC WebAdministration 1.0.0.76 411 Wednesday, January 14, 2015 Approved
SEEK DSC WebAdministration 1.0.0.75 693 Tuesday, December 2, 2014 Approved
SEEK DSC WebAdministration 1.0.0.74 515 Sunday, November 9, 2014 Approved
SEEK DSC WebAdministration 1.0.0.73 410 Friday, November 7, 2014 Approved
SEEK DSC WebAdministration 1.0.0.72 460 Thursday, November 6, 2014 Approved
SEEK DSC WebAdministration 1.0.0.71 408 Thursday, November 6, 2014 Approved
SEEK DSC WebAdministration 1.0.0.70 402 Thursday, November 6, 2014 Approved
SEEK DSC WebAdministration 1.0.0.69 430 Monday, November 3, 2014 Approved
SEEK DSC WebAdministration 1.0.0.68 399 Monday, November 3, 2014 Approved
SEEK DSC WebAdministration 1.0.0.67 395 Monday, November 3, 2014 Approved
SEEK DSC WebAdministration 1.0.0.64 449 Thursday, October 30, 2014 Approved
SEEK DSC WebAdministration 1.0.0.63 420 Thursday, October 30, 2014 Approved
SEEK DSC WebAdministration 1.0.0.62 423 Monday, October 27, 2014 Approved
SEEK DSC WebAdministration 1.0.0.61 375 Friday, October 24, 2014 Approved
SEEK DSC WebAdministration 1.0.0.60 415 Friday, October 24, 2014 Approved
SEEK DSC WebAdministration 1.0.0.59 391 Friday, October 24, 2014 Approved
SEEK DSC WebAdministration 1.0.0.58 367 Friday, October 24, 2014 Approved
SEEK DSC WebAdministration 1.0.0.55 402 Friday, October 24, 2014 Approved
SEEK DSC WebAdministration 1.0.0.54 419 Wednesday, October 15, 2014 Approved
SEEK DSC WebAdministration 1.0.0.53 429 Wednesday, October 15, 2014 Approved
SEEK DSC WebAdministration 1.0.0.52 442 Wednesday, October 15, 2014 Approved
SEEK DSC WebAdministration 1.0.0.51 407 Wednesday, October 15, 2014 Approved
SEEK DSC WebAdministration 1.0.0.50 418 Sunday, October 12, 2014 Approved
SEEK DSC WebAdministration 1.0.0.48 401 Friday, October 10, 2014 Approved
SEEK DSC WebAdministration 1.0.0.47 385 Friday, October 10, 2014 Approved
SEEK DSC WebAdministration 1.0.0.46 370 Friday, October 10, 2014 Approved
SEEK DSC WebAdministration 1.0.0.45 385 Thursday, October 9, 2014 Approved
SEEK DSC WebAdministration 1.0.0.43 369 Wednesday, October 8, 2014 Approved
SEEK DSC WebAdministration 1.0.0.42 383 Wednesday, October 8, 2014 Approved
SEEK DSC WebAdministration 1.0.0.41 366 Thursday, October 2, 2014 Approved
SEEK DSC WebAdministration 1.0.0.40 382 Thursday, September 25, 2014 Approved
SEEK DSC WebAdministration 1.0.0.39 351 Thursday, September 25, 2014 Approved
SEEK DSC WebAdministration 1.0.0.37 362 Wednesday, September 24, 2014 Approved
SEEK DSC WebAdministration 1.0.0.36 358 Monday, September 22, 2014 Approved
SEEK DSC WebAdministration 1.0.0.35 350 Monday, September 15, 2014 Approved
SEEK DSC WebAdministration 1.0.0.34 376 Monday, September 15, 2014 Approved
SEEK DSC WebAdministration 1.0.0.33 373 Monday, September 15, 2014 Approved
SEEK DSC WebAdministration 1.0.0.32 359 Thursday, September 11, 2014 Approved
SEEK DSC WebAdministration 1.0.0.31 349 Wednesday, September 10, 2014 Approved
SEEK DSC WebAdministration 1.0.0.30 381 Wednesday, September 10, 2014 Approved
SEEK DSC WebAdministration 1.0.0.29 395 Wednesday, September 10, 2014 Approved
SEEK DSC WebAdministration 1.0.0.28 400 Tuesday, September 9, 2014 Approved
SEEK DSC WebAdministration 1.0.0.27 350 Tuesday, September 9, 2014 Approved
SEEK DSC WebAdministration 1.0.0.20 381 Tuesday, September 9, 2014 Approved
SEEK DSC WebAdministration 1.0.0.19 379 Tuesday, September 9, 2014 Approved
SEEK DSC WebAdministration 1.0.0.18 403 Tuesday, September 9, 2014 Approved
SEEK DSC WebAdministration 1.0.0.17 375 Tuesday, September 9, 2014 Approved
SEEK DSC WebAdministration 1.0.0.13 388 Friday, September 5, 2014 Approved
SEEK DSC WebAdministration 1.0.0.11 383 Friday, September 5, 2014 Approved
SEEK DSC WebAdministration 1.0.0 392 Tuesday, September 9, 2014 Approved
SEEK DSC WebAdministration 0.0.0.1 330 Tuesday, May 5, 2015 Approved

This package has no dependencies.

Discussion for the SEEK DSC WebAdministration Package

Ground Rules:

  • This discussion is only about SEEK DSC WebAdministration and the SEEK DSC WebAdministration package. If you have feedback for Chocolatey, please contact the Google Group.
  • This discussion will carry over multiple versions. If you have a comment about a particular version, please note that in your comments.
  • The maintainers of this Chocolatey Package will be notified about new comments that are posted to this Disqus thread, however, it is NOT a guarantee that you will get a response. If you do not hear back from the maintainers after posting a message below, please follow up by using the link on the left side of this page or follow this link to contact maintainers. If you still hear nothing back, please follow the package triage process.
  • Tell us what you love about the package or SEEK DSC WebAdministration, or tell us what needs improvement.
  • Share your experiences with the package, or extra configuration or gotchas that you've found.
  • If you use a url, the comment will be flagged for moderation until you've been whitelisted. Disqus moderated comments are approved on a weekly schedule if not sooner. It could take between 1-5 days for your comment to show up.
comments powered by Disqus