【问题标题】:PowerShell BizTalk scripts WITHOUT using BizTalk provider for PowerShellPowerShell BizTalk 脚本不使用 PowerShell 的 BizTalk 提供程序
【发布时间】:2011-07-31 12:53:54
【问题描述】:

一段时间以来,我一直在使用 Codeplex 的优秀 BizTalk Provider for PowerShell。然而,在我的新公司,构建团队不习惯使用它,所以我需要重写所有方便的配置脚本以不使用它。

我已经重做了其中的大部分,但在查找如何执行以下两件事的示例时遇到了一些问题:

  1. 创建主机实例
  2. 创建发送/接收适配器处理程序

谁能告诉我如何在没有 BizTalk 的 PowerShell 提供程序的情况下执行这些操作的示例?我做了一些查找,现在似乎每个人都在使用它。

提前非常感谢。

【问题讨论】:

  • 真正的问题不是不愿意使用 BizTalk PowerShell 提供程序,什么时候可以使用自定义脚本?有什么反对意见?

标签: powershell biztalk


【解决方案1】:

Sandro Pereira 还有一个非常有用的博客,其中包含处理主机、主机实例和适配器处理程序的功能

还有Tomas Restrepo在GitHub上设置

他们似乎没有提到的是删除 BizTalk 主机......

function Remove-BizTalkHost(
    [string] $hostName)
{
    try
    {
        $strQuery = "MSBTS_HostSetting.Name='$hostName'";
        $objPath = New-Object System.Management.ManagementPath
        $objPath.Path = $strQuery

        [System.Management.ManagementObject]$objHostSetting = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_HostSetting").CreateInstance()
        $objHostSetting.Path = $objPath

        $objHostSetting.Delete()

        Write-Host "Host $hostName was successfully deleted" -ForegroundColor DarkGreen
    }
    catch [System.Management.Automation.RuntimeException]
    {
        if ($_.Exception.Message.Contains("No instance was found with the specified key") -eq $true)
        {
            Write-Host "$hostName can't be deleted because already removed from the BizTalk group." -ForegroundColor DarkRed
        }
        else
        {
            Write-Error "$hostName host could not be deleted: $_.Exception.ToString()"
        }
    }
}

【讨论】:

  • Delete 不是 PowerShell 中支持的动词。如果您使用动词-名词的 PowerShell 约定,仅使用已知动词,则此 Cmdlet 将称为 Remove-BizTalkHost。您可以使用Get-Verb 查找正确的动词。
【解决方案2】:

看起来您从 Santhosh Benjamin 的脚本中借用了反射来提交 PutOptions:

    [Type[]] $targetTypes = New-Object System.Type[] 1
    $targetTypes[0] = $putOptions.GetType()
    $sysMgmtAssemblyName = “System.Management”
    $sysMgmtAssembly = [System.Reflection.Assembly]::LoadWithPartialName($sysMgmtAssemblyName)
    $objHostSettingType = $sysMgmtAssembly.GetType(“System.Management.ManagementObject”)
    [Reflection.MethodInfo] $methodInfo = $objHostSettingType.GetMethod(“Put”,$targetTypes)
    $methodInfo.Invoke($objHostSetting,$putOptions)

我用我目前正在使用的几个脚本对此进行了测试,并发现(通过纯粹的顽固)你可以简单地在对象上使用 Put 方法,就像你在 C# 中习惯的那样:

    $objHostSetting.Put($putOptions)

干杯, 查尔斯。

【讨论】:

    【解决方案3】:

    好的,如果其他人需要,这是我完成的 hacky powershell 函数:

    function write-WarnMessage([string]$message) {
        Write-Host $(Get-Date) $message -ForegroundColor Yellow
    }
    
    function write-SucessMessage([string]$message) {
        Write-Host $(Get-Date) $message -ForegroundColor Green
    }
    
    function write-InfoMessage([string]$message) {
        Write-Host $(Get-Date) $message -ForegroundColor Blue -BackgroundColor White
    }
    
    function write-ErrorMessage ([string]$message) {
        Write-Host $(Get-Date) $message -ForegroundColor Red
    }
    
    # Gets the execution directory
    function Get-ScriptDirectory 
    {
        $Invocation = (Get-Variable MyInvocation -Scope 1).Value
        Split-Path $Invocation.MyCommand.Path
    }
    
    function Delete-Bts-Receive-Handler ( [string]$adapter, [string]$hostName )
    {   
        try
        {
            [System.Management.ManagementObject]$objHandler = get-wmiobject 'MSBTS_ReceiveHandler' -namespace 'root\MicrosoftBizTalkServer' -filter "HostName='$hostName' AND AdapterName='$adapter'"
            $objHandler.Delete()
            write-SucessMessage "Deleted $adapter receive handler for $hostName"
        }
        catch [System.Management.Automation.RuntimeException]
        {
            if ($_.Exception.Message -eq "You cannot call a method on a null-valued expression.")
            {
                write-WarnMessage "$adapter receive handler for $hostName does not exist"
            }
            elseif ($_.Exception.Message.IndexOf("Cannot delete a receive handler that is used by") -ne -1)
            {
                write-WarnMessage "$adapter receive handler for $hostName is in use. Cannot delete."
            }
            else
            {
                write-Error "$adapter receive handler for $hostName could not be deleted: $_.Exception.ToString()"
            }
        }
    }
    
    function Delete-Bts-Send-Handler ( [string]$adapter, [string]$hostName )
    {
        try
        {
            [System.Management.ManagementObject]$objHandler = get-wmiobject 'MSBTS_SendHandler2' -namespace 'root\MicrosoftBizTalkServer' -filter "HostName='$hostName' AND AdapterName='$adapter'"
            $objHandler.Delete()
            write-SucessMessage "Deleted $adapter send handler for $hostName"
        }
        catch [System.Management.Automation.RuntimeException]
        {
            if ($_.Exception.Message -eq "You cannot call a method on a null-valued expression.")
            {
                write-WarnMessage "$adapter send handler for $hostName does not exist"
            }
            elseif ($_.Exception.Message.IndexOf("Cannot delete a send handler that is used by") -ne -1)
            {
                write-WarnMessage "$adapter send handler for $hostName is in use. Cannot delete."
            }
            else
            {
                write-Error "$adapter send handler for $hostName could not be deleted: $_.Exception.ToString()"
            }
        }
    }
    
    function Delete-Bts-Instance( [string]$hostName, [string]$Server )
    {
        try
        {
            # Unintall
            [System.Management.ManagementObject]$objHostInstance = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_HostInstance").CreateInstance()
            $name = "Microsoft BizTalk Server " + $hostName + " " + $Server
            $objHostInstance["Name"] = $name
            $objHostInstance.Uninstall()
    
            # Unmap
            [System.Management.ManagementObject]$objServerHost = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_ServerHost").CreateInstance()
            $objServerHost["HostName"] = $hostName
            $objServerHost["ServerName"] = $Server
            $objServerHost.Unmap()
    
            write-SucessMessage "Deleted host instance for $hostName on $Server"
        }
        catch [System.Management.Automation.RuntimeException]
        {
            write-Error "$hostName host instance on server $Server could not be deleted: $_.Exception.ToString()"
        }
    }
    
    function Stop-Bts-HostInstance ( [string] $HostName, [string] $Server )
    {
        try
        {
            $filter = "HostName = '" + $HostName + "' and RunningServer = '" + $Server + "'"
            $HostInstance = get-wmiobject "MSBTS_HostInstance" -namespace "root\MicrosoftBizTalkServer" -filter $filter
            $HostInstanceState = $HostInstance.GetState().State
    
            write-InfoMessage "Current state of $HostName instance on server $Server : $HostInstanceState (1=Stopped, 2=Start pending, 3=Stop pending, 4=Running, 8=Unknown)"
    
            if ($HostInstanceState -eq 4) 
            {
                $HostInstance.Stop() 
                $HostInstanceState = $HostInstance.GetState().State
                write-SucessMessage "New state of $HostName instance on server $Server: $HostInstanceState (1=Stopped, 2=Start pending, 3=Stop pending, 4=Running, 8=Unknown)"
            }
            else
            {
                $HostInstanceState = $HostInstance.GetState().State
                write-WarnMessage "Failed to stop host instance $HostName on server $Server because host instance state $HostInstanceState was not the expected value of 4 (running)"
            }
        }
        catch [System.Management.Automation.RuntimeException]
        {
            write-Error "$hostName host instance could not be stopped on $Server : $_.Exception.ToString()"
        }
    }
    
    function Delete-Bts-Host ( [string]$hostName )
    {
        # TODO: This only works intermittently
    
        try
        {
            [System.Management.ManagementObject]$objHostSetting = get-wmiobject 'MSBTS_HostSetting' -namespace 'root\MicrosoftBizTalkServer' -filter "HostName='$hostName'"
            $objHostSetting.Delete()
            write-SucessMessage "Deleted host $hostName"
        }
        catch [System.Management.Automation.RuntimeException]
        {
            write-Error "$hostName host could not be deleted: $_.Exception.ToString()"
        }
    }
    
    # function to create BizTalk host
    function Create-Bts-Host(
        [string]$hostName, 
        [int]$hostType, 
        [string]$ntGroupName, 
        [bool]$authTrusted, 
        [bool]$tracking, 
        [bool]$32BitOnly)
    {
        try
        {
            [System.Management.ManagementObject]$objHostSetting = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_HostSetting").CreateInstance()
    
            $objHostSetting["Name"] = $hostName
            $objHostSetting["HostType"] = $hostType
            $objHostSetting["NTGroupName"] = $NTGroupName
            $objHostSetting["AuthTrusted"] = $authTrusted
            $objHostSetting["IsHost32BitOnly"] = $32BitOnly 
            $objHostSetting["HostTracking"] = $tracking
    
            $putOptions = new-Object System.Management.PutOptions
            $putOptions.Type = [System.Management.PutType]::CreateOnly;
    
            [Type[]] $targetTypes = New-Object System.Type[] 1
            $targetTypes[0] = $putOptions.GetType()
    
            $sysMgmtAssemblyName = "System.Management"
            $sysMgmtAssembly = [System.Reflection.Assembly]::LoadWithPartialName($sysMgmtAssemblyName)
            $objHostSettingType = $sysMgmtAssembly.GetType("System.Management.ManagementObject")
    
            [Reflection.MethodInfo] $methodInfo = $objHostSettingType.GetMethod("Put", $targetTypes)
            $methodInfo.Invoke($objHostSetting, $putOptions)
    
            write-SucessMessage "Host $hostName created"
        }
        catch [System.Management.Automation.RuntimeException]
        {
            write-Error "$hostName host could not be created: $_.Exception.ToString()"
        }
    }
    
    function Update-Bts-Host ( 
        [string]$hostName, 
        [int]$hostType, 
        [string]$ntGroupName, 
        [bool]$authTrusted, 
        [bool]$tracking, 
        [bool]$32BitOnly)
    {
        try
        {
            [System.Management.ManagementObject]$objHostSetting = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_HostSetting").CreateInstance()
    
            $objHostSetting["Name"] = $hostName
            $objHostSetting["HostType"] = $hostType
            $objHostSetting["NTGroupName"] = $ntGroupName
            $objHostSetting["AuthTrusted"] = $authTrusted
            $objHostSetting["IsHost32BitOnly"] = $32BitOnly 
            $objHostSetting["HostTracking"] = $tracking
    
            $putOptions = new-Object System.Management.PutOptions
            $putOptions.Type = [System.Management.PutType]::UpdateOnly; # This tells WMI it's an update.
    
            [Type[]] $targetTypes = New-Object System.Type[] 1
            $targetTypes[0] = $putOptions.GetType()
    
            $sysMgmtAssemblyName = "System.Management"
            $sysMgmtAssembly = [System.Reflection.Assembly]::LoadWithPartialName($sysMgmtAssemblyName)
            $objHostSettingType = $sysMgmtAssembly.GetType("System.Management.ManagementObject")
    
            [Reflection.MethodInfo] $methodInfo = $objHostSettingType.GetMethod("Put", $targetTypes)
            $methodInfo.Invoke($objHostSetting, $putOptions)
    
            write-SucessMessage "Host updated"
        }
        catch [System.Management.Automation.RuntimeException]
        {
            write-Error "$hostName host could not be updated: $_.Exception.ToString()"
        }
    }
    
    # function to create BizTalk send adapter handler
    function Create-Bts-SendHandler([string]$adapter, [string]$hostName)
    {
        try
        {
            [System.Management.ManagementObject]$objSendHandler = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_SendHandler2").CreateInstance()
    
            $objSendHandler["AdapterName"] = $adapter
            $objSendHandler["HostName"] = $hostName
            $objSendHandler["IsDefault"] = $false
    
            $putOptions = new-Object System.Management.PutOptions
            $putOptions.Type = [System.Management.PutType]::CreateOnly;
    
            [Type[]] $targetTypes = New-Object System.Type[] 1
            $targetTypes[0] = $putOptions.GetType()
    
            $sysMgmtAssemblyName = "System.Management"
            $sysMgmtAssembly = [System.Reflection.Assembly]::LoadWithPartialName($sysMgmtAssemblyName)
            $objSendHandlerType = $sysMgmtAssembly.GetType("System.Management.ManagementObject")
    
            [Reflection.MethodInfo] $methodInfo = $objSendHandlerType.GetMethod("Put", $targetTypes)
            $methodInfo.Invoke($objSendHandler, $putOptions)
    
            write-SucessMessage "Send handler created for $adapter / $hostName"
        }
        catch [System.Management.Automation.RuntimeException]
        {
            write-Error "Send handler for $adapter / $hostName could not be created: $_.Exception.ToString()"
        }
    }
    
    # function to create BizTalk receive adapter handler
    function Create-Bts-ReceiveHandler([string]$adapter, [string]$hostName)
    {
        try
        {
            [System.Management.ManagementObject]$objReceiveHandler = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_ReceiveHandler").CreateInstance()
    
            $objReceiveHandler["AdapterName"] = $adapter
            $objReceiveHandler["HostName"] = $hostName
    
            $putOptions = new-Object System.Management.PutOptions
            $putOptions.Type = [System.Management.PutType]::CreateOnly;
    
            [Type[]] $targetTypes = New-Object System.Type[] 1
            $targetTypes[0] = $putOptions.GetType()
    
            $sysMgmtAssemblyName = "System.Management"
            $sysMgmtAssembly = [System.Reflection.Assembly]::LoadWithPartialName($sysMgmtAssemblyName)
            $objReceiveHandlerType = $sysMgmtAssembly.GetType("System.Management.ManagementObject")
    
            [Reflection.MethodInfo] $methodInfo = $objReceiveHandlerType.GetMethod("Put", $targetTypes)
            $methodInfo.Invoke($objReceiveHandler, $putOptions)
    
            write-SucessMessage "Receive handler created for $adapter / $hostName"
        }
        catch [System.Management.Automation.RuntimeException]
        {
            write-Error "Receive handler for $adapter / $hostName could not be created: $_.Exception.ToString()"
        }
    }
    
    # function to create BizTalk host instance
    function Create-Bts-Instance([string]$hostName, [string]$login, [string]$password, [string]$Server)
    {
        try
        {
            [System.Management.ManagementObject]$objServerHost = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_ServerHost").CreateInstance()
    
            $objServerHost["HostName"] = $hostName
            $objServerHost["ServerName"] = $Server
            $objServerHost.Map()
    
            [System.Management.ManagementObject]$objHostInstance = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_HostInstance").CreateInstance()
    
            $name = "Microsoft BizTalk Server " + $hostName + " " + $Server
            $objHostInstance["Name"] = $name
            $objHostInstance.Install($Login, $Password, $True)
    
            write-SucessMessage "Created host instance for $hostName on $Server"
        }
        catch [System.Management.Automation.RuntimeException]
        {
            write-Error "$hostName host instance on server $Server could not be created: $_.Exception.ToString()"
        }
    }
    
    function Start-Bts-HostInstance ( [string] $HostName, [string] $Server )
    {
        try
        {
            $filter = "HostName = '" + $HostName + "' and RunningServer = '" + $Server + "'"
            $HostInstance = get-wmiobject "MSBTS_HostInstance" -namespace "root\MicrosoftBizTalkServer" -filter $filter
            $HostInstanceState = $HostInstance.GetState().State
    
            write-InfoMessage "Current state of $HostName instance on server $Server: $HostInstanceState (1=Stopped, 2=Start pending, 3=Stop pending, 4=Running, 8=Unknown)"
    
            if ($HostInstanceState -eq 1) 
            {
                $HostInstance.Start() 
                $HostInstanceState = $HostInstance.GetState().State
                write-SucessMessage "New state of $HostName instance on server $Server: $HostInstanceState (1=Stopped, 2=Start pending, 3=Stop pending, 4=Running, 8=Unknown)"
            }
            else
            {
                $HostInstanceState = $HostInstance.GetState().State
                write-WarnMessage "Failed to start host instance $HostName on server $Server because host instance state $HostInstanceState was not the expected value of 1 (stopped)"
            }
        }
        catch [System.Management.Automation.RuntimeException]
        {
            write-Error "$hostName host instance could not be started on $Server : $_.Exception.ToString()"
        }
    }
    
    function Install-BTSMsi ( [string]$bts_application, [string]$msi_package, [string]$install_env ) 
    {
        write-InfoMessage "Installing $msi_package in $bts_application for $install_env"
    
        BTSTask ImportApp /ApplicationName:$bts_application /Package:$msi_package /Overwrite /Environment:$install_env
    
        if ($LASTEXITCODE -ne 0) {
            write-ErrorMessage "Failed to Import MSI $msi_package"
        } 
        else
        {
            write-SucessMessage "Installed $bts_application for $install_env"
        }
    }
    
    function Remove-BTSApplication  ( [string]$appServer, [string]$appDatabase, [string]$appName ) 
    {
        write-InfoMessage "Uninstalling Application: $appName "
        BTSTask RemoveApp /Server:"$appServer" /ApplicationName:"$appName" /Database:"$appDatabase"  #| out-null
    
        if ($LASTEXITCODE -ne 0) {
            write-ErrorMessage "Failed to remove $appServer $appName"
        }
        else
        {
            write-SucessMessage "Removed $appName from $appServer"
        }
    } 
    
    # Accesses SSO and will require the build user account to belong to the SSO Admins group. 
    # Also requires Microsoft.BizTalk.ExplorerOM.dll to be loaded.
    function StartStop-BTSApplication ( [string]$appServer, [string]$appName, [string]$appCommand ) 
    { 
        if ( ($appName -eq '') -or ($appName -eq $null) )
        {
            throw 'you must supply the application name'
        }
    
        #write-InfoMessage " Finding Application: $appServer:$appName "
        $exp = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
        $exp.ConnectionString = Get-BTSConnectionString($appServer) 
        $app = $exp.Applications[$appName] 
    
        if($app -eq $null) 
        { 
            if ($appCommand -eq "stop" )
            {
                write-WarnMessage "WARNING failed to stop $appName"
            }
            else
            {
                write-WarnMessage "FAILED to start $appName"
            }
        } 
        else 
        {
            switch -wildcard ( $app.Status.ToString() )
            {
                'Stopped' 
                {
                    if ($appCommand -eq "start" ) {
                        write-InfoMessage "Starting Application: $appName "
                        $null = $app.Start([Microsoft.BizTalk.ExplorerOM.ApplicationStartOption]::StartAll) 
                        $null = $exp.SaveChanges() 
                        write-SucessMessage " Started Application: $appName "
                    } else {
                        write-InfoMessage "Application Already Stopped: $appName "
                    }
                } 
                '*Started' 
                { 
                    # includes Started and PartiallyStarted
                    if ($appCommand -eq "stop" ) {
                        write-InfoMessage "Stopping Application: $appName "
                        $null = $app.Stop([Microsoft.BizTalk.ExplorerOM.ApplicationStopOption]::StopAll) 
                        $null = $exp.SaveChanges() 
                        write-SucessMessage " Stopped Application: $appName "
                    } else {
                        write-InfoMessage "Application Already Started : $appName "
                    }
                }
                'NotApplicable' 
                {
                    write-InfoMessage "Application doesn't require $appCommand"
                } 
                default
                {
                    $msg = "Unkown STATUS: " + $app.Status
                    write-ErrorMessage $msg
                }
            }
        }
    }
    
    function Get-BTSConnectionString ( [string] $server )
    {
        $group = Get-WmiObject MSBTS_GroupSetting -n root\MicrosoftBizTalkServer -computername $server
        $grpdb = $group.MgmtDBName
        $grpsvr = $group.MgmtDBServerName
        [System.String]::Concat("server=", $grpsvr, ";database=", $grpdb, ";Integrated Security=SSPI")
        write-InfoMessage " Server: $grpsvr - Database  $grpdb"
    } 
    

    【讨论】:

    • PS 以上脚本不适用于 PowerShell 1.0,如果您想使用它们,请升级。
    • 为什么要自定义 Write-XxxMessage 方法?为什么不使用内置的Write-ErrorWrite-WarningWrite-Host 等...?
    • Delete 不是 PowerShell 中支持的动词。如果您使用动词-名词的 PowerShell 约定,只有已知动词,这些 Cmdlet 将被称为 Remove-BizTalkReceiveHandler, ... 您可以使用 Get-Verb 查找正确的动词。
    【解决方案4】:

    即使您不能使用 Powershell 库本身,也没有什么能阻止您检查其源代码以了解它执行这些功能的功能,即与 Microsoft.BizTalk.ExplorerOM 程序集交互。

    【讨论】:

    • 感谢您的回复。我觉得你有点忽略了这一点。我要的是 powershell 示例,而不是 C# 示例,我可以找到很多。
    【解决方案5】:

    对于 2) 你应该查看Microsoft.BizTalk.ExplorerOM

    使用ReceiveHandlerSendHandler 应该可以满足您的需求。

    但是似乎没有办法使用 ExplorerOM 来控制主机实例,只能控制主机。

    【讨论】:

    • 感谢您的回复。我有一个脚本来做主机。在 WMI 中使用 MSBTS_HostSetting。我无法让它与主机实例一起使用。
    猜你喜欢
    • 1970-01-01
    • 2012-02-25
    • 2017-08-13
    • 1970-01-01
    • 2023-03-08
    • 2016-03-21
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多