Convert-SonusSbcConfigToWord.ps1

 

Been here before? Know the deal? Jump to the revision history to see what’s in the latest update.
… or go straight to the Downloads.

The name’s a bit of a mouthful, but “Convert-RibbonSbcConfigToWord.ps1” takes the backup file from your Ribbon/Sonus SBC/UX 1000 or 2000 gateway and creates a new Word document, with all of the important(?) configuration information captured in tables.

It started life as a way to save the tedium of screen-scraping lots of fixed frames for my as-built documents, but it quickly became apparent that it would also make a useful tool for the offline review of a gateway’s config (although it ain’t no “UxBuilder”).

Convert your backups from this:

… to this:

"Before" TransformationTable-Word-v2

Features

  • Decodes gateway versions up to 8.0.0 & the SWe Lite
  • Converts and saves the config to a new Word document, and optionally makes a PDF of it too
  • Doesn’t need any Lync PowerShell modules – it’s fine on your Win 7 – Win 10 machine (which needs to have Word installed)
  • Tested on Word 2010, 2013 & 2016
  • Reasonably well debugged throughout (although time will tell of course!)
  • Use the “RedactIP” switch to strip all IP addresses from the resulting file
  • It’s easy enough to turn off an unwanted section if you’re only interested in a specific subset of the functionality, or are adapting to suit your environment
  • A “-SkipWrite” switch skips the relatively slow process of writing to Word. I added this for debugging and have left it in the released version to help anyone refining or enhancing the script
  • The script is code-signed, so no longer requires you to drop your ExecutionPolicy to “Unrestricted”. This also means you can be confident the code’s not changed since it left here
  • Uses your existing Word document template for the formatting of the table headings and table of contents – or nominate a different one from the commandline

ScriptRunning

Limitations

  • It’s not the fastest to run! Stuffing values into Word is a relatively slow process. With v2 and all options enabled allow up to 10 minutes for your average gateway. I’ve stolen Scott Hanselman’s “Progress Bars in PowerShell” to help the watched pot boil
  • Each update captures even more of the gateway’s config than before, however it still doesn’t capture EVERYTHING. There’s an enormous amount in there, and it’s growing with each release! If you find I’ve not captured a particularly valuable element of the config, feel free to revise it to suit your needs – and send me the new bits to incorporate, please. If you’re not feeling up to it, send me a sample config file and some screen-grabs of the bit you’d like to see added
  • There are MANY hash tables throughout. (This is where an integer is stored in the config file, but it’s decoded to text on-screen). I’ve put a lot of effort into capturing these, but there are going to be examples where I’ve missed one. Please send me screen-grabs and sample config files and I’ll update the script.
  • I’m largely letting Word control the width of the table columns, and you’ll find many instances where it’s done a poor job. You’ll need to edit every document the script produces to resolve this

Instructions

  1. I’ve published the script here as “Convert-RibbonSbcConfigToWord-<version>.txt” as a way of capturing the version number, but to also get around programs like Outlook that aren’t too happy being used as a delivery means for “ps1” files. So please rename it to Convert-RibbonSbcConfigToWord.ps1
  2. Backup your gateway. Export the config file. Older versions (pre 2.2.1) will save to an archive called “backup.tar.gz”, while newer versions save as “SBC_Config_<hostname>_<version>_<date>.tar”
  3. Older backups you’ll need to unzip twice to recover the “symphonyconfig.xml” document we need, whilst newer ones only need one unzip to reveal their goodness>> If you have 7-zip installed you no longer need to unzip “SBC_Config_<hostname>_<version>_<date>.tar” – just feed the .tar file as the “-inputfile”
  4. Open a PowerShell window
  5. Now feed the backup into the script! Either place the config file in the same path as the script, give the full path in the command line, or (as of v2.7) a relative path:
    PS H:\> Convert-RibbonSbcConfigToWord.ps1 -InputFile "symphonyconfig.xml" -OutputFile "CustomerSBC-config.docx"

    If you don’t specify an InputFile, the script goes looking for “symphonyconfig.xml” in its directory. If you don’t specify an OutputFile, it will re-use the name of the InputFile and save as “.docx”, overwriting any existing file of the same name in that directory. If you add the “-MakePdf” switch, it will save the same output filename as a .pdf as well

You can even batch it:

PS H:\> Get-Item "d:\path\*.tar" | foreach {.\Convert-RibbonSbcConfigToWord.ps1 -InputFile $_.Fullname -MakePdf -SkipUpdateCheck}

 

Troubleshooting

If the script won’t start, odds are you’ve run foul of a protective mechanism: the “Execution Policy”. Here’s how to Get the current value and Set it to “AllSigned”.

PS H:\> Get-ExecutionPolicy
Restricted       
PS H:\> Set-ExecutionPolicy AllSigned
Execution Policy Change
The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy?
[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"): y
PS H:\>

Note that the first time you run this script you’ll have to agree to trust my code-signing cert:

PS H:\> .\Convert-RibbonSbcConfigToWord.ps1 -Inputfile symphonyconfig.xml -Verbose -MakePDF
Do you want to run software from this untrusted publisher?
File H:\\Convert-RibbonSbcConfigToWord.ps1 is published by CN=Greig Sheridan, O=Greig Sheridan, L=Petersham North, S=New South Wales, C=AU and is not trusted on your system. Only run scripts from trusted publishers.

[V] Never run  [D] Do not run  [R] Run once  [A] Always run  [?] Help (default is "D"): a

The other one you might encounter is more easily fixed. If you get this error, just do like the last line says and re-run with “.\” at the start:

Convert-RibbonSbcConfigToWord.ps1 : The term 'Convert-RibbonSbcConfigToWord.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Suggestion [3,General]: The command Convert-RibbonSbcConfigToWord.ps1 was not found, but does exist in the current location. Windows PowerShell does not load commands from the current location by default. If you trust this command, instead type ".\Convert-RibbonSbcConfigToWord.ps1". See "get-help about_Command_Precedence" for more details.

PowerShell ISE

Some users have reported problems when running the script from a PowerShell ISE window. If that’s you, try it in a normal (but elevated) PowerShell window.
 

What’s Under the Hood

At almost over 5,000 more than 5,000 7,000 8,000 10,000 lines of code this script’s not compact, but structurally it is really quite simple. There are two primary components: one that reads the XML and extracts the required values; and the second is a pair of very similar functions (“WriteSection” & “WriteSectionVertically”) that creates a suitable table and dumps the values therein.

The main body of the script simply wends its way sequentially through the XML file, plucking out all of the sections of interest with essentially the same string manipulation repeating over and over again. (I had a go at it, but the unique content of each section prevented me from proceduralising this).

# ---- FXS Cards ----------
if ($NodeHardwareGroup.name -eq "FXSCards")
{
$FXSCards = $NodeHardwareGroup.GetElementsByTagName("ID")
$FXSCardColumnTitles = @("Card", "Port", "Enabled", "Port Name", "Port Alias", "Port Description", "Rx Gain", "Tx Gain", "Analog Line Profile")
if ($FXSCards.Count -ne 0)
{
ForEach ($FXSCard in $FXSCards)
{
if ($FXSCard.IE.classname -eq $null) { continue } # Empty / deleted entry
if ($FXSCard.IE.classname -eq "LINE_CARD_CONFIG_IE")
{
$FXSCardPorts = $FXSCard.GetElementsByTagName("ID")
ForEach ($FXSCardPort in $FXSCardPorts)
{
if  ($FXSCardPort.IE.classname -eq "FXS_PORT_PROFILE_CONFIG_ENTRY_IE")
{
$FXSCardObject = @($FXSCard.value, $EnabledLookup.Get_Item($FXSCardPort.IE.Enabled) <EDIT>))
$FXSCardCollection += , $FXSCardObject
}
}
}
}
$NodeHardwareData += , ("FXS Cards", $FXSCardColumnTitles, $FXSCardCollection)
}
}

… and so on.

As each section is read, the required parameters are extracted & formatted into an array. If there are multiple objects of the same type, these are also processed and an array of arrays is prepared in readiness for Word. If the section has a “Sequence” value (the ordering of entries in a Transformation Table is a prime example), this is decoded and the array entries re-ordered to represent the active sequence. Once the sequence is correct, the final array is passed to the appropriate WriteSection.

The WriteSection functions open and inspect the passed array, decoding it back into multiple constituent arrays representing column titles (“horizontal” tables only) and each table’s row. The title of the section is written to the document in the Heading1 style. If there are sub-headings (sub-tables or groups within the section), these are written as Heading2 and Heading3. We then loop through the array, writing each string therein as a new row.


 

The ENTIRE revision history is now in a separate post here.

Revision History

v8.0.1B – 21st April 2019

  • Changed Sig Gp ‘Supported Video/Application Modes’ to display ‘[None]’ if $LicencedForVideo but no modes applicable (rather than blank)
  • Cosmetic: moved ‘Static Host’ in SIP profiles between ‘FQDN in From’ and ‘Contact’ headers to align with on-screen
  • Updated ‘Static Host’ to new label ‘Static Host FQDN/IP[:port]’
  • Added another example, showing how you can batch and drop the output files in another folder. (Thanks Cookie!)
  • Bug CHOR-3343 in 8.0.1 b180 & 181 results in the SWeLite dropping its hostname from nodeinfo.txt, replaced by “/usr/sbin/vsbcinfo.sh: line 74: hostname: not found”.
    – Updated the script to drop a warning and continue, rather than abort
  • Re-jigged wording of SIP Sig Gp ‘Supported Audio Modes’ and ‘Supported Video/Application Modes’ to align with current on-screen experience
  • Updated wording of Sig Gp MOH option [2] from ‘Enabled for 2-way Hold Only’ to ‘Enabled for SDP Inactive’
  • Added new bits in SweLite v8.0.0:
    • ICE Support added to SIP Sig Gps. (Removed previous test for Lite that hid this)
    • Opus codec to the media profile options
  • Fixed bugs:
    • ‘Static Host’ now correctly displays if $FQDNinContactHeader = ‘Static’ [3]
    • Fixed one bad example: was using “where” shortcut instead of “foreach”
    • Corrected wrong quotes in the write-warning message under “$NodeHostname.CompareTo”. Was not resolving variable names
    • SIP Sig Gp was not showing ‘Nonce Lifetime’ if Nonce Expiry = Limited. Deleted the now-redundant $SipNonceExpiryLookup

v8.0.1 – 30th January 2019

  • Added new bits in 8.0.1:
    • Changed ISDN Sig Gp for new ‘Until Timer Expiry’ option in ‘Play Inband Message Post-Disconnect’
    • Added new ‘Convert DISC PI=1,8 to Progress’ to ISDN Sig Gp
  • Fixed bugs:
    • If the SBC has only 1 Transformation Table it would not display. (Bug in the alpha sort introduced in v7.0.0B)
    • Corrected several bugs in display of ‘DTLS-SRTP Profiles’
    • Corrected bug in Media Lists where the ‘DTLS-SRTP Profile’ value wasn’t correctly reported
    • Certs was truncating parameters if one happened to be a URL (as I was splitting on ‘/’)
    • Certs wasn’t populating the issuer’s details (the RHS of the table)
  • Created new $SipProfileCntctHdrLookup & edited values in $SipProfileFrmHdrLookup for new on-screen text
  • Added “[No CN]” text if a cert (so far GoDaddy roots) has no CN

v8.0.0B – 16th November 2018

  • Updated label and display of SIP Sig Gp / Media Info / Supported Audio(/Fax) Modes to match current display syntax: Lite and 1k2k
  • Fixed bug:
    • The logic for displaying SIP Sig Gp ICE Mode was faulty. (Mitsu-San yet again on the ball!)

v8.0.0 – 26th September 2018

  • Updated name to “Convert-RibbonSbcConfigToWord.ps1”
  • Added new bits in 8.0.0 (b502):
    • NEW COLOUR SCHEME! (And added “-SonusGreen” switch for the die-hards)
    • TOD Routing
    • Load Balancing options 4 & 5 to $SipLoadBalancingLookup
    • ‘SIP Failover Cause Codes’ in SIP Sig Gps
    • ‘RTCP Multiplexing’ in SIP Sig Gps
    • ‘ICE Mode’ in SIP Sig Gps
    • Renamed ‘Media Crypto Profiles’ to ‘SDES-SRTP Profiles’
    • ‘DTLS-SRTP Profiles’
    • ‘Redundancy Retry Timer’ in SIP Profiles
    • Grouped Transformations, TOD, Call Routing & Call Actions in new ‘Call Routing’ group to align with the new on-screen layout
  • Added new test in Test-ForNull to drop a marker in the doc if an expected lookup returned $null
  • Set Word to disable spelling and grammar checking in the document. (Thanks Mike!)
  • Hid the display of “Translations” (long obsolete)
  • Fixed bugs:
    • Renamed variables in the SGPeers’ .split() code to make them unique. (Had accidentally reused old having copy/pasted)
    • Corrected display of ‘SDES-SRTP Profiles’ Derivation Rate to add the ‘2^’ prefix for non-zero values
    • If you ran with “-do calls” it would incorrectly not show the “incomplete” warning after the TOC. (“calls” sounds like “all”)

v7.0.3 – 31st July 2018

  • Added new bits in 7.0.2 (b485) and SWe Lite 7.0.3 (b141):
    • New SIP Sig Gp Interop Mode ‘Header Transparency’
    • Changed SIP Profile’s ‘FQDN in Contact Header’ from $EnableLookup to $SipProfileFrmHdrLookup for Teams Direct Routing
  • Changed Media Profiles and Media Crypto Profiles to V-tables
  • Improved error reporting if the PDF exists and is open (i.e. locked) when the script goes to create it
  • Major update to the SIP Message Manipulation rules:
    • Changed handling of SIP ElementDescriptors to break out the Token, Prefix and Suffix to a separate line for each
    • Added the “pre-400” messages to $SIPDescriptionLookup
    • Changed SMM rules to use $SIPDescriptionLookup when Applicable Messages = Selected Messages & a SIP code is matched
    • SMM Header & Request Line rules were not displaying URI & URIUser parameters
    • Changed SMM rules to display the header name in Title Case
    • Added some missing descriptors to $SipElementDescElementClassLookup & $SipElementDescActionLookup to improve SMM
    • Corrected display of “Ordinal” value in Header rules. Now only shows when the header name is Contact, Route, Record-Route or History-Info or PAI
    • Suppressed incorrect display of “Value” when Action = Remove
  • Fixed bugs:
    • Corrected SWeLite’s Media Crypto Profiles, suppressing display of Master Key Lifetime, Lifetime Value and Derivation Rate values
    • Func Dump-ErrToScreen was not correctly dumping the error to screen when in “non-debug” mode
    • Added some missing SIP messages to the $SIPDescriptionLookup. (Thank you again Mitsu-San)
    • Updated Strip-TrailingCR to keep removing the last char from the string until the last char ISN’T a CR. (Was only stripping once).

v7.0.2

Skipped

Known Issues

  • If you’re running Word independently at the same time that the script is executing, I’ve noticed that sometimes the script may:
    • generate an error when it goes to add the Footer (“Property ‘Text’ cannot be found on this object; make sure it exists and is settable”)
    • close Word out from under you!


 

Download

If you have any problems downloading the latest version here you’ll also find it on the TechNet Gallery site.

v8.0.1B: Click here to view it in the browser. Click here to to download the ZIP: Convert-RibbonSbcConfigToWord-v8.0.1B

Help me improve the script

PLEASE let me know if you encounter any problems. All I ask is a copy of the symphonyconfig.xml file (de-identified as you wish) – or preferably a .TAR backup file – and a screen-grab from the browser to show me what it’s meant to look like on-screen.

Credits

There are many great posts out there where people have achieved awesome things with PowerShell and Word, and I’ve relied heavily on their experiences and generosity. I’ve pasted these links into the bottom of the script as well.
TOC: http://www.edrawsoft.com/automating-word-vb.php
http://carlwebster.com/documenting-a-citrix-xenapp-6-5-farm-with-microsoft-powershell-and-word-version-3/
http://stackoverflow.com/questions/14507815/powershell-word-2007-2010-2013-add-a-caption-to-table-and-move-table-3-tabs-to-r
http://mypowershell.webnode.sk/news/create-word-document-with-multiple-tables-from-powershell/
http://dilutedthoughts.com/dilutedthoughts/2012/12/19/using-powershell-to-create-a-custom-word-document
Save as PDF: http://blog.coolorange.com/2012/04/20/export-word-to-pdf-using-powershell/
Write-Progress: http://www.hanselman.com/blog/ProgressBarsInPowerShell.aspx

G.

17 Comments

  1. Hi,
    Really nice job! I just change the script a little bit because I need a different color for the first row of tables. It would have been nicer if you choose only one variable for all the first rows but it was still easy to modify.

    Here is the part I added:
    # Transformation RGB -> WdColor
    # wdColor = (red + 0x100 * green + 0x10000 * blue)
    # light orange (255,204,153)
    $MyColor = (255 + 0x100 * 204 + 0x10000 * 153)

    # Replace Colors by one common for all first rows
    $wdColorFirstRow = $MyColor

    And I replace variable after “.BackgroundPatternColor” by $wdColorFirstRow, to allow change the color in just one place.

    Many thanks for your script!!!

  2. Hi Greg
    I have used your great script several times, and the outcome is great:) But now I have an issue when I run the script from a SB2K rel. 5.0.1. It runs the script, but fails at last with this error:
    Aborted with fatal error: You cannot call a method on a null-valued expression.
    WARNING: Failed to save DOC and/or create PDF
    Have tried several times, with same result

    Do You have time to give it a shot :)

    Best regards
    David

    • Hi David,

      If you can send me the backup file I’d love to see why it’s crashing. If you’re concerned for the privacy of the data, I only need the XML, and you can obfuscate the IPs, hostnames & any other identifying details before sending it through.

Leave a Reply to Naimesh Mistry Cancel reply

Your email address will not be published. Required fields are marked *

... and please just confirm for me that you're not a bot first: Time limit is exhausted. Please reload the CAPTCHA.

This site uses Akismet to reduce spam. Learn how your comment data is processed.