r'''
    .. versionadded:: 2017.7.0

    Configure an IIS application.

    .. note::
        This function only configures an existing app. Params are case
        sensitive.

    :param str name: The IIS application.
    :param str site: The IIS site name.
    :param str settings: A dictionary of the setting names and their values.
        - physicalPath: The physical path of the webapp.
        - applicationPool: The application pool for the webapp.
        - userName: "connectAs" user
        - password: "connectAs" password for user
    :return: A boolean representing whether all changes succeeded.
    :rtype: bool

    CLI Example:

    .. code-block:: bash

        salt '*' win_iis.set_webapp_settings name='app0' site='site0' settings="{'physicalPath': 'C:\site0', 'apppool': 'site0'}"

def set_webapp_settings(name, site, settings):
    r'''
    .. versionadded:: 2017.7.0

    Configure an IIS application.

    .. note::
        This function only configures an existing app. Params are case
        sensitive.

    :param str name: The IIS application.
    :param str site: The IIS site name.
    :param str settings: A dictionary of the setting names and their values.
        - physicalPath: The physical path of the webapp.
        - applicationPool: The application pool for the webapp.
        - userName: "connectAs" user
        - password: "connectAs" password for user
    :return: A boolean representing whether all changes succeeded.
    :rtype: bool

    CLI Example:

    .. code-block:: bash

        salt '*' win_iis.set_webapp_settings name='app0' site='site0' settings="{'physicalPath': 'C:\site0', 'apppool': 'site0'}"
    '''
    pscmd = list()
    current_apps = list_apps(site)
    current_sites = list_sites()
    availableSettings = ('physicalPath', 'applicationPool', 'userName', 'password')

    # Validate params
    if name not in current_apps:
        msg = "Application" + name + "doesn't exist"
        raise SaltInvocationError(msg)

    if site not in current_sites:
        msg = "Site" + site + "doesn't exist"
        raise SaltInvocationError(msg)

    if not settings:
        msg = "No settings provided"
        raise SaltInvocationError(msg)

    # Treat all values as strings for the purpose of comparing them to existing values & validate settings exists in predefined settings list
    for setting in settings.keys():
        if setting in availableSettings:
            settings[setting] = six.text_type(settings[setting])
        else:
            availSetStr = ', '.join(availableSettings)
            log.error("Unexpected setting: %s ", setting)
            log.error("Available settings: %s", availSetStr)
            msg = "Unexpected setting:" + setting + " Available settings:" + availSetStr
            raise SaltInvocationError(msg)

    # Check if settings already configured
    current_settings = get_webapp_settings(
        name=name, site=site, settings=settings.keys())

    if settings == current_settings:
        log.warning('Settings already contain the provided values.')
        return True

    for setting in settings:
        # If the value is numeric, don't treat it as a string in PowerShell.
        try:
            complex(settings[setting])
            value = settings[setting]
        except ValueError:
            value = "'{0}'".format(settings[setting])

        # Append relevant update command per setting key
        if setting == "userName" or setting == "password":
            pscmd.append(" Set-WebConfigurationProperty -Filter \"system.applicationHost/sites/site[@name='{0}']/application[@path='/{1}']/virtualDirectory[@path='/']\"".format(site, name))
            pscmd.append(" -Name \"{0}\" -Value {1};".format(setting, value))

        if setting == "physicalPath" or setting == "applicationPool":
            pscmd.append(r' Set-ItemProperty "IIS:\Sites\{0}\{1}" -Name {2} -Value {3};'.format(site, name, setting, value))
            if setting == "physicalPath":
                if not os.path.isdir(settings[setting]):
                    msg = 'Path is not present: ' + settings[setting]
                    raise SaltInvocationError(msg)

    # Run commands
    cmd_ret = _srvmgr(pscmd)

    # Verify commands completed successfully
    if cmd_ret['retcode'] != 0:
        msg = 'Unable to set settings for web application {0}'.format(name)
        raise SaltInvocationError(msg)

    # verify changes
    new_settings = get_webapp_settings(
        name=name, site=site, settings=settings.keys())
    failed_settings = dict()

    for setting in settings:
        if six.text_type(settings[setting]) != six.text_type(new_settings[setting]):
            failed_settings[setting] = settings[setting]

    if failed_settings:
        log.error('Failed to change settings: %s', failed_settings)
        return False

    log.debug('Settings configured successfully: %s', list(settings))
    return True