Application/Application.ps1

#region Copyright & License

# Copyright © 2012 - 2022 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 Reference
   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
   © 2022 be.stateless.
#>

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

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

      [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 ($Reference | 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 references '$($Reference -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
   © 2022 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[]]
      $Reference
   )
   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 ($Reference | Test-Any) {
               $Reference | 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 Reference
   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
   © 2022 be.stateless.
#>

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

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

      [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 ($Reference | Test-Any) {
            $actualReferences = @($application.References | ForEach-Object -Process { $_.Name })
            $Reference | Where-Object -FilterScript { $_ -notin $actualReferences } | Test-None
         } else {
            $true
         }
      } else {
         $false
      }
   }
}

# SIG # Begin signature block
# MIII0QYJKoZIhvcNAQcCoIIIwjCCCL4CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUMUeaKRhugCXENwq/Oyao60wd
# pI2gggVMMIIFSDCCAzCgAwIBAgIJAJkr3mJdTBkUMA0GCSqGSIb3DQEBCwUAMEEx
# PzA9BgNVBAMeNgBpAGMAcgBhAGYAdABzAG8AZgB0AHcAYQByAGUAQABzAHQAYQB0
# AGUAbABlAHMAcwAuAGIAZTAeFw0yMTA2MjUxNDEyMjNaFw00MTA2MjAxNDEyMjNa
# MEExPzA9BgNVBAMeNgBpAGMAcgBhAGYAdABzAG8AZgB0AHcAYQByAGUAQABzAHQA
# YQB0AGUAbABlAHMAcwAuAGIAZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAOeqdUHBv7sxSeX3aj6yPKj7PAvs8izpVXjyEBl5aR8mQneVcXuF53AH7EW1
# 6E5p4+Az5pJPGUD5c3tXhiGMF7vgLhQjO6hlaVBRIqiIYHikNLwMNy6YBMc/QQYM
# rPhqHEFsZ53dkBIIj3M8e3kFcTFA09n25yDtTPDab4nd9yUhc9Qc8+nfpIzfYsoP
# 1pZ3nCzhw6hN2/44v1dkQrG3dRYwt+px65p6NPNZWEJpt4VCJjIFh+lBYJdxm9d4
# X/rAnlHIkbv7liOavWDzgHVabS3hdAWtcDmynm+7+FcZDFqPWNCl3e4SS7xe4s/R
# CKFKA0IsfKkSk9YJlLgeSQIEXUOOWXJAGaLqnRD8xWLZsc4Oi9GZg7XV1mv/S88c
# oztXnwtAN3OOlRKBh2QbomMgxeMO0GvsLE/cq5Q/YKAoz+KGr/7LcZq9jzQ8IPus
# ZvWLeDXmxPiwJjpZc1koLgfGIEX2NStQTT3QmacWr9thrWcKvI+4uBmI4exS9B4a
# R3nV91w5EY+2RoYsHqej9LWwNamO96+jMX9pxprTX+EkLUuMAikw/po8sBC9MUUn
# 5pMWmUv7DCtQOLGGBDDMMMkn4ZcjpCEEdPGHRKfqNnD27ssGtDjiNzfQrsm67toU
# bBwUF+gyJq/YckWquYJhA9ZOFWEADuIwGnsOzsoRvuQyY+p9AgMBAAGjQzBBMA4G
# A1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAzAXBgNVHREEEDAO
# ggxzdGF0ZWxlc3MuYmUwDQYJKoZIhvcNAQELBQADggIBACithYM3qckZRc9+Xbfu
# a6gWr3HwjrW+FHKgjfrcOm8ZnLVapb9xFqsqrRQqd3RXWQDINEGrtI2rSfrzyfoK
# UiTgldIfQNP1ZcGY229d++90t3hdo2mlt05hjYlbMENloJHpsEP0vQZmwOcEimCT
# ex1pymYM+P9pj3j8UD1PT1eIZot6or8fBRl63UybyDSrM7L4UOkkAOniKxWy5pW6
# 6duS8SR+SZpr3Bv44NyXPj0Nv+MIpLmsLrd7XPBFmnGxzY01ZO9vzi9KEhM2wT5i
# jPqHDNOvfPiADtAa+EyUBzdJiqy9heCz/TMZQgMWGwtfqJNxWZmsHcha2anW4Qt+
# mzrLO4GojWoVog9uVSAq+l0a+YQsd1u1kUmm4vgZCFyUA+lEp4LkI7ca2VBHkLPD
# w+u2DoDMRiqFPZjO7BCKjGc0jj9B/qGR3JVt+tqDdB621xXf2YGF2oFvxZQ/keGt
# 0ujfJ+JwN3nCulDAA4773q6KUnfykyrvAgITNbRJL6TngeRKtw9VIJBPxzqMzLpV
# 5ggXNituwLaD1CCBJ1oo9DZHpL9gplXp1wGrelJOTiJhh+pdNsPtRH7CrranWa5h
# LFLuigqin0eewQ5giJ1VaiBVEseOmiZog+27UpFIv40aDzgGL3YxB/Mu0ojwrQtp
# WLmqJCmWnR5qxOm0yK+zNWe0MYIC7zCCAusCAQEwTjBBMT8wPQYDVQQDHjYAaQBj
# AHIAYQBmAHQAcwBvAGYAdAB3AGEAcgBlAEAAcwB0AGEAdABlAGwAZQBzAHMALgBi
# AGUCCQCZK95iXUwZFDAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAA
# oQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4w
# DAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUBH0Kp2eS4I6JW94GIIIHEZFC
# jhswDQYJKoZIhvcNAQEBBQAEggIAO/yOLL/T1lZiagesqrDyK/rH9dZqyAVwMBjt
# fyXeTqLzcj4HZDh7qlWbI5M6JWP9BQcMTnLIBOMV8ufdIRzhVVP/y10+M/acQ73f
# cuhGI9D9hLuzzldfZIhqG3x3VwPc+FucFZIeBw+AFFgtJZ2Z8UniBfOLfkOinX5H
# AkPykQDdlT6vUNWi7pLaR5eJQ4n7xe7rpuS87YwHa6PKTaLtyzRt+Qaw3k0CTPe6
# ZGc7ljPk/6P8vNa/GqSBDEHsYBD6kBng8Bq83KjCql0bfEB78fIN4LWM2kReWaba
# Q3nR1Ud1LfML2c2X1BWfot4QJ4aEyZjNWuAjpl09TsRzP8fYhfqS36+aqGtvTVVF
# m/nJAC6eDopXBvyZoA1xTaV3fXAE60xcHK9TJo3UxOAfbmPZHe4ua0OGH3RE+Nim
# qU/kstx3H6phNtIKZEyC8qFSS8Z+/xlgcE9ufsR/cbYhU9PfyfPLJhRzfj7+3GlQ
# wM81n8KpdoJLdh3TTW9lxIT3p++x0g9/DOOxW7f1CywFQ10fCIBsKjdj5CET4vvi
# OgnY12qIDf3cdDGxhVWsfe2foQlhjoa9CcBy7PEncNGtcRSuRuIKeeMPmOv6ObRE
# NIln/3vJxGkP9sbt/Lsr0ENdbtCSqo9204SPcr/AlGDrR0TsVJQrTXo2kkidfroR
# cYRV7pk=
# SIG # End signature block