PoshCode Logo PowerShell Code Repository

Get-OnlineHelp by Joel Bennett 22 months ago (modification of post by Joel Bennett view diff)
View followups from Joel Bennett | diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/1724"></script>download | new post

Retrieve Online Cmdlet Help — Fix a type check

I’m now using New-WebServiceProxy to take advantage of the well-formed XML provided by the MSDN ContentService

  1. ## An update using New-WebServiceProxy to the MSDN ContentService instead of HttpRest
  2. ## See: http: //services.msdn.microsoft.com/ContentServices/ContentService.asmx
  3.  
  4. ## This is a VERY EARLY prototype of a function that could retrieve cmdlet help from TechNet ...
  5. ## and hypothetically, other online help sites which used the same format (none)
  6.  
  7. ## Version History
  8. ## 0.3 - 2010-03-25 - Fixed a buggy type check which failed on first run. THIS VERSION
  9. ## 0.2 - 2010-03-24 - Switched to using the ContentService Web Service.  PoshCode.org/1723
  10. ## 0.1 - 2010-03-23 - Initial release depended on HttpRest.  PoshCode.org/1719
  11.  
  12. param(
  13.    [Parameter(Mandatory=$true,Position=0)]
  14.    [String]$Name
  15. ,
  16.    [Parameter(Mandatory=$false,Position=1)]
  17.    [String[]]$Sections= @("Name", "Synopsis", "Syntax", "Description")
  18. )
  19.  
  20.  
  21. # http://poshcode.org/1718
  22. function Select-Expand {
  23. <#
  24. .Synopsis
  25.    Like Select-Object -Expand, but with recursive iteration of a select chain
  26. .Description
  27.    Takes a dot-separated series of properties to expand, and recursively iterates the output of each property ...
  28. .Parameter Property
  29.    A collection of property names to expand.
  30.    
  31.    Each property can be a dot-separated series of properties, and each one is expanded, iterated, and then evaluated against the next
  32. .Parameter InputObject
  33.    The input to be selected from
  34. .Parameter Unique
  35.    If set, this becomes a pipeline hold-up, and the total output is checked to ensure uniqueness
  36. .Parameter EmptyToo
  37.    If set, Select-Expand will include empty/null values in it's output
  38. .Example
  39.    Get-Help Get-Command | Select-Expand relatedLinks.navigationLink.uri -Unique
  40.  
  41.    This will return the online-help link for Get-Command.  It's the equivalent of running the following command:
  42.  
  43.    C:\PS> Get-Help Get-Command | Select-Object -Expand relatedLinks | Select-Object -Expand navigationLink | Select-Object -Expand uri | Where-Object {$_} | Select-Object -Unique
  44. #>
  45. param(
  46.    [Parameter(ValueFromPipeline=$false,Position=0)]
  47.    [string[]]$Property
  48. ,
  49.    [Parameter(ValueFromPipeline=$true)]
  50.    [Alias("IO")]
  51.    [PSObject[]]$InputObject
  52. ,
  53.    [Switch]$Unique
  54. ,
  55.    [Switch]$EmptyToo
  56. )
  57. begin {
  58.    if($unique) {
  59.       $output = @()
  60.    }
  61. }
  62. process {
  63.    foreach($io in $InputObject) {
  64.       foreach($prop in $Property -split "\.") {
  65.          if($io -ne $null) {
  66.             $io = $io | Select-Object -Expand $prop
  67.             Write-Verbose $($io | out-string)
  68.          }
  69.       }
  70.       if(!$EmptyToo -and ($io -ne $null)) {
  71.          $io = $io | Where-Object {$_}
  72.       }
  73.       if($unique) {
  74.          $output += @($io)
  75.       }
  76.       else {
  77.          Write-Output $io
  78.       }
  79.    }
  80. }
  81. end {
  82.    if($unique) {
  83.       Write-Output $output | Select-Object -Unique
  84.    }
  85. }
  86. }
  87. # New-Alias slep Select-Expand
  88.  
  89. # http://poshcode.org/1722
  90. function Get-HttpResponseUri {
  91. #.Synopsis
  92. #   Fetch the HEAD for a url and return the ResponseUri.
  93. #.Description
  94. #   Does a HEAD request for a URL, and returns the ResponseUri. This is useful for resolving (in a service-independent way) shortened urls.
  95. #.Parameter ShortUrl
  96. #   A (possibly) shortened URL to be resolved to its redirect location.
  97.    PARAM(
  98.       [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true)]
  99.       [Alias("Uri","Url")]
  100.       [string]$ShortUrl
  101.    )
  102.    $req = [System.Net.HttpWebRequest]::Create($ShortUrl)
  103.    $req.Method = "HEAD"
  104.    $response = $req.GetResponse()
  105.    Write-Output $response.ResponseUri
  106.    $response.Close() # clean up like a good boy
  107. }
  108. # New-Alias Resolve-ShortUri Select-Expand
  109.  
  110. if( -not("Mtps.ContentService" -as [type] -and $global:MtpsWebServiceProxy -as "Mtps.ContentService")) {
  111. $global:MtpsWebServiceProxy = New-WebServiceProxy "http://services.msdn.microsoft.com/ContentServices/ContentService.asmx?wsdl" -Namespace Mtps
  112. }
  113.  
  114. function Get-OnlineHelpContent {
  115. param(
  116.    [Parameter(Mandatory=$true,Position=0)]
  117.    [String]$Name
  118. ,
  119.    [Parameter(Mandatory=$false,Position=1)]
  120.    [String[]]$Sections= @("Name", "Synopsis", "Syntax", "Description")
  121. )
  122. process {
  123.    $uri = Get-Help $Name | Select-Expand relatedLinks.navigationLink.uri -Unique | Get-HttpResponseUri
  124.    
  125.    if(!$uri) { throw "Couldn't find online help URL for $Name" }
  126.    
  127.    $id = [IO.Path]::GetFileNameWithoutExtension( $uri.segments[-1] )
  128.    write-verbose "Content Id: $id"
  129.  
  130.    $content = $MtpsWebServiceProxy.GetContent( (New-Object 'Mtps.getContentRequest' -Property @{locale = $PSUICulture; contentIdentifier = $id; requestedDocuments = (New-Object Mtps.requestedDocument -Property @{Selector="Mtps.Failsafe"}) }) )
  131.    $global:OnlineHelpContent = $content.primaryDocuments |?{$_.primaryFormat -eq "Mtps.Failsafe"} | Select -Expand Any
  132.    
  133.    $NameNode = $global:OnlineHelpContent.SelectSingleNode("//*[local-name()='div' and @class='topic']/*[local-name()='div' and @class='title']")
  134.    $NameNode.SetAttribute("header","NAME")
  135.    
  136.    $global:OnlineHelpContent = $global:OnlineHelpContent.SelectSingleNode("//*[local-name()='div' and @id='mainBody']")
  137.    
  138.    $Synopsis = $global:OnlineHelpContent.SelectSingleNode("*[local-name()='p']")
  139.    $Synopsis.SetAttribute("header","SYNOPSIS")
  140.    
  141.    $headers = $OnlineHelpContent.h2  | ForEach-Object { $_.get_InnerText().Trim() }
  142.    $content = $OnlineHelpContent.div | ForEach-Object { $_ }
  143.  
  144.    $global:help = @{Name=$NameNode; Synopsis=$Synopsis}
  145.    if($headers.Count -ne $content.Count) {
  146.       Write-Warning "Unmatched content"
  147.       foreach($header in $headers) {
  148.         $help.$header = $OnlineHelpContent.SelectNodes( "//*[preceding-sibling::*[1][local-name()='h2' and normalize-space()='$header']]" )
  149.         $help.$header.SetAttribute("header",$header.ToUpper())
  150.       }
  151.    }
  152.    else {
  153.       for($h=0;$h -lt $headers.Count; $h++){
  154.          $help.($headers[$h]) = $content[$h]
  155.          $help.($headers[$h]).SetAttribute("header",$headers[$h].ToUpper())
  156.       }
  157.    }
  158.    $help
  159.    
  160.    $content[$Sections] | ForEach-Object {
  161.       Write-Output
  162.       Write-Output $_.Header
  163.       Write-Output
  164.       Write-Output ($_.get_InnerText() -replace '^[\n\s]*\n|\n\s+$')
  165.    }
  166. }
  167. }
  168.  
  169. Get-OnlineHelpContent $Name | out-null
  170.  
  171.  
  172. $help[$Sections] | ForEach-Object {
  173.    Write-Host
  174.    Write-Host $_.Header -Fore Cyan
  175.    Write-Host
  176.    Write-Host ($_.get_InnerText() -replace '^[\n\s]*\n|\n\s+$')
  177. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me