J - C Sharper
J - C Sharper

Reputation: 1697

How to rename application pool that already has application assigned to it?

I have an Application pool that has a lot of applications been assigned to it, it won't let me rename.

Beside delete and creating a new application pool, is there anyway to get a new name for my application pool? I don't want to go and reassign every application in it.

Upvotes: 20

Views: 16263

Answers (6)

Vladimir1211
Vladimir1211

Reputation: 1

I also try create PowerShell function for rename AppPool with reconfiguring Applications.

I thing that this procedure correctly renames AppPool Original to AppPool New in IIS:

  1. Checking existing AppPool Original and AppPool New.
    • AppPool Original must exist.
    • AppPool New must not exist.
  2. Making a list of Apps that are associated with AppPool Original, if any there are.
  3. Remember status of AppPool Original.
  4. Exporting AppPool Original as xml to a temporary file.
  5. Renaming AppPool Original in the temporary file to AppPool New.
  6. Creating AppPool New by exporting a temporary file.
  7. Stoping AppPool Original.
  8. If there are Apps associated with AppPool Original, then reconfiguring these Apps to AppPool New.
  9. Starting AppPool New.
  10. Removing AppPool Original.

Script PowerShell:

##############################
# Set variables
##############################

# Original pool name
[string]$AppPoolName = 'DefaultAppPool'

# New pool name
[string]$AppPoolNewName = 'DefaultAppPool2'

# Path to appcmd.exe
[string]$AppCmd = 'C:\windows\system32\inetsrv\appcmd.exe'

##############################
# Set functions
##############################


function Get-IISApps {
    <#
    .SYNOPSIS
        The function will return a list of applications associated with the AppPool.
    .DESCRIPTION
        The function get a full list of applications by using appcmd.exe.
        Then function will leave in the list only those applications that mention name of AppPool AppPoolName.
        The result is returned as an array of application names.
    .EXAMPLE
        [array]$List = Get-IISApps -AppPoolName 'DefaultAppPool'
    #>
    [CmdletBinding()]
    [OutputType([array])]
    param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $AppPoolName,

        [string]
        $AppCmd = 'C:\windows\system32\inetsrv\appcmd.exe'
    )
    process {
        # Exporting the list of applications to xml
        [string]$AppCmdCommand = $AppCmd + ' list app /config:* /xml'
        [xml]$ListAppsXml = (cmd.exe /c $AppCmdCommand)

        # Get application names
        [array]$ListAppNames = @()
        ($ListAppsXml.appcmd.ChildNodes ) | ForEach-Object {
            if ($_.'APPPOOL.NAME' -eq $AppPoolName){
                $ListAppNames += $_.'APP.NAME'
            }
        }

        # Return an array of application names
        $ListAppNames
    }
}


function Stop-IISPool {
    <#
    .SYNOPSIS
        The function stoping the AppPool
    .DESCRIPTION
        The function will execute stop command for the AppPool and waiting while AppPool status will be "Stopped".
        While AppPool status is not "Stopped" function wil be get status of AppPool every 100 ms.
        If AppPool status is not "Stopped" a long time, than function will be display a message about this every 5 seconds.
    .EXAMPLE
        Stop-IISPool -AppPoolName 'DefaultAppPool' -Format 'yyyy.MM.ddTHH:mm:ss.fffZ'
    #>
    [CmdletBinding()]
    [OutputType([string])]
    param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $AppPoolName,

        [string]
        $Format = 'yyyy.MM.dd HH:mm:ss.fff'
    )
    process {
        [string]$Message = $null
        [int]$ThisTimer = 0
        [int]$TimePrint = 0
        $null = (Import-Module WebAdministration)
        Do {
            [string]$AppPoolState = (Get-WebAppPoolState -Name $AppPoolName).Value
            if ($AppPoolState -eq 'Started') {
                $null = (Stop-WebAppPool -Name $AppPoolName)
            }
            Start-Sleep -Milliseconds $ThisTimer
            $AppPoolState = (Get-WebAppPoolState -Name $AppPoolName).Value
            if ($AppPoolState -ne 'Stopped') {
                $ThisTimer = 100
                $TimePrint += 100
            }
            if ($TimePrint -eq 5000) {
                [string]$ThisMessage = '[' + (get-date -Format $Format) + ']' + ' INFO ' + 'Waiting for the AppPool "' + $AppPoolName + '" to stop ...' + [System.Environment]::NewLine
                Write-Warning -Message $ThisMessage
                $Message += $ThisMessage
                $TimePrint = 0
            }
        } while ($AppPoolState -ne 'Stopped')
        $Message += '[' + (get-date -Format $Format) + ']' + ' INFO ' + 'AppPool "' + $AppPoolName + '" is stopped.'
        write-host $Message
    }
}


function Start-IISPool {
    <#
    .SYNOPSIS
        The function starting the AppPool
    .DESCRIPTION
        The function will execute start command for the AppPool and waiting while AppPool status will be "Started".
        While AppPool status is not "Started" function wil be get status of AppPool every 100 ms.
        If AppPool status is not "Started" a long time, than function will be display a message about this every 5 seconds.
    .EXAMPLE
        Start-IISPool -AppPoolName 'DefaultAppPool' -Format 'yyyy.MM.ddTHH:mm:ss.fffZ'
    #>
    [CmdletBinding()]
    [OutputType([string])]
    param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $AppPoolName,

        [string]
        $Format = 'yyyy.MM.dd HH:mm:ss.fff'
    )
    process {
        [string]$Message = $null
        $ThisTimer = 0
        $TimePrint = 0
        $null = (Import-Module WebAdministration)
        Do {
            $AppPoolState = (Get-WebAppPoolState -Name $AppPoolName).Value
            if ($AppPoolState -eq 'Stopped') {
                $null = (Start-WebAppPool -Name $AppPoolName)
            }
            Start-Sleep -Milliseconds $ThisTimer
            $AppPoolState = (Get-WebAppPoolState -Name $AppPoolName).Value
            if ($AppPoolState -ne 'Started') {
                $ThisTimer = 100
                $TimePrint += 100
            }
            if ($TimePrint -eq 5000) {
                [string]$ThisMessage = '[' + (get-date -Format $Format) + ']' + ' INFO ' + 'Waiting for the AppPool "' + $AppPoolName + '" to start ...' + [System.Environment]::NewLine
                Write-Warning -Message $ThisMessage
                $Message += $ThisMessage
                $TimePrint = 0
            }
        } while ($AppPoolState -ne 'Started')
        $Message += '[' + (get-date -Format $Format) + ']' + ' INFO ' + 'AppPool "' + $AppPoolName + '" is started.'
        write-host $Message
    }
}


function Rename-IISPool {
    <#
    .SYNOPSIS
        The function will renaming the AppPool
    .DESCRIPTION
        The function will creating a new AppPool with the same characteristics as the original AppPool.
        All applications what associated with the original AppPool will be reconfigured to the new AppPool.
        The original AppPool will be deleted.
        The procedure is as follows:
        1. Creating a new AppPool.
        2. Stoping the original AppPool if it is running.
        3. Reconfiguring applications what associated with the original AppPool to the new AppPool.
        4. Starting a new AppPool if the original AppPool was started.
        5. Deleting the original AppPool.
    .EXAMPLE
        Rename-IISPool -AppPoolName 'DefaultAppPool' -AppPoolNewName 'NewDefaultAppPool' -AppCmd 'C:\windows\system32\inetsrv\appcmd.exe'
    #>
    [CmdletBinding()]
    [OutputType([string])]
    param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $AppPoolName,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $AppPoolNewName,

        [string]
        $AppCmd = 'C:\windows\system32\inetsrv\appcmd.exe',

        [string]
        $Format = 'yyyy.MM.dd HH:mm:ss.fff'
    )
    process {    
    
        # Setting the default encoding
        $PSDefaultParameterValues['*:Encoding'] = 'utf8'

        # Connecting a module to work with IIS
        $null = (Import-Module WebAdministration)

        # Check the existing of pools
        [bool]$ExistAppPoolOriginal =  Test-Path ('IIS:\AppPools\' + $AppPoolName)
        [bool]$ExistAppPoolNew =  Test-Path ('IIS:\AppPools\' + $AppPoolNewName)

        if (-not $ExistAppPoolOriginal) {
            [string]$Message = '[' + (get-date -Format $Format) + ']' + ' DEBUG ' + 'AppPool "' + $AppPoolName + '" does not exist. AppPool "' + $AppPoolNewName + '" will not be created.'
            write-host $Message
        }

        if ($ExistAppPoolNew) {
            [string]$Message = '[' + (get-date -Format $Format) + ']' + ' DEBUG ' + 'AppPool "' + $AppPoolNewName + '" already exists. Nothing to do.'
            write-host $Message
        }

        if ($ExistAppPoolOriginal -and (-not $ExistAppPoolNew)) {
            # Getting a list of applications what associated with a AppPool
            [array]$ListAppNames = Get-IISApps -AppPoolName $AppPoolName -AppCmd $AppCmd

            # Remembering the state of the AppPool
            [string]$AppPoolState = (Get-WebAppPoolState -Name $AppPoolName).Value
    
            # Exporting AppPool to a temporary file
            [string]$TmpPath = New-TemporaryFile
            [string]$AppCmdCommand = $AppCmd + ' list apppool ' + $AppPoolName + ' /config:* /xml > ' + $TmpPath
            try {
                [string]$ExportLog = (cmd.exe /c $AppCmdCommand)
            } finally {
                $ErrorCodeExport = $Lastexitcode
            }
            if ($ErrorCodeExport -eq 0) {
                # Renaming AppPool in a temporary file
                [xml]$NewAppPool = Get-Content $TmpPath
                $NewAppPool.appcmd.APPPOOL.'APPPOOL.NAME' = $AppPoolNewName
                $NewAppPool.appcmd.APPPOOL.add | Where-Object { $_.name -eq $AppPoolName } | ForEach-Object {
                    $_.name = $AppPoolNewName
                }
                $NewAppPool.Save($TmpPath)
    
                # Importing AppPool - Creating AppPool with a new name.
                [string]$AppCmdCommand = $AppCmd + ' add apppool /in < ' + $TmpPath
                try {
                    [string]$ImportLog = (cmd.exe /c $AppCmdCommand)
                } finally {
                    $ErrorCodeImport = $Lastexitcode
                }
                if ($ErrorCodeImport -eq 0) {
                    # Deleting a temporary file
                    Remove-Item -Force $TmpPath
        
                    # AppPool creation check - for slow servers
                    $ThisTimer = 0
                    $TimePrint = 0
                    Do {
                        [bool]$AppPoolExist = (Test-Path ('IIS:\AppPools\' + $AppPoolNewName))
                        Start-Sleep -Milliseconds $ThisTimer
                        if (-not ($AppPoolExist)) {
                            $ThisTimer = 100
                            $TimePrint += 100
                        }
                        if ($TimePrint -eq 5000) {
                            [string]$Message = '[' + (get-date -Format $Format) + ']' + ' INFO ' + 'The AppPool import command was successful, but the AppPool "' + $AppPoolNewName + '" has not yet been created. We are waiting ...'
                            write-host $Message
                            $TimePrint = 0
                        }
                    } while (-not ($AppPoolExist))
                    [string]$Message = '[' + (get-date -Format $Format) + ']' + ' INFO ' + 'AppPool "' + $AppPoolNewName + '" created.'
                    write-host $Message
    
                    # Stopping the original AppPool
                    if ($AppPoolState -ne 'Stopped') {
                        Stop-IISPool -AppPoolName $AppPoolName
                    }
    
                    # If the AppPool is associated with applications, then the applications will be reconfigure to the new AppPool.
                    if ($ListAppNames.Count -gt 0) {
                        Foreach ($AppName in $ListAppNames) {
                            # Reconfiguring the application
                            [string]$AppCmdCommand = $AppCmd + ' set app "' +  $AppName + '" /applicationPool:"' + $AppPoolNewName + '"'
                            $ReconfigAppLog = (cmd.exe /c $AppCmdCommand)
    
                            # Checking that the reconfiguration was completed correctly
                            [string]$AppCmdCommand = $AppCmd + ' list app /config:* /xml'
                            [xml]$AppXml = (cmd.exe /c $AppCmdCommand)
                            [bool]$AppReconfigTrue = $true
                            $AppXml.appcmd.APP | Where-Object { $_.'APP.NAME' -eq $AppName } | ForEach-Object {
                                if ($_.'APPPOOL.NAME' -ne $AppPoolNewName){
                                    $AppReconfigTrue = $false
                                }
                            }
    
                            # Displaying message
                            if ($AppReconfigTrue) {
                                [string]$Message = '[' + (get-date -Format $Format) + ']' + ' INFO ' + 'App "' + $AppName + '" was reconfigured successfully.'
                                write-host $Message
                            } else {
                                [string]$Message = '[' + (get-date -Format $Format) + ']' + ' ERROR ' + 'App "' + $AppName + '" not reconfigured!'
                                write-host $Message
                            }
                        }
                    }
    
                    # Starting a new AppPool
                    if ($AppPoolState -ne 'Stopped') {
                        Start-IISPool -AppPoolName $AppPoolNewName
                    }
    
                    # Deleting original AppPool
                    [string]$AppCmdCommand = $AppCmd + ' delete apppool "' + $AppPoolName + '"'
                    [string]$RemoveLog = (cmd.exe /c $AppCmdCommand)
    
                    # Checking if the AppPool has been deleted
                    if (-not (Test-Path ('IIS:\AppPools\' + $AppPoolName))) {
                        [string]$Message = '[' + (get-date -Format $Format) + ']' + ' INFO ' + 'AppPool "' + $AppPoolName + '" deleted.'
                        write-host $Message
                    } else {
                        [string]$Message = '[' + (get-date -Format $Format) + ']' + ' ERROR ' + 'AppPool "' + $AppPoolName + '" not deleted! Result of executing the delete AppPool command: ' + $RemoveLog
                        write-host $Message
                    }
                } else {
                    [string]$Message = '[' + (get-date -Format $Format) + ']' + ' ERROR ' + 'An error occurred while importing AppPool "' + $AppPoolNewName + '"! AppPool has not been renamed. Error text: ' + $ImportLog
                    write-host $Message
                }
            } else {
                [string]$Message = '[' + (get-date -Format $Format) + ']' + ' ERROR ' + 'An error occurred while exporting AppPool "' + $AppPoolNewName + '"! AppPool has not been renamed. Error text: ' + $ExportLog
                write-host $Message
            }
        }
    }
}

##############################
# Executable code
##############################

Rename-IISPool -AppPoolName $AppPoolName -AppPoolNewName $AppPoolNewName -AppCmd $AppCmd

And i published this script on github this: https://github.com/vladimirk1211/scripts/tree/main/PowerShell/IIS/RenameAppPool

Upvotes: 0

Anton Palyok
Anton Palyok

Reputation: 1559

I've created similar script to automate this job. It is a bit different from the other answer here:

  • It works for WebSites in addition to WebApplications;
  • It works for all pools: with and without assigned applications;

Powershell script:

Import-Module WebAdministration

Function Rename-AppPool([String]$oldName="", [String]$newName="") {
    if ($oldName -eq "") {
        Write-Warning "Parameter 'oldName' was not provided."
        return
    }

    if ($newName -eq "") {
        Write-Warning "Parameter 'newName' was not provided."
        return
    }

    if(-not (Test-Path "IIS:\AppPools\$oldName")){
        Write-Warning "There is no pool with name '$oldName' to rename. Operation stopped."
        return
    }

    if(Test-Path "IIS:\AppPools\$newName"){
        Write-Warning "Pool with name '$newName' already exists. Operation stopped."
        return
    }

    Write-Output "Renaming app pool '$oldName' to '$newName'"

    $pathsOfPools = New-Object System.Collections.ArrayList

    $listOfSites = Get-ChildItem "IIS:\Sites"

    foreach ($site in $listOfSites) {
        if ($site.applicationPool -eq $oldName) {
            $path = ("IIS:\Sites\{0}" -f $site.name)
            $pathsOfPools.Add($path) | Out-Null
        }

        $apps = $site | Get-ChildItem
        foreach ($app in $apps) {
            if ($app.applicationPool -eq $oldName) {                
                $path = ("IIS:\Sites\{0}\{1}" -f $site.name, $app.name)
                $pathsOfPools.Add($path) | Out-Null
            }
        }
    }

    $tempGuid = [Guid]::NewGuid()
    $tempName = $tempGuid.Guid

    if ($pathsOfPools.Count -gt 0) {

        $pathsOfPools   

        New-WebAppPool $tempName | Out-Null
        Write-Output "Temp app pool '$tempName' has been created"

        Write-Output "Changing apps to Temp pool"
        foreach ($path in $pathsOfPools) {
            Set-ItemProperty $path applicationPool $tempName        
        }
    }

    Set-ItemProperty "IIS:\AppPools\$oldName" -Name name -Value $newName
    Write-Output "Application pool name has been changed"

    if ($pathsOfPools.Count -gt 0) {
        Write-Output "Changing apps to New pool"
        foreach ($path in $pathsOfPools) {
            Set-ItemProperty $path applicationPool $newName     
        }   

        Remove-WebAppPool $tempName 
        Write-Output "Temp pool has been removed"
    }
}

Rename-AppPool "OldName" "NewBetterName"

Upvotes: 3

Pramod Hm
Pramod Hm

Reputation: 31

Yes, there is an option. Create a dummy app pool or make use of DefaultApppool. Associate the existing site to the defaultapppool . Now go to the original app pool, Stop the app pool and rename.

Associate back the url to the renamed appool.

Upvotes: 3

Alexis Coles
Alexis Coles

Reputation: 1317

This was the simplest way that I could work it out, although I can't believe this isn't easier.

Import-Module WebAdministration

$oldName = "OldAppPool";
$newName = "NewAppPool";

if(-not (Test-Path IIS:\AppPools\TempPool)){
    New-WebAppPool TempPool
}
$tempAppPool = Get-Item IIS:\AppPools\TempPool

foreach($site in Get-ChildItem IIS:\Sites){
    $apps = $site | Get-ChildItem | Where-Object { $_.ApplicationPool -eq $oldName }

    foreach($app in $apps){
        $path = ("IIS:\Sites\{0}\{1}" -f $site.name, $app.name)
        $path
        Set-ItemProperty $path applicationPool TempPool
    }
}

Set-ItemProperty "IIS:\AppPools\$oldName" -Name name -Value $newName

foreach($site in Get-ChildItem IIS:\Sites){
    $apps = $site | Get-ChildItem | Where-Object { $_.ApplicationPool -eq "TempPool" }

    foreach($app in $apps){
        $path = ("IIS:\Sites\{0}\{1}" -f $site.name, $app.name)
        $path
        Set-ItemProperty $path applicationPool $newName
    }
}

Remove-WebAppPool TempPool

Upvotes: 5

Ben
Ben

Reputation: 35653

No, there isn't.

Either put up with the name, or create a new App Pool and assign the applications one-by-one.

If you need to repeat it on multiple servers, you can even automate it with ADSI and JavaScript or VBScript:

Upvotes: 3

evhen14
evhen14

Reputation: 1927

Assign applications to another pool, rename the one you wanted renamed. Re-assign applications back to your pool.

IIS doesn't support other options

Upvotes: 29

Related Questions