PSIISHelper.psm1
#Region IsLocal <# .SYNOPSIS .DESCRIPTION .NOTES Author: matthewjdegarmo GitHub: https://github.com/matthewjdegarmo #> Function IsLocal() { [CmdletBinding()] [OutputType([bool])] Param( [System.String]$ComputerName ) Begin { $LocalValues = @( 'localhost', '.', $env:COMPUTERNAME ) } Process { Try { $LocalValues.Contains($ComputerName) } Catch { Throw $_ } } End {} } #EndRegion IsLocal #Region Get-PSIISBinding <# .SYNOPSIS Returns information about IIS web site bindings .DESCRIPTION Takes a list of IIS servers and returns all the web site bindings Requires administrator permissions. .PARAMETER ComputerName A string or string array of server names. .PARAMETER Port The port number to use for the connection. .EXAMPLE Get-WebSiteBinding MY_SERVER_NAME Description ----------- Returns all the web site bindings for the specified server. .EXAMPLE Get-WebSiteBinding MY_SERVER_NAME1, MY_SERVER_NAME2 Description ----------- Returns all the web site bindings for the specified servers. .EXAMPLE "MY_SERVER_NAME" | Get-WebSiteBinding Description ----------- Returns all the web site bindings for the specified server. .EXAMPLE @("MY_SERVER_NAME1", "MY_SERVER_NAME2") | Get-WebSiteBinding Description ----------- Returns all the web site bindings for the specified servers. .EXAMPLE Get-Content myServerNames.txt | Get-WebSiteBinding .NOTES Author: Matthewjdegarmo GitHub: https://github.com/matthewjdegarmo Sponsor: https://github.com/sponsors/matthewjdegarmo #> function Get-PSIISBinding() { [CmdletBinding()] Param ( [Parameter( ValueFromPipeline )] [System.String[]] $ComputerName = $env:COMPUTERNAME, [Parameter()] [System.String] $Port = '*' ) Begin { Write-Verbose -Message "Starting Get-PSIISBinding" $scriptBlock = { [CmdletBinding()] Param( [System.String] $Port ) Import-Module WebAdministration; $sites = Get-ChildItem -path IIS:\Sites foreach ($Site in $sites) { foreach ($Bind in (Get-WebBinding $Site.Name)) { foreach ($bindinfo in ($Bind | Select-Object -ExpandProperty bindingInformation)) { $bindingInformation = @($bindinfo -split ':') if ('*' -ne $Port) { If ($Port -ne $bindingInformation[1]) { continue } } [pscustomobject]@{ Server = $env:COMPUTERNAME Sitename = $Site.name Id = $Site.id State = $Site.State PhysicalPath = $Site.physicalPath ApplicationPool = $Site.applicationPool Protocol = $Bind.Protocol SslFlags = $Bind.sslFlags IpAddress = $bindingInformation[0] Port = $bindingInformation[1] HostName = $bindingInformation[2] } } } } } } Process { Switch($Port) { 'HTTP' {$Port = '80'} 'HTTPS' {$Port = '443'} DEFAULT {} } Write-Verbose "Retrieving IIS information from $ComputerName" If (IsLocal $ComputerName) { Write-Verbose "$($MyInvocation.MyCommand.Name): Running on local computer: $env:COMPUTERNAME" & $scriptBlock -Port $Port -Verbose:$VerbosePreference | Select-Object -ExcludeProperty PSComputerName, RunspaceID, PSShowComputerName } Else { Write-Verbose "$($MyInvocation.MyCommand.Name): Running on remote computer: $COMPUTERNAME" Invoke-Command -ComputerName $ComputerName -ScriptBlock $scriptBlock -ArgumentList $Port | Select-Object -ExcludeProperty PSComputerName, RunspaceID, PSShowComputerName } } } #EndRegion Get-PSIISBinding #Region Get-PSIISPool <# .SYNOPSIS Get application pool information. .DESCRIPTION Query one or multiple remote servers for their application pools and other information. .PARAMETER ComputerName Specify a remote computer to run against. .PARAMETER Name Specify the name of the Application Pool to search for. .PARAMETER State Specify the state of the application pool to query. .EXAMPLE PS> Get-PSIISPool -ComputerName some-remote-pc1 Description ----------- Query 'some-remote-pc1' for all started app pools. .EXAMPLE PS> Get-PSIISPool -ComputerName WebServer01 -Name SiteAppPool_01 Description ----------- This will get the single app pool SiteAppPool_01 from WebServer01 .EXAMPLE PS> Get-PSIISPool -ComputerName WebServer01 -State Stopped Description ----------- Get all stopped app pools from WebServer01 .EXAMPLE PS> Get-PSIISPool WebServer01,WebServer02 -State * Description ----------- Search for all app pools (all states) from WebServer01 and WebServer02 .OUTPUTS [PSCustomObject]@{ Name # Name of Application Pool State # State of Application Pool Applications # Site Names that are in this Application Pool PSComputerName # ComputerName that the Application Pool lives on. } .NOTES Author: Matthew.DeGarmo Github: https://github.com/matthewjdegarmo Sponsor: https://github.com/sponsors/matthewjdegarmo #> Function Get-PSIISPool() { [CmdletBinding()] Param( [Parameter(ValueFromPipelineByPropertyName)] [Alias('Server', 'PSComputerName')] [System.String[]] $ComputerName = $env:COMPUTERNAME, [Parameter(ValueFromPipelineByPropertyName)] [Alias('ApplicationPool')] [System.String] $Name, [Parameter()] [ValidateSet('Started','Stopped', '*')] [System.String] $State = '*' ) Begin { $OriginalFormatEnumerationLimit = $FormatEnumerationLimit $global:FormatEnumerationLimit = -1 } Process { if ($_ -is [System.Object]) { $Pool = @{ # The below If Else statements are version of these Turnary commands. # Windows PowerShell can't handle turnary operators. Leaving these here for reference to the below logic. # ComputerName = ($_.Server) ? $_.Server : (($_.ComputerName) ? $_.ComputerName : $_.PSComputerName) # Name = ($_.ApplicationPool) ? $_.ApplicationPool : $_.Name } If ($_.Server) { $Pool['ComputerName'] = $_.Server } Else { If ($_.ComputerName) { $Pool['ComputerName'] = $_.ComputerName } Else { $Pool['ComputerName'] = $_.PSComputerName } } If ($_.ApplicationPool) { $Pool['Name'] = $_.ApplicationPool } Else { $Pool['Name'] = $_.Name } } else { $Pool = @{ ComputerName = $ComputerName Name = $Name } } $ScriptBlock = { Param( $InputObject, [System.String]$State ) Write-Verbose "$($COMPUTERNAME)`: Retrieving pool information..." Import-Module WebAdministration $Pools = Get-ChildItem 'IIS:\AppPools' | Where-Object { ($_.State -like $State) -and ($_.Name -match $InputObject.Name) } $Sites = Get-ChildItem 'IIS:\Sites' $Pools | Foreach-Object { $Pool = $_ [PSCustomObject] @{ Name = $Pool.Name State = $Pool.State Applications = ($Sites | Where-Object {$_.applicationPool -eq $Pool.Name}).Name ComputerName = $env:COMPUTERNAME } } } $Pool.ComputerName | Foreach-Object { If (IsLocal $_) { & $ScriptBlock -InputObject $Pool -State $State } Else { Invoke-Command -ComputerName $_ -ScriptBlock $ScriptBlock -ArgumentList $_, $State | Select-Object * -ExcludeProperty RunspaceID } } } End { $global:FormatEnumerationLimit = $OriginalFormatEnumerationLimit } } #EndRegion Get-PSIISPool #Region Get-PSIISSite <# .SYNOPSIS Get IIS Site information. .DESCRIPTION Get IIS Site information. .PARAMETER ComputerName Specify a remote computer to run against. .PARAMETER Name Specify the name of the Application Pool to search for. .PARAMETER State Specify the state of the application pool to query. .EXAMPLE Get-PSIISSite -ComputerName "localhost" -Name "DefaultSite" .NOTES Author: matthewjdegarmo GitHub: https://github.com/matthewjdegarmo #> Function Get-PSIISSite() { [CmdletBinding()] Param( [Parameter(ValueFromPipelineByPropertyName)] [Alias('Server', 'PSComputerName')] [System.String[]] $ComputerName = $env:COMPUTERNAME, [Parameter(ValueFromPipelineByPropertyName)] [Alias('Site')] [System.String] $Name, [Parameter()] [ValidateSet('Started','Stopped', '*')] [System.String] $State = '*' ) Begin { $OriginalFormatEnumerationLimit = $FormatEnumerationLimit $global:FormatEnumerationLimit = -1 } Process { $ScriptBlock = { Param( [System.String]$Name, [System.String]$State ) Write-Verbose "$($COMPUTERNAME)`: Retrieving Site information..." Import-Module WebAdministration $WhereList = New-Object System.Collections.ArrayList $Where = $null If ($Name) {[void]$WhereList.Add('$_.Name -like $Name')} If ($State) {[void]$WhereList.Add('$_.State -like $State')} $Where = [scriptblock]::Create($WhereList -join " -and ") Get-ChildItem 'IIS:\Sites' | Where-Object $Where | Foreach-Object { [PSCustomObject] @{ Name = $_.Name State = $_.State ApplicationPool = $_.ApplicationPool ComputerName = $env:COMPUTERNAME } } } $ComputerName | Foreach-Object { If (IsLocal $_) { & $ScriptBlock -Name $Name -State $State } Else { Invoke-Command -ComputerName $_ -ScriptBlock $ScriptBlock -ArgumentList $Name, $State | Select-Object * -ExcludeProperty RunspaceID } } } End { $global:FormatEnumerationLimit = $OriginalFormatEnumerationLimit } } #EndRegion Get-PSIISSite #Region Restart-PSIISPool <# .SYNOPSIS Restart an application pool. .DESCRIPTION Supply the web server and application pool to recycle. .PARAMETER ComputerName Specify the remote server to run against. .PARAMETER Name Specify the pool name to recycle. .PARAMETER Sites Specify the site names that are tied to this pool. This parameter is meant to support Pipeline values, but is not required to specify manually. Example: $Pool | Restart-PSIISPool # $Pool will have Sites information and pass it through the pipeline. Restart-PSIISPool -ComputerName Server1 -Name Pool1 # No site information will be included.. .PARAMETER PassThru If true, the command will return the IIS information. .EXAMPLE PS> Restart-PSIISPool -ComputerName WebServer01 -Name DefaultSitePool Description ----------- This will recycle the DefaultSitePool pool on WebServer01. .EXAMPLE PS> Get-AppPool -ComputerName WebServer01 -Name DefaultSitePool | Restart-PSIISPool Description ----------- This will recycle the DefaultSitePool pool on WebServer01. .EXAMPLE PS> Get-AppPool -ComputerName WebServer01,WebServer02 | Restart-PSIISPool Description ----------- CAUTION: This will recycle ALL app pools on WebServer01 and WebServer02. .EXAMPLE PS> Get-WebsiteInformation url.matthewjdegarmo.com | Restart-PSIISPool Description ----------- If url.matthewjdegarmo.com is found, this will prompt to recycle the app pool it is using. You should only do this if you KNOW that this is the only site on the found Application Pool. .NOTES Author: Matthew.DeGarmo Handle: @matthewjdegarmo #> Function Restart-PSIISPool() { [CmdletBinding( SupportsShouldProcess, ConfirmImpact = "High" )] Param( [Parameter(ValueFromPipelineByPropertyName)] [Alias('Server', 'PSComputerName')] [System.String[]] $ComputerName = $env:COMPUTERNAME, [Parameter(ValueFromPipelineByPropertyName)] [Alias('ApplicationPool')] [System.String] $Name, [Parameter(ValueFromPipelineByPropertyName)] [Alias('Sitename', 'Applications')] [System.String[]] $Sites, [switch]$PassThru ) Begin {} Process { #Region Dynamic Pipeline handling if ($_ -is [System.Object]) { $Pool = @{ # The below If Else statements are version of these Turnary commands. # Windows PowerShell can't handle turnary operators. Leaving these here for reference to the below logic. # ComputerName = ($_.Server) ? $_.Server : (($_.ComputerName) ? $_.ComputerName : $_.PSComputerName).ToUpper() # Name = ($_.ApplicationPool) ? $_.ApplicationPool : $_.Name # Sites = ($_.SiteName) ? $_.SiteName : (($_.Applications) ? $_.Applications : $_.Sites) } If ($_.Server) { $Pool['ComputerName'] = $_.Server } Else { If ($_.ComputerName) { $Pool['ComputerName'] = $_.ComputerName } Else { $Pool['ComputerName'] = $_.PSComputerName } } If ($_.ApplicationPool) { $Pool['Name'] = $_.ApplicationPool } Else { $Pool['Name'] = $_.Name } If ($_.SiteName) { $Pool['Sites'] = $_.SiteName } Else { If ($_.Applications) { $Pool['Sites'] = $_.Applications } Else { $Pool['Sites'] = $_.Sites } } } else { $Pool = @{ ComputerName = $ComputerName.ToUpper() Name = $Name } If ($Sites) { $Pool['Sites'] = $Sites.ToUpper() } else { $Pool['Sites'] = (Get-PSIISPool -ComputerName $Pool.ComputerName -Name $Pool.Name).Applications } } #EndRegion Dynamic Pipeline handling if ($PSCmdlet.ShouldProcess($Pool.ComputerName, "Recycle $($Pool.Name) pool containing sites: $($Pool.Sites)")) { $ScriptBlock = { [CmdletBinding()] Param( $Pool, [switch]$PassThru ) Write-Verbose "$($Pool.ComputerName): Recycling Pool: $($Pool.Name)" Import-Module WebAdministration Try { Restart-WebAppPool -Name $Pool.Name } Catch { $_ } If ($PassThru) { Get-PSIISPool -Name $Pool.Name -State 'Started' } } If (IsLocal $Pool.ComputerName) { & $ScriptBlock -Pool $Pool -PassThru:$PassThru } Else { Invoke-Command -ComputerName $Pool.ComputerName -ScriptBlock $ScriptBlock -ArgumentList $Pool, $PassThru } } } } #EndRegion Restart-PSIISPool #Region Restart-PSIISSite <# .SYNOPSIS Restart a Website. .DESCRIPTION Supply the web server and website to restart. .PARAMETER ComputerName Specify the remote server to run against. .PARAMETER Name Specify the website name to restart. .PARAMETER PassThru If true, the command will return the IIS information. .EXAMPLE PS> Restart-PSIISSite -ComputerName WebServer01 -Name DefaultSite Description ----------- This will restart the website DefaultSite on WebServer01 .NOTES Author: Matthew.DeGarmo Github: https://github.com/matthewjdegarmo Sponsor: https://github.com/sponsors/matthewjdegarmo #> Function Restart-PSIISSite() { [CmdletBinding( SupportsShouldProcess, ConfirmImpact="High" )] Param( [Parameter(ValueFromPipelineByPropertyName)] [Alias('Server','PSComputerName')] [System.String[]] $ComputerName = $env:COMPUTERNAME, [Parameter(ValueFromPipelineByPropertyName)] [Alias('Sitename')] [System.String] $Name, [switch]$PassThru ) Begin {} Process { if ($_ -is [System.Object]) { $Site = @{ # The below If Else statements are version of these Turnary commands. # Windows PowerShell can't handle turnary operators. Leaving these here for reference to the below logic. # ComputerName = ($_.Server) ? $_.Server : (($_.ComputerName) ? $_.ComputerName : $_.PSComputerName) # Name = ($_.Sitename) ? $_.Sitename : $_.Name } If ($_.Server) { $Site['ComputerName'] = $_.Server } Else { If ($_.ComputerName) { $Site['ComputerName'] = $_.ComputerName } Else { $Site['ComputerName'] = $_.PSComputerName } } If ($_.Sitename) { $Site['Name'] = $_.Sitename } Else { $Site['Name'] = $_.Name } } else { $Site = @{ ComputerName = $ComputerName Name = $Name } } if ($PSCmdlet.ShouldProcess($Site.ComputerName, "Restart site: $($Site.Name)")) { $ScriptBlock = { [CmdletBinding()] Param( $Site, [switch]$PassThru ) Import-Module WebAdministration Stop-Website -Name $Site.Name -ErrorAction SilentlyContinue Start-Website -Name $Site.Name -ErrorAction SilentlyContinue -PassThru:$PassThru } $Site.ComputerName | FOreach-Object { If (IsLocal $_) { & $ScriptBlock -Site $Site -PassThru:$PassThru } Else { Invoke-Command -ComputerName $_ -ScriptBlock $ScriptBlock -ArgumentList $Site, $PassThru | Select-Object -ExcludeProperty RunspaceId } } } } } #EndRegion Restart-PSIISSite #Region Start-PSIISPool <# .SYNOPSIS Restart an application pool. .DESCRIPTION Supply the web server and application pool to recycle. .PARAMETER ComputerName Specify the remote server to run against. .PARAMETER Name Specify the pool name to recycle. .PARAMETER Sites Specify the site names that are tied to this pool. This parameter is meant to support Pipeline values, but is not required to specify manually. Example: $Pool | Restart-PSIISPool # $Pool will have Sites information and pass it through the pipeline. Restart-PSIISPool -ComputerName Server1 -Name Pool1 # No site information will be included.. .PARAMETER PassThru If true, the command will return the IIS information. .EXAMPLE PS> Restart-PSIISPool -ComputerName WebServer01 -Name DefaultSitePool Description ----------- This will recycle the DefaultSitePool pool on WebServer01. .EXAMPLE PS> Get-AppPool -ComputerName WebServer01 -Name DefaultSitePool | Restart-PSIISPool Description ----------- This will recycle the DefaultSitePool pool on WebServer01. .EXAMPLE PS> Get-AppPool -ComputerName WebServer01,WebServer02 | Restart-PSIISPool Description ----------- CAUTION: This will recycle ALL app pools on WebServer01 and WebServer02. .EXAMPLE PS> Get-WebsiteInformation url.matthewjdegarmo.com | Restart-PSIISPool Description ----------- If url.matthewjdegarmo.com is found, this will prompt to recycle the app pool it is using. You should only do this if you KNOW that this is the only site on the found Application Pool. .NOTES Author: matthewjdegarmo GitHub: https://github.com/matthewjdegarmo Sponsor: https://github.com/sponsors/matthewjdegarmo #> Function Start-PSIISPool() { [CmdletBinding( SupportsShouldProcess, ConfirmImpact = "High" )] Param( [Parameter(ValueFromPipelineByPropertyName)] [Alias('Server', 'PSComputerName')] [System.String[]] $ComputerName = $env:COMPUTERNAME, [Parameter(ValueFromPipelineByPropertyName)] [Alias('ApplicationPool')] [System.String] $Name, [Parameter(ValueFromPipelineByPropertyName)] [Alias('Sitename', 'Applications')] [System.String[]] $Sites, [switch]$PassThru ) Begin {} Process { #Region Dynamic Pipeline handling if ($_ -is [System.Object]) { $Pool = @{ # The below If Else statements are version of these Turnary commands. # Windows PowerShell can't handle turnary operators. Leaving these here for reference to the below logic. # ComputerName = ($_.Server) ? $_.Server : (($_.ComputerName) ? $_.ComputerName : $_.PSComputerName).ToUpper() # Name = ($_.ApplicationPool) ? $_.ApplicationPool : $_.Name # Sites = ($_.SiteName) ? $_.SiteName : (($_.Applications) ? $_.Applications : $_.Sites) } If ($_.Server) { $Pool['ComputerName'] = $_.Server } Else { If ($_.ComputerName) { $Pool['ComputerName'] = $_.ComputerName } Else { $Pool['ComputerName'] = $_.PSComputerName } } If ($_.ApplicationPool) { $Pool['Name'] = $_.ApplicationPool } Else { $Pool['Name'] = $_.Name } If ($_.SiteName) { $Pool['Sites'] = $_.SiteName } Else { If ($_.Applications) { $Pool['Sites'] = $_.Applications } Else { $Pool['Sites'] = $_.Sites } } } else { $Pool = @{ ComputerName = $ComputerName.ToUpper() Name = $Name } If ($Sites) { $Pool['Sites'] = $Sites.ToUpper() } else { $Pool['Sites'] = (Get-PSIISPool -ComputerName $Pool.ComputerName -Name $Pool.Name).Applications } } #EndRegion Dynamic Pipeline handling if ($PSCmdlet.ShouldProcess($Pool.ComputerName, "Start $($Pool.Name) pool containing sites: $($Pool.Sites)")) { $ScriptBlock = { [CmdletBinding()] Param( $Pool, [switch]$PassThru ) Write-Verbose "$($Pool.ComputerName): Starting Pool: $($Pool.Name)" Import-Module WebAdministration Start-WebAppPool -Name $Pool.Name -ErrorAction SilentlyContinue -PassThru:$PassThru } If (IsLocal $Pool.ComputerName) { & $ScriptBlock -Pool $Pool -PassThru:$PassThru } Else { Invoke-Command -ComputerName $Pool.ComputerName -ScriptBlock $ScriptBlock -ArgumentList $Pool, $PassThru } } } } #EndRegion Start-PSIISPool #Region Start-PSIISSite <# .SYNOPSIS Start an IIS Site. .DESCRIPTION Start an IIS Site. .PARAMETER ComputerName Specify a remote computer to run against. .PARAMETER Name Specify the name of the IIS Site to search for. .PARAMETER PassThru If true, the command will return the IIS information. .EXAMPLE Start-PSIISSite -ComputerName localhost -Name MySite .NOTES Author: matthewjdegarmo GitHub: https://github.com/matthewjdegarmo Sponsor: https://github.com/sponsors/matthewjdegarmo #> Function Start-PSIISSite() { [CmdletBinding( SupportsShouldProcess, ConfirmImpact="High" )] Param( [Parameter(ValueFromPipelineByPropertyName)] [Alias('Server','PSComputerName')] [System.String[]] $ComputerName = $env:COMPUTERNAME, [Parameter(ValueFromPipelineByPropertyName)] [Alias('Sitename')] [System.String] $Name, [switch]$PassThru ) Begin {} Process { if ($_ -is [System.Object]) { $Site = @{ # The below If Else statements are version of these Turnary commands. # Windows PowerShell can't handle turnary operators. Leaving these here for reference to the below logic. # ComputerName = ($_.Server) ? $_.Server : (($_.ComputerName) ? $_.ComputerName : $_.PSComputerName) # Name = ($_.Sitename) ? $_.Sitename : $_.Name } If ($_.Server) { $Site['ComputerName'] = $_.Server } Else { If ($_.ComputerName) { $Site['ComputerName'] = $_.ComputerName } Else { $Site['ComputerName'] = $_.PSComputerName } } If ($_.Sitename) { $Site['Name'] = $_.Sitename } Else { $Site['Name'] = $_.Name } } else { $Site = @{ ComputerName = $ComputerName Name = $Name } } if ($PSCmdlet.ShouldProcess($Site.ComputerName, "Start site: $($Site.Name)")) { $ScriptBlock = { [CmdletBinding()] Param( $Site, [switch]$PassThru ) Import-Module WebAdministration Start-Website -Name $Site.Name -ErrorAction SilentlyContinue -PassThru:$PassThru } $Site.ComputerName | Foreach-Object { If (IsLocal $_) { & $ScriptBlock -Site $Site -PassThru:$PassThru } Else { Invoke-Command -ComputerName $_ -ScriptBlock $ScriptBlock -ArgumentList $Site, $PassThru | Select-Object -ExcludeProperty RunspaceId } } } } } #EndRegion Start-PSIISSite #Region Stop-PSIISPool <# .SYNOPSIS Stop an application pool. .DESCRIPTION Supply the web server and application pool to recycle. .PARAMETER ComputerName Specify the remote server to run against. .PARAMETER Name Specify the pool name to recycle. .PARAMETER Sites Specify the site names that are tied to this pool. This parameter is meant to support Pipeline values, but is not required to specify manually. Example: $Pool | Stop-PSIISPool # $Pool will have Sites information and pass it through the pipeline. Stop-PSIISPool -ComputerName Server1 -Name Pool1 # No site information will be included.. .PARAMETER PassThru If true, the command will return the IIS information. .EXAMPLE PS> Stop-PSIISPool -ComputerName WebServer01 -Name DefaultSitePool Description ----------- This will recycle the DefaultSitePool pool on WebServer01. .EXAMPLE PS> Get-AppPool -ComputerName WebServer01 -Name DefaultSitePool | Stop-PSIISPool Description ----------- This will recycle the DefaultSitePool pool on WebServer01. .EXAMPLE PS> Get-AppPool -ComputerName WebServer01,WebServer02 | Stop-PSIISPool Description ----------- CAUTION: This will recycle ALL app pools on WebServer01 and WebServer02. .EXAMPLE PS> Get-WebsiteInformation url.matthewjdegarmo.com | Stop-PSIISPool Description ----------- If url.matthewjdegarmo.com is found, this will prompt to recycle the app pool it is using. You should only do this if you KNOW that this is the only site on the found Application Pool. .NOTES Author: matthewjdegarmo GitHub: https://github.com/matthewjdegarmo Sponsor: https://github.com/sponsors/matthewjdegarmo #> Function Stop-PSIISPool() { [CmdletBinding( SupportsShouldProcess, ConfirmImpact = "High" )] Param( [Parameter(ValueFromPipelineByPropertyName)] [Alias('Server', 'PSComputerName')] [System.String[]] $ComputerName = $env:COMPUTERNAME, [Parameter(ValueFromPipelineByPropertyName)] [Alias('ApplicationPool')] [System.String] $Name, [Parameter(ValueFromPipelineByPropertyName)] [Alias('Sitename', 'Applications')] [System.String[]] $Sites, [switch]$PassThru ) Begin {} Process { #Region Dynamic Pipeline handling if ($_ -is [System.Object]) { $Pool = @{ # The below If Else statements are version of these Turnary commands. # Windows PowerShell can't handle turnary operators. Leaving these here for reference to the below logic. # ComputerName = ($_.Server) ? $_.Server : (($_.ComputerName) ? $_.ComputerName : $_.PSComputerName).ToUpper() # Name = ($_.ApplicationPool) ? $_.ApplicationPool : $_.Name # Sites = ($_.SiteName) ? $_.SiteName : (($_.Applications) ? $_.Applications : $_.Sites) } If ($_.Server) { $Pool['ComputerName'] = $_.Server } Else { If ($_.ComputerName) { $Pool['ComputerName'] = $_.ComputerName } Else { $Pool['ComputerName'] = $_.PSComputerName } } If ($_.ApplicationPool) { $Pool['Name'] = $_.ApplicationPool } Else { $Pool['Name'] = $_.Name } If ($_.SiteName) { $Pool['Sites'] = $_.SiteName } Else { If ($_.Applications) { $Pool['Sites'] = $_.Applications } Else { $Pool['Sites'] = $_.Sites } } } else { $Pool = @{ ComputerName = $ComputerName.ToUpper() Name = $Name } If ($Sites) { $Pool['Sites'] = $Sites.ToUpper() } else { $Pool['Sites'] = (Get-PSIISPool -ComputerName $Pool.ComputerName -Name $Pool.Name).Applications } } #EndRegion Dynamic Pipeline handling if ($PSCmdlet.ShouldProcess($Pool.ComputerName, "Stop $($Pool.Name) pool containing sites: $($Pool.Sites)")) { $ScriptBlock = { [CmdletBinding()] Param( $Pool, [switch]$PassThru ) Write-Verbose "$($Pool.ComputerName): Stopping Pool: $($Pool.Name)" Import-Module WebAdministration Stop-WebAppPool -Name $Pool.Name -ErrorAction SilentlyContinue -PassThru:$PassThru # Get-PSIISPool -Name $Pool.Name -State 'Stopped' } If (IsLocal $Pool.ComputerName) { & $ScriptBlock -Pool $Pool -PassThru:$PassThru } Else { Invoke-Command -ComputerName $Pool.ComputerName -ScriptBlock $ScriptBlock -ArgumentList $Pool, $PassThru } } } } #EndRegion Stop-PSIISPool |