Application/Application.ps1

#region Copyright & License

# Copyright © 2012 - 2021 François Chabot
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#endregion

using namespace Microsoft.BizTalk.ExplorerOM
using namespace Microsoft.BizTalk.Operations

Set-StrictMode -Version Latest

<#
.SYNOPSIS
    Asserts the existence of a Microsoft BizTalk Server Application.
.DESCRIPTION
    This command will throw if the Microsoft BizTalk Server Application does not exist and will silently complete
    otherwise.
.PARAMETER Name
    The name of the Microsoft BizTalk Server Application.
.PARAMETER References
    The name of the Microsoft BizTalk Server Applications that are to be referenced by the one whose existence is
    tested.
.PARAMETER ManagementDatabaseServer
    The name of the SQL server hosting the management database; it defaults to MSBTS_GroupSetting.MgmtDbServerName.
.PARAMETER ManagementDatabaseName
    The name of the management database; it defaults to MSBTS_GroupSetting.MgmtDbName.
.EXAMPLE
    PS> Assert-BizTalkApplication
.EXAMPLE
    PS> Assert-BizTalkApplication -Name 'BizTalk.System'
.NOTES
    © 2020 be.stateless.
#>

function Assert-BizTalkApplication {
    [CmdletBinding()]
    [OutputType([void])]
    param(
        [Parameter(Position = 0, Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Name,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string[]]
        $References,

        [Parameter(Position = 1, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ManagementDatabaseServer = (Get-BizTalkGroupMgmtDbServer),

        [Parameter(Position = 2, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ManagementDatabaseName = (Get-BizTalkGroupMgmtDbName)
    )
    Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
    if (-not(Test-BizTalkApplication @PSBoundParameters)) {
        if ($References | Test-None) {
            throw "Microsoft BizTalk Server Application '$Name' does not exist."
        } else {
            throw "Microsoft BizTalk Server Application '$Name' does not exist or some the required application refereces '$($References -join ''', ''')' are missing."
        }
    }
    Write-Verbose -Message "Microsoft BizTalk Server Application '$Name' exists."
}

<#
.SYNOPSIS
    Gets the Microsoft BizTalk Server Applications.
.DESCRIPTION
    Gets either one or all of the Microsoft BizTalk Server Applications as Microsoft.BizTalk.ExplorerOM.Application
    objects.
.PARAMETER Name
    The name of the Microsoft BizTalk Server Application.
.PARAMETER ManagementDatabaseServer
    The name of the SQL server hosting the management database; it defaults to MSBTS_GroupSetting.MgmtDbServerName.
.PARAMETER ManagementDatabaseName
    The name of the management database; it defaults to MSBTS_GroupSetting.MgmtDbName.
.OUTPUTS
    Returns the Microsoft BizTalk Server Applications.
.EXAMPLE
    PS> Get-BizTalkApplication
.EXAMPLE
    PS> Get-BizTalkApplication -Name 'BizTalk.System'
.NOTES
    © 2020 be.stateless.
#>

function Get-BizTalkApplication {
    [CmdletBinding()]
    [OutputType([Microsoft.BizTalk.ExplorerOM.Application[]])]
    param(
        [Parameter(Position = 0, Mandatory = $false)]
        [AllowEmptyString()]
        [AllowNull()]
        [string]
        $Name,

        [Parameter(Position = 1, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ManagementDatabaseServer = (Get-BizTalkGroupMgmtDbServer),

        [Parameter(Position = 2, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ManagementDatabaseName = (Get-BizTalkGroupMgmtDbName)
    )
    Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
    Use-Object ($catalog = Get-BizTalkCatalog $ManagementDatabaseServer $ManagementDatabaseName) {
        if ([string]::IsNullOrWhiteSpace($Name)) {
            $catalog.Applications
        } else {
            $catalog.Applications[$Name]
        }
    }
}

function New-BizTalkApplication {
    [CmdletBinding(SupportsShouldProcess = $true)]
    [OutputType([Microsoft.BizTalk.ExplorerOM.Application])]
    param(
        [Parameter(Position = 0, Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Name,

        [Parameter(Position = 1, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Description,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string[]]
        $References
    )
    Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
    if (Test-BizTalkApplication -Name $Name) {
        Write-Information -MessageData "`t Microsoft BizTalk Server Application '$Name' has already been created."
    } elseif ($PsCmdlet.ShouldProcess($globalMessages.Should_Target, "Creating application '$Name'")) {
        Write-Information -MessageData "`t Creating Microsoft BizTalk Server Application '$Name'..."
        Use-Object ($catalog = Get-BizTalkCatalog ) {
            try {
                $application = $catalog.AddNewApplication()
                $application.Name = $Name
                if (![string]::IsNullOrWhiteSpace($Description)) { $application.Description = $Description }
                if ($References | Test-Any) {
                    $References | ForEach-Object -Process {
                        Assert-BizTalkApplication -Name $_
                        $dependantApplication = $catalog.Applications[$_]
                        Write-Information -MessageData "`t Adding Reference to Microsoft BizTalk Server Application '$_' from Microsoft BizTalk Server Application '$Name'."
                        $application.AddReference($dependantApplication)
                    }
                }
                $catalog.SaveChanges()
                $application
            } catch {
                $catalog.DiscardChanges()
                throw
            }
        }
        Write-Information -MessageData "`t Microsoft BizTalk Server Application '$Name' has been created."
    }
}

function Remove-BizTalkApplication {
    [CmdletBinding(SupportsShouldProcess = $true)]
    [OutputType([void])]
    param(
        [Parameter(Position = 0, Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Name
    )
    Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
    if (-not(Test-BizTalkApplication -Name $Name)) {
        Write-Information -MessageData "`t Microsoft BizTalk Server Application '$Name' has already been removed."
    } elseif ($PsCmdlet.ShouldProcess($globalMessages.Should_Target, "Removing application '$Name'")) {
        Write-Information -MessageData "`t Removing Microsoft BizTalk Server Application '$Name'..."
        Invoke-Tool -Command { BTSTask RemoveApp -ApplicationName:`"$Name`" }
        Write-Information -MessageData "`t Microsoft BizTalk Server Application '$Name' has been removed."
    }
}

function Start-BizTalkApplication {
    [CmdletBinding()]
    [OutputType([void])]
    param(
        [Parameter(Position = 0, Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Name,

        [Parameter(Position = 1, Mandatory = $false)]
        [ApplicationStartOption]
        $StartOptions = (
            [ApplicationStartOption]::StartAllOrchestrations -bor
            [ApplicationStartOption]::StartAllSendPorts -bor
            [ApplicationStartOption]::StartAllSendPortGroups -bor
            [ApplicationStartOption]::EnableAllReceiveLocations -bor
            [ApplicationStartOption]::DeployAllPolicies
        ),

        [Parameter(Position = 3, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ManagementDatabaseServer = (Get-BizTalkGroupMgmtDbServer),

        [Parameter(Position = 4, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ManagementDatabaseName = (Get-BizTalkGroupMgmtDbName)
    )
    Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
    Use-Object ($catalog = Get-BizTalkCatalog $ManagementDatabaseServer $ManagementDatabaseName) {
        $application = $catalog.Applications[$Name]
        try {
            $application.Start($StartOptions)
            $catalog.SaveChanges()
        } catch {
            $catalog.DiscardChanges()
            throw
        }
    }
}

function Stop-BizTalkApplication {
    [CmdletBinding()]
    [OutputType([void])]
    param(
        [Parameter(Position = 0, Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Name,

        [Parameter(Position = 1, Mandatory = $false)]
        [ApplicationStopOption]
        $StopOptions = (
            [ApplicationStopOption]::UnenlistAllOrchestrations -bor
            [ApplicationStopOption]::UnenlistAllSendPorts -bor
            [ApplicationStopOption]::UnenlistAllSendPortGroups -bor
            [ApplicationStopOption]::DisableAllReceiveLocations -bor
            [ApplicationStopOption]::UndeployAllPolicies
        ),

        [Parameter(Position = 2, Mandatory = $false)]
        [switch]
        $TerminateServiceInstances,

        [Parameter(Position = 3, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ManagementDatabaseServer = (Get-BizTalkGroupMgmtDbServer),

        [Parameter(Position = 4, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ManagementDatabaseName = (Get-BizTalkGroupMgmtDbName)
    )
    Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
    Use-Object ($controller = Get-BizTalkController $ManagementDatabaseServer $ManagementDatabaseName) {
        if ($TerminateServiceInstances) {
            $controller.GetServiceInstances() |
                ForEach-Object -Process { $_ -as [MessageBoxServiceInstance] } |
                Where-Object -FilterScript { $_.Application -eq $Name -and ($_.InstanceStatus -band ([InstanceStatus]::RunningAll -bor [InstanceStatus]::SuspendedAll)) } |
                ForEach-Object -Process {
                    Write-Information -MessageData "Terminating service instance ['$($_.Class)', '$($_.ID)']."
                    result = $controller.TerminateInstance($_.ID)
                    if (result -ne [CompletionStatus]::Succeeded -and $_.Class -ne [ServiceClass::RoutingFailure]) {
                        throw "Cannot stop application '$Name': failed to terminate service instance ['$($_.Class)', '$($_.ID)']."
                    }
                }
        }
        $hasInstance = $controller.GetServiceInstances() |
            ForEach-Object -Process { $_ -as [MessageBoxServiceInstance] } |
            Where-Object -FilterScript { $_.Application -eq $Name } |
            Test-Any
        if ($hasInstance) {
            throw "Cannot stop application '$Name' because it has running service instances."
        }
    }
    Use-Object ($catalog = Get-BizTalkCatalog $ManagementDatabaseServer $ManagementDatabaseName) {
        $application = $catalog.Applications[$Name]
        try {
            $application.Stop($StopOptions)
            $catalog.SaveChanges()
        } catch {
            $catalog.DiscardChanges()
            throw
        }
    }
}

<#
.SYNOPSIS
    Tests the existence of a Microsoft BizTalk Server Application.
.DESCRIPTION
    Tests the existence of a Microsoft BizTalk Server Application.
.PARAMETER Name
    The name of the Microsoft BizTalk Server Application.
.PARAMETER References
    The name of the Microsoft BizTalk Server Applications that are to be referenced by the one whose existence is
    tested.
.PARAMETER ManagementDatabaseServer
    The name of the SQL server hosting the management database; it defaults to MSBTS_GroupSetting.MgmtDbServerName.
.PARAMETER ManagementDatabaseName
    The name of the management database; it defaults to MSBTS_GroupSetting.MgmtDbName.
.OUTPUTS
    Returns $true if the Microsoft BizTalk Server Application exists; $false otherwise.
.EXAMPLE
    PS> Test-BizTalkApplication
.EXAMPLE
    PS> Test-BizTalkApplication -Name 'BizTalk.System'
.NOTES
    © 2020 be.stateless.
#>

function Test-BizTalkApplication {
    [CmdletBinding()]
    [OutputType([bool])]
    param(
        [Parameter(Position = 0, Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Name,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string[]]
        $References,

        [Parameter(Position = 1, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ManagementDatabaseServer = (Get-BizTalkGroupMgmtDbServer),

        [Parameter(Position = 2, Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ManagementDatabaseName = (Get-BizTalkGroupMgmtDbName)
    )
    Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
    Use-Object ($catalog = Get-BizTalkCatalog $ManagementDatabaseServer $ManagementDatabaseName) {
        $application = $catalog.Applications[$Name]
        if ($null -ne $application) {
            if ($References | Test-Any) {
                $actualReferences = @($application.References | ForEach-Object -Process { $_.Name })
                $References | Where-Object -FilterScript { $_ -notin $actualReferences } | Test-None
            } else {
                $true
            }
        } else {
            $false
        }
    }
}

# SIG # Begin signature block
# MIIJEgYJKoZIhvcNAQcCoIIJAzCCCP8CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU0hDn/nzqiH6mZjDLgVJdgsaS
# /5mgggWhMIIFnTCCA1GgAwIBAgIQKBOAjgMDO55A7UJ/k/g5nTBBBgkqhkiG9w0B
# AQowNKAPMA0GCWCGSAFlAwQCAQUAoRwwGgYJKoZIhvcNAQEIMA0GCWCGSAFlAwQC
# AQUAogMCASAwJjEkMCIGA1UEAwwbaWNyYWZ0c29mdHdhcmVAc3RhdGVsZXNzLmJl
# MB4XDTIwMDYyMzExNDM1NloXDTIxMDYyMzEyMDM1NlowJjEkMCIGA1UEAwwbaWNy
# YWZ0c29mdHdhcmVAc3RhdGVsZXNzLmJlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
# MIICCgKCAgEAmQcb0GwlBHBHBJZ9vNM8EewN7T+nhsWVU0WBoWnIw6UAT99Rw9x5
# RcfOQU2hxqKmR1k+iI6B+qddpTC3VLSChA/mh1P4pCDDsZeyR/0nn/r/DezhDe8x
# 5jckjR88KSRcgDoh0kLjgfrToDpx9EvBcwXmNJKDwBIWu5SBvk04beU4XO7OHjBo
# g0kMaHxCZc9HcWfdzBefP+fbVzu6f1j1WgEqZn9sr1ML2ulHRdu26+56xGq9RZGJ
# vXyY1mY+K5mqBcET+1bV2pZnBrM3Gc/hlmvTkwrC0ZGBALLZWZqqpLVrDCY5eoHP
# w2C0kA4JzK4Q1o218s+wXbuDcjYRIZqBSwI8fizR/4DS+6dEjfa3kzs2z/MrkJOk
# hJ06tiMSRr55tX1DR8NwVLdiNqZYvs4zP2ZNRMMI8uFCjkP/Wn1hfBr+GSPlgdLq
# 2TFishY2pj5O1WlE/tCz+B0YLhPWdfbVEp8kB3fGBsVf7uw4STK/wDA1MYRIHikt
# w+K9gtdf0eIR9dYX9CMwoDN2TNLK6vnCWMrzWFe5EOU3/oljUBkyQT838a5A6wMu
# cGeu7Cwjdigylt7ULaTglL7ORIyaRbzkltxd+1oaQ21kjl4ef0ZD2gWLj7bwrZR+
# KWCfmaHFoZlVRKNPtScuyOnilPGGZ6T7SNuwVxSXFRtbp+cQea4UxxUCAwEAAaNf
# MF0wDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMBcGA1UdEQQQ
# MA6CDHN0YXRlbGVzcy5iZTAdBgNVHQ4EFgQUq4sCoE2IqN4K4uwNuibjqd5yNNQw
# QQYJKoZIhvcNAQEKMDSgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDAN
# BglghkgBZQMEAgEFAKIDAgEgA4ICAQBR98amLpANKFlc7mPlkaV4ZtS2uTmbJ6dO
# qzyWKJ2yTmv7U9yq8PdEH9mPJlxYvGyNgxqHoocKv1SdjgYh27SM8pDnsfU2NpER
# 6K/3sICy6Orh9vhC+U18Bp93WoLEezolaBcF0co3/o+HazOvs/2zBFONFHMkef9/
# 3Bipm0sd95teHo53vLKViHbjSmoGxYsvJJiYITB4Zeo6xgUAmwcUpL1To62Lb3RP
# CDLKZQ5h8Ir07nncV4HLq+0qF3+G9Y0IXHJv6Qcr/XTTLo0J877HRqS37WJcgF8+
# 2nbZbqO9NVvp14A4nTqpeDFmzewDU33hiZvzuLHBj//OgLgGZ9lJPxCu0tVxfFWZ
# INHg1YHp3lMaAw00Q3tb/vhc5kE6Kl7FnXnUTsu4j+vUoaFMWhYezoyn9m4rD+xN
# RITrbLPZdWAZvVOJ8ehmswRhfiMZ1npwbrk7KU1UTsmMS7PHREWSyUM28WlMFf2i
# ut8TlY/MV/adUGr2GpqBWhxp5DRgfl1uamKm2wFlCra3/kReVlQgC/Bbod2JOgJW
# t8zCbO4nJx+fJYwM9RG70h/TmuqzP8uChsHtKcgs2YtXmSm12JZakXY4IflInI7p
# ddDEs9UOfsWXDsqpvmFQZbwgGeNeEsPk3Fdm1MzDtS9PBXMk4jGGXNzEsVUgwf42
# 2HuDWeX/4jGCAtswggLXAgEBMDowJjEkMCIGA1UEAwwbaWNyYWZ0c29mdHdhcmVA
# c3RhdGVsZXNzLmJlAhAoE4COAwM7nkDtQn+T+DmdMAkGBSsOAwIaBQCgeDAYBgor
# BgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEE
# MBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBSM
# c05tEQFlZXJzqEgtOuado3x+EjANBgkqhkiG9w0BAQEFAASCAgAgFiyKwSJ3eryk
# gNJo1rpAKvCeRA1ewonEH6qDNe207hkLGIiCR55hj6rqZU32zOntpOAG3Wdp6R0X
# Z2+lWQ4ls+aqmT78O7vFYL+P5kAOmFcq1WhLnvHBWo0iALnV9oxm2+MqkTMKFMG2
# OxuKPpqda+3F4o9w30XrPy4AVzWll19JHPdo1Gqn6uVmW5CQc45vsgDyF3KHPo74
# LxWlWK6nCznGpGuNg0Vpjy7s7XXnM2A1rX7B1xcVQ0zAp/fKyKkMPgUFr99GPSWv
# x8vwDaYNAEPpzskiLrGIpuWAcl7iFwvQxutEE6N67VnC339cuSCYr/2cvsO9qSQU
# sYpAPQh+G9/HKCHggLuBV1JxjB6YPhH8QuyiP6sEY9Jtym46tqcu3RzFwJbDk9KV
# w8NUdbnXjMH2RNliVbyTie0YdHrNnF9t+63cfjeevS3/3FtMZfmkyiJVUazZf/yR
# DRlI9wtib3hBUKLtqf2YZUFO/zIdkg5uB73g8TngpPu5IM8vfNOu89CD5xAfSjuJ
# IAYS72PWujXhYBNMge4Mqga3+pqRB3AAcJpYH/2FLIhO4pfARKMdv+vWTxrq5EGC
# n6o2GHTdCVZqeTNwJXn6fAlUe9/2vpIeavf0uC/6vuilhDE+U4MjeydUTOGTBqVU
# H7Y3ONQ58LU62pxfDatZvsVpxl+cxw==
# SIG # End signature block