Initial version BizTalkStatus Tool.
This commit is contained in:
278
src/BizTalkStatusTool.ps1
Normal file
278
src/BizTalkStatusTool.ps1
Normal file
@@ -0,0 +1,278 @@
|
||||
<#!
|
||||
BizTalk Status Tool (PowerShell only, Remote Server Support)
|
||||
Compatible with:
|
||||
- Windows Server 2019
|
||||
- PowerShell 5.1
|
||||
- BizTalk Server 2020 (WMI under root\MicrosoftBizTalkServer)
|
||||
Author: Copilot
|
||||
Version: 1.3.0
|
||||
#>
|
||||
|
||||
$Global:LogFile = Join-Path (Get-Location) "BizTalkStatusTool.log"
|
||||
|
||||
function Write-Log {
|
||||
param(
|
||||
[string]$Message,
|
||||
[ValidateSet('INFO','WARN','ERROR','DEBUG')]
|
||||
[string]$Level = 'INFO'
|
||||
)
|
||||
$timestamp = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss')
|
||||
$line = "[$timestamp][$Level] $Message"
|
||||
Write-Host $line
|
||||
Add-Content -Path $Global:LogFile -Value $line
|
||||
}
|
||||
|
||||
# ----------------- Helpers: Status mapping & coloring -----------------
|
||||
function Format-Status {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$ArtifactType,
|
||||
[Parameter(Mandatory=$false)]$Value
|
||||
)
|
||||
$result = [ordered]@{ Text=''; Class='neutral'; ConsoleColor='Yellow' }
|
||||
|
||||
switch ($ArtifactType) {
|
||||
'ReceiveLocation' {
|
||||
# Value is boolean (Enabled)
|
||||
$enabled = [bool]$Value
|
||||
if ($enabled) { $result.Text='Enabled'; $result.Class='ok'; $result.ConsoleColor='Green' }
|
||||
else { $result.Text='Disabled'; $result.Class='bad'; $result.ConsoleColor='Red' }
|
||||
}
|
||||
'SendPort' {
|
||||
# MSBTS_SendPort.Status: 1=Bound, 2=Stopped, 3=Started
|
||||
$code = [int]$Value
|
||||
switch ($code) {
|
||||
3 { $result.Text='Started'; $result.Class='ok'; $result.ConsoleColor='Green' }
|
||||
2 { $result.Text='Stopped'; $result.Class='bad'; $result.ConsoleColor='Red' }
|
||||
1 { $result.Text='Bound'; $result.Class='bad'; $result.ConsoleColor='Red' }
|
||||
default { $result.Text="Unknown($code)"; $result.Class='bad'; $result.ConsoleColor='Red' }
|
||||
}
|
||||
}
|
||||
'Orchestration' {
|
||||
# MSBTS_Orchestration.OrchestrationStatus: 1=Unbound, 2=Bound, 3=Stopped, 4=Started
|
||||
$code = [int]$Value
|
||||
switch ($code) {
|
||||
4 { $result.Text='Started'; $result.Class='ok'; $result.ConsoleColor='Green' }
|
||||
3 { $result.Text='Stopped'; $result.Class='bad'; $result.ConsoleColor='Red' }
|
||||
2 { $result.Text='Bound'; $result.Class='bad'; $result.ConsoleColor='Red' }
|
||||
1 { $result.Text='Unbound'; $result.Class='bad'; $result.ConsoleColor='Red' }
|
||||
default { $result.Text="Unknown($code)"; $result.Class='bad'; $result.ConsoleColor='Red' }
|
||||
}
|
||||
}
|
||||
default {
|
||||
$result.Text = [string]$Value
|
||||
}
|
||||
}
|
||||
return [pscustomobject]$result
|
||||
}
|
||||
|
||||
function Write-ColoredKV {
|
||||
param(
|
||||
[string]$Key,
|
||||
[psobject]$Formatted
|
||||
)
|
||||
Write-Host ("{0,-15}" -f ($Key + ':')) -NoNewline
|
||||
Write-Host $Formatted.Text -ForegroundColor $Formatted.ConsoleColor
|
||||
}
|
||||
|
||||
# ----------------- Snapshot -----------------
|
||||
function Get-BizTalkSnapshot {
|
||||
param(
|
||||
[string]$OutputFile = 'snapshot.json',
|
||||
[string]$Server = $env:COMPUTERNAME
|
||||
)
|
||||
Write-Log "Erzeuge Snapshot von Server '$Server' → Datei: $OutputFile"
|
||||
try {
|
||||
$apps = Get-WmiObject MSBTS_Application -Namespace "root\MicrosoftBizTalkServer" -ComputerName $Server -ErrorAction Stop
|
||||
} catch {
|
||||
Write-Log "FEHLER: Verbindung zu BizTalk-WMI auf '$Server' fehlgeschlagen: $($_.Exception.Message)" 'ERROR'
|
||||
throw
|
||||
}
|
||||
|
||||
$snapshot = @()
|
||||
foreach ($app in $apps) {
|
||||
$appName = $app.Name
|
||||
Write-Log "Lese Anwendung '$appName'"
|
||||
|
||||
$rl = Get-WmiObject MSBTS_ReceiveLocation -Namespace root\MicrosoftBizTalkServer -ComputerName $Server |
|
||||
Where-Object { $_.ApplicationName -eq $appName } |
|
||||
Select-Object Name,
|
||||
@{n='Enabled'; e={ -not $_.IsDisabled }},
|
||||
AdapterName,
|
||||
@{n='Address'; e={$_.InboundTransportURL}}
|
||||
|
||||
$sp = Get-WmiObject MSBTS_SendPort -Namespace root\MicrosoftBizTalkServer -ComputerName $Server |
|
||||
Where-Object { $_.ApplicationName -eq $appName } |
|
||||
Select-Object Name,
|
||||
@{n='Status';e={$_.Status}},
|
||||
@{n='PrimaryTransportType';e={$_.PTTransportType}},
|
||||
@{n='PrimaryTransportAddress';e={$_.PTAddress}}
|
||||
|
||||
$orch = Get-WmiObject MSBTS_Orchestration -Namespace root\MicrosoftBizTalkServer -ComputerName $Server |
|
||||
Where-Object { $_.ApplicationName -eq $appName } |
|
||||
Select-Object Name, @{n='OrchestrationStatus';e={$_.OrchestrationStatus}}
|
||||
|
||||
$snapshot += [PSCustomObject]@{
|
||||
Application = $appName
|
||||
ReceiveLocations = $rl
|
||||
SendPorts = $sp
|
||||
Orchestrations = $orch
|
||||
}
|
||||
}
|
||||
|
||||
$snapshot | ConvertTo-Json -Depth 8 | Out-File $OutputFile -Encoding UTF8
|
||||
Write-Log "Snapshot gespeichert: $OutputFile"
|
||||
}
|
||||
|
||||
# ----------------- Diff + HTML + Console Output -----------------
|
||||
function Compare-BizTalkSnapshots {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$Before,
|
||||
[Parameter(Mandatory=$true)][string]$After,
|
||||
[string]$HtmlReport = 'BizTalkDiff.html'
|
||||
)
|
||||
Write-Log "Vergleiche Snapshots: $Before ↔ $After"
|
||||
|
||||
$snapBefore = Get-Content $Before | ConvertFrom-Json
|
||||
$snapAfter = Get-Content $After | ConvertFrom-Json
|
||||
|
||||
$differences = @()
|
||||
|
||||
# Helper: add diff row
|
||||
function Add-Diff {
|
||||
param($appName,$type,$name,$beforeVal,$afterVal)
|
||||
$b = Format-Status -ArtifactType $type -Value $beforeVal
|
||||
$a = Format-Status -ArtifactType $type -Value $afterVal
|
||||
$differences += [PSCustomObject]@{
|
||||
Application = $appName
|
||||
ArtifactType = $type
|
||||
Name = $name
|
||||
Before = $beforeVal
|
||||
After = $afterVal
|
||||
BeforeText = $b.Text
|
||||
BeforeClass = $b.Class
|
||||
AfterText = $a.Text
|
||||
AfterClass = $a.Class
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($appAfter in $snapAfter) {
|
||||
$appBefore = $snapBefore | Where-Object { $_.Application -eq $appAfter.Application }
|
||||
|
||||
# Receive Locations
|
||||
foreach ($rlAfter in $appAfter.ReceiveLocations) {
|
||||
$rlBefore = $appBefore.ReceiveLocations | Where-Object { $_.Name -eq $rlAfter.Name }
|
||||
if ($null -eq $rlBefore) { Add-Diff $appAfter.Application 'ReceiveLocation' $rlAfter.Name $null $rlAfter.Enabled; continue }
|
||||
if ($rlBefore.Enabled -ne $rlAfter.Enabled) { Add-Diff $appAfter.Application 'ReceiveLocation' $rlAfter.Name $rlBefore.Enabled $rlAfter.Enabled }
|
||||
}
|
||||
# Detect removed RL
|
||||
foreach ($rlBefore in $appBefore.ReceiveLocations) {
|
||||
$rlAfter = $appAfter.ReceiveLocations | Where-Object { $_.Name -eq $rlBefore.Name }
|
||||
if ($null -eq $rlAfter) { Add-Diff $appAfter.Application 'ReceiveLocation' $rlBefore.Name $rlBefore.Enabled $null }
|
||||
}
|
||||
|
||||
# Send Ports
|
||||
foreach ($spAfter in $appAfter.SendPorts) {
|
||||
$spBefore = $appBefore.SendPorts | Where-Object { $_.Name -eq $spAfter.Name }
|
||||
if ($null -eq $spBefore) { Add-Diff $appAfter.Application 'SendPort' $spAfter.Name $null $spAfter.Status; continue }
|
||||
if ($spBefore.Status -ne $spAfter.Status) { Add-Diff $appAfter.Application 'SendPort' $spAfter.Name $spBefore.Status $spAfter.Status }
|
||||
}
|
||||
foreach ($spBefore in $appBefore.SendPorts) {
|
||||
$spAfter = $appAfter.SendPorts | Where-Object { $_.Name -eq $spBefore.Name }
|
||||
if ($null -eq $spAfter) { Add-Diff $appAfter.Application 'SendPort' $spBefore.Name $spBefore.Status $null }
|
||||
}
|
||||
|
||||
# Orchestrations
|
||||
foreach ($oAfter in $appAfter.Orchestrations) {
|
||||
$oBefore = $appBefore.Orchestrations | Where-Object { $_.Name -eq $oAfter.Name }
|
||||
if ($null -eq $oBefore) { Add-Diff $appAfter.Application 'Orchestration' $oAfter.Name $null $oAfter.OrchestrationStatus; continue }
|
||||
if ($oBefore.OrchestrationStatus -ne $oAfter.OrchestrationStatus) { Add-Diff $appAfter.Application 'Orchestration' $oAfter.Name $oBefore.OrchestrationStatus $oAfter.OrchestrationStatus }
|
||||
}
|
||||
foreach ($oBefore in $appBefore.Orchestrations) {
|
||||
$oAfter = $appAfter.Orchestrations | Where-Object { $_.Name -eq $oBefore.Name }
|
||||
if ($null -eq $oAfter) { Add-Diff $appAfter.Application 'Orchestration' $oBefore.Name $oBefore.OrchestrationStatus $null }
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------- Console text summary with colors ----------------
|
||||
Write-Host ""; Write-Host "------------------------------------------------------------" -ForegroundColor Yellow
|
||||
Write-Host " TEXTUELLE ÄNDERUNGSÜBERSICHT (StdOut)" -ForegroundColor Yellow
|
||||
Write-Host "------------------------------------------------------------" -ForegroundColor Yellow
|
||||
|
||||
if ($differences.Count -eq 0) {
|
||||
Write-Host "Keine Unterschiede gefunden." -ForegroundColor Green
|
||||
} else {
|
||||
foreach ($d in $differences) {
|
||||
Write-Host ""; Write-Host ("Application: {0}" -f $d.Application) -ForegroundColor Cyan
|
||||
Write-Host ("Artifact: {0}" -f $d.ArtifactType)
|
||||
Write-Host ("Name: {0}" -f $d.Name)
|
||||
Write-ColoredKV -Key 'Before' -Formatted ([pscustomobject]@{ Text=$d.BeforeText; ConsoleColor=($(if($d.BeforeClass -eq 'ok'){'Green'}elseif($d.BeforeClass -eq 'bad'){'Red'}else{'Yellow'})) })
|
||||
Write-ColoredKV -Key 'After' -Formatted ([pscustomobject]@{ Text=$d.AfterText; ConsoleColor=($(if($d.AfterClass -eq 'ok'){'Green'}elseif($d.AfterClass -eq 'bad'){'Red'}else{'Yellow'})) })
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------- HTML report ----------------
|
||||
Write-Log "Erzeuge HTML-Report: $HtmlReport"
|
||||
|
||||
$htmlHeader = @"
|
||||
<html>
|
||||
<head>
|
||||
<title>BizTalk Differences Report</title>
|
||||
<style>
|
||||
body { font-family: Arial, Helvetica, sans-serif; }
|
||||
table { border-collapse: collapse; width: 100%; }
|
||||
th, td { border: 1px solid #999; padding: 8px; text-align: left; }
|
||||
th { background-color: #2d6cdf; color: white; }
|
||||
tr:nth-child(even) { background-color: #f8f8f8; }
|
||||
.ok { color: #0a7d00; font-weight: 600; }
|
||||
.bad { color: #b00020; font-weight: 600; }
|
||||
.neutral { color: #b58900; font-weight: 600; }
|
||||
.small { color:#666; font-size:12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>BizTalk Differences Report</h2>
|
||||
<p class="small">Vergleich: <b>$Before</b> → <b>$After</b></p>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Application</th>
|
||||
<th>Artifact</th>
|
||||
<th>Name</th>
|
||||
<th>Before</th>
|
||||
<th>After</th>
|
||||
</tr>
|
||||
"@
|
||||
|
||||
$rows = foreach ($d in $differences) {
|
||||
"<tr><td>$($d.Application)</td><td>$($d.ArtifactType)</td><td>$($d.Name)</td><td class='${($d.BeforeClass)}'>$($d.BeforeText)</td><td class='${($d.AfterClass)}'>$($d.AfterText)</td></tr>"
|
||||
}
|
||||
|
||||
$htmlFooter = "</table></body></html>"
|
||||
|
||||
($htmlHeader + ($rows -join "`n") + $htmlFooter) | Out-File $HtmlReport -Encoding UTF8
|
||||
|
||||
Write-Host ""; Write-Host ("HTML-Report erstellt: {0}" -f $HtmlReport) -ForegroundColor Green
|
||||
Write-Host "→ Im selben Verzeichnis öffnen für die farbige Übersicht." -ForegroundColor DarkYellow
|
||||
|
||||
return $differences
|
||||
}
|
||||
|
||||
# ---------------- Parameters (CLI) ----------------
|
||||
param(
|
||||
[switch]$Before,
|
||||
[switch]$After,
|
||||
[switch]$Compare,
|
||||
[string]$Server = $env:COMPUTERNAME,
|
||||
[string]$OutDir = '.'
|
||||
)
|
||||
|
||||
if ($PSBoundParameters.ContainsKey('OutDir')) { New-Item -ItemType Directory -Force -Path $OutDir | Out-Null; Set-Location $OutDir }
|
||||
|
||||
if ($Before) { Get-BizTalkSnapshot -OutputFile 'before.json' -Server $Server; exit }
|
||||
elif ($After) { Get-BizTalkSnapshot -OutputFile 'after.json' -Server $Server; exit }
|
||||
elif ($Compare) { Compare-BizTalkSnapshots -Before 'before.json' -After 'after.json' -HtmlReport 'BizTalkDiff.html'; exit }
|
||||
else {
|
||||
Write-Host "Verwendung:" -ForegroundColor Yellow
|
||||
Write-Host " Snapshot vor Downtime: .\BizTalkStatusTool.ps1 -Before -Server <BizTalkServer> -OutDir <Pfad>"
|
||||
Write-Host " Snapshot nach Downtime: .\BizTalkStatusTool.ps1 -After -Server <BizTalkServer> -OutDir <Pfad>"
|
||||
Write-Host " Diff + HTML Report: .\BizTalkStatusTool.ps1 -Compare"
|
||||
}
|
||||
Reference in New Issue
Block a user