'Using Script resource in DSC to set IIS custom error pages

I am using the xWebAdministration module to configure IIS using DSC - however it does not have anything that supports custom error pages. So I am using a Script resource to do so instead, but am running into two problems:

  1. It sets existing configuration correctly, but it does not add new configurations (such as the error page for 500.4, which would be statusCode = 500 and subStatusCode = 4)
  2. Even though it sets the error pages correctly for existing configurations, it still doesn't recognize they are in the desired state and so re-sets them again on the next run.

Here is the resource code:

foreach ($ErrorPage in $Node.ErrorPages) {
    Script "$($ErrorPage.statusCode)_$($ErrorPage.subStatusCode)" {
        GetScript  = {
            Set-Location "IIS:\"
            $ErrorPageExists = (Get-WebConfiguration -Filter /System.WebServer/HttpErrors).Collection | Where-Object { ($_.statusCode -eq $using:ErrorPage.statusCode) -and ($_.subStatusCode -eq $using:ErrorPage.subStatusCode) }
            return @{ 'Result' = $ErrorPageExists }
        }
        TestScript = {
            $State = [scriptblock]::Create($GetScript).Invoke()
            if (($State.statusCode -ne $using:ErrorPage.statusCode) -or ($State.subStatusCode -ne $using:ErrorPage.subStatusCode) -or ($State.prefixLanguageFilePath -ne $using:ErrorPage.prefixLanguageFilePath) -or ($State.path -ne $using:ErrorPage.path) -or ($State.responseMode -ne $using:ErrorPage.responseMode)) {
                Write-Verbose -Message ("ErrorPage $($using:ErrorPage.statusCode)/$($using:ErrorPage.subStatusCode) is not in the desired state.")
                return $true
            }
            Write-Verbose -Message ("ErrorPage $($using:ErrorPage.statusCode)/$($using:ErrorPage.subStatusCode) is in the desired state.")
            return $false
        }
        SetScript  = {
            Set-Location "IIS:\"
            if ($null -eq (Get-WebConfiguration -Filter /System.WebServer/HttpErrors).Collection | Where-Object { ($_.statusCode -eq $using:ErrorPage.statusCode) -and ($_.subStatusCode -eq $using:ErrorPage.subStatusCode) }) {
                Add-WebConfiguration -Filter /System.WebServer/HttpErrors -Value @{StatusCode = "$($using:ErrorPage.statusCode)"; PrefixLanguageFilePath = "$($using:ErrorPage.prefixLanguageFilePath)"; Path = "$($using:ErrorPage.path)"; ResponseMode = "$($using:ErrorPage.responseMode)" }
            }
            else {
                Set-WebConfiguration -Filter "/System.WebServer/HttpErrors/error[@statusCode='$($using:ErrorPage.statusCode)' and @subStatusCode='$($using:ErrorPage.subStatusCode)']" -Value @{StatusCode = "$($using:ErrorPage.statusCode)"; PrefixLanguageFilePath = "$($using:ErrorPage.prefixLanguageFilePath)"; Path = "$($using:ErrorPage.path)"; ResponseMode = "$($using:ErrorPage.responseMode)" }
            }
        }
    }
}

This is what is in the data file:

ErrorPages                  = @(
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "401";
        SubStatusCode          = "-1";
        PrefixLanguageFilePath = "%SystemDrive%\inetpub\custerr";
        Path                   = "401.htm";
        ResponseMode           = "File"
    },
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "403";
        SubStatusCode          = "-1";
        PrefixLanguageFilePath = "%SystemDrive%\inetpub\custerr";
        Path                   = "403.htm";
        ResponseMode           = "File"
    },
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "404";
        SubStatusCode          = "-1";
        PrefixLanguageFilePath = "";
        Path                   = "/path/404-100.asp";
        ResponseMode           = "ExecuteURL"
    },
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "404";
        SubStatusCode          = "1";
        PrefixLanguageFilePath = "";
        Path                   = "/path/404-100.asp";
        ResponseMode           = "ExecuteURL"
    },
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "404";
        SubStatusCode          = "2";
        PrefixLanguageFilePath = "";
        Path                   = "/path/404-100.asp";
        ResponseMode           = "ExecuteURL"
    },
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "404";
        SubStatusCode          = "3";
        PrefixLanguageFilePath = "";
        Path                   = "/path/404-100.asp";
        ResponseMode           = "ExecuteURL"
    },
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "404";
        SubStatusCode          = "100";
        PrefixLanguageFilePath = "";
        Path                   = "/path/404-100.asp";
        ResponseMode           = "ExecuteURL"
    },
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "405";
        SubStatusCode          = "-1";
        PrefixLanguageFilePath = "%SystemDrive%\inetpub\custerr";
        Path                   = "405.htm";
        ResponseMode           = "File"
    },
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "406";
        SubStatusCode          = "-1";
        PrefixLanguageFilePath = "%SystemDrive%\inetpub\custerr";
        Path                   = "406.htm";
        ResponseMode           = "File"
    },
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "412";
        SubStatusCode          = "-1";
        PrefixLanguageFilePath = "%SystemDrive%\inetpub\custerr";
        Path                   = "412.htm";
        ResponseMode           = "File"
    },
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "500";
        SubStatusCode          = "-1";
        PrefixLanguageFilePath = "";
        Path                   = "/path/500-100.asp";
        ResponseMode           = "ExecuteURL"
    },
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "500";
        SubStatusCode          = "100";
        PrefixLanguageFilePath = "";
        Path                   = "/path/500-100.asp";
        ResponseMode           = "ExecuteURL"
    },
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "501";
        SubStatusCode          = "-1";
        PrefixLanguageFilePath = "%SystemDrive%\inetpub\custerr";
        Path                   = "501.htm";
        ResponseMode           = "File"
    },
    @{
        PSPath                 = "IIS:\";
        StatusCode             = "502";
        SubStatusCode          = "-1";
        PrefixLanguageFilePath = "%SystemDrive%\inetpub\custerr";
        Path                   = "502.htm";
        ResponseMode           = "File"
    }
)

Can anyone help me out with what is wrong with my resource code?

Side note: Ignore the 'PSPath' right now, that's for future updates to the code to make it more dynamic. Right now I'm only interested in setting at the IIS:\ level.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source