Results 1 to 3 of 3

Thread: Powershell sanity check please. (Solved)

  1. #1
    Senior Member
    Join Date
    Dec 2013
    Posts
    3,526
    Thanks
    504
    Thanked
    468 times in 326 posts

    Powershell sanity check please. (Solved)

    Can some kind person check if what follows is my poor coding or a bug, oddity, or whatever.
    Code:
    $URL = 'https://onegetcdn.azureedge.net/providers/providers.masterList.feed.swidtag'
    $Online = Invoke-WebRequest -UseBasicParsing -Uri $URL
    That, unless I've missed something, should be an xml document however powershell doesn't seem to treating as such..
    Code:
    $Online.Content | Get-Member
    Doesn't return any objects from the xml document and..
    Code:
    [xml]$Online.Content
    Says it "Cannot convert value "<?xml version="1.0" encoding="utf-8"?>" and "The specified node cannot be inserted as the valid child of this node, because the specified node is the wrong type."

    I think it's something to do with either the formatting of the xml document or how Invoke-WebRequest/Invoke-RestMethod are decoding it because if i use "-outfile" and read it back in with "get-content" it works as you'd expect an xml file to work.
    I've read some stuff about Invoke-WebRequest/Invoke-RestMethod screwing up BOM but I'm not entirely sure what, or how to spot, a BOM so can't tell if the above xml at the url is the problem or if it's my lack of powershell experience.

    If it matters I'm currently parsing the xml document using this and while it works being able to use powershell's built in xml parsing would be a lot cleaner.
    Code:
    $URL = 'https://onegetcdn.azureedge.net/providers/providers.masterList.feed.swidtag'
    $Online = Invoke-WebRequest -UseBasicParsing -Uri $URL
    $Local = Get-ChildItem "$PathToScript\Files\Installers\Powershell\nuget" -Recurse -File
    $OnlineVersion = $Online.Content | Select-String -Pattern 'https.*swidtag' | ForEach-Object { $_.Matches.Value }
    if (($OnlineVersion -replace '\D') -gt ($Local.VersionInfo.FileVersion -replace '\D')) {
      $Download = (Invoke-WebRequest -UseBasicParsing -Uri "$OnlineVersion").Content | Select-String -Pattern 'https.*\d.dll' | ForEach-Object { $_.Matches.Value }
      $NewVersion = $Download | Select-String -Pattern '\d.+([\d]{1,3})' | ForEach-Object { $_.Matches.Value }
      New-Item "$PathToScript\Files\Installers\Powershell\nuget\$NewVersion" -ItemType 'Directory' -Force | Out-Null
      Invoke-WebRequest "$Download" -OutFile "$PathToScript\Files\Installers\Powershell\nuget\$NewVersion\Microsoft.PackageManagement.NuGetProvider.dll"
      Remove-Item $Local.DirectoryName -Recurse -Force -EA 'SilentlyContinue'
    }
    Last edited by Corky34; 04-11-2020 at 12:20 PM.

  2. #2
    Senior Member
    Join Date
    Dec 2013
    Posts
    3,526
    Thanks
    504
    Thanked
    468 times in 326 posts

    Re: Powershell sanity check please. (Solved)

    Just updating in case anyone comes across this.

    I couldn't workout why Invoke-WebRequest/Invoke-RestMethod had problems parsing the swidtag as everything indicates it's a correctly formatted XML file so in the end i used the .net webclient, not sure if it makes for cleaner code but if anyone wants a laugh at how awful my coding is I'll leave what i ended up with bellow for people to pick holes in.

    Code:
    $URL = 'https://onegetcdn.azureedge.net/providers/providers.masterList.feed.swidtag'
    [xml]$XML = (New-Object 'Net.WebClient').DownloadString($URL)
    $Local = Get-ChildItem "$PathToScript\Files\Installers\Powershell\nuget" -Recurse -File
    $Online = $XML.SoftwareIdentity.Link | Where-Object { ($_.rel -EQ 'package') -and ($_.name -eq 'nuget') }
    if (([version]$Online.version) -gt ([version]$Local.VersionInfo.FileVersion)) {
        $Download = [xml]$XML = (New-Object 'Net.WebClient').DownloadString($Online.href)
        New-Item "$PathToScript\Files\Installers\Powershell\nuget\$($Online.version)" -ItemType 'Directory' -Force | Out-Null
        Invoke-WebRequest "$Download" -OutFile "$PathToScript\Files\Installers\Powershell\nuget\$($Online.version)\Microsoft.PackageManagement.NuGetProvider.dll"
        Remove-Item $Local.DirectoryName -Recurse -Force -EA 'SilentlyContinue'
    }

  3. Received thanks from:

    Jonj1611 (04-11-2020)

  4. #3
    Registered+
    Join Date
    Nov 2012
    Posts
    46
    Thanks
    0
    Thanked
    2 times in 2 posts

    Re: Powershell sanity check please. (Solved)

    Couple of things. $Online.Content.GetType() returns System.String, not XmlDocument.

    The document itself appears to have been created using a Windows editor and has the "magic" 3-byte Byte Order Mark (BOM) as the first 3 bytes, which according to the Wiki page for UTF is absolutely not recommended with UTF-8 encoding.

    When you dump $Online.Content in your Powershell console window the first char is a space. Additionally, [int]$Online.Content[0] returns 65279, which is just the result of *interpreting* the BOM as the first Unicode character, instead of processing the BOM as metadata.

    Anyway, long story short, [xml]$Online.Content.Substring(1) works - it ignores the first returned char. This is probably not a good idea tho.

    Instead, [xml]$Online.Content.Substring($Online.Content.IndexOf('<')) is probably a better idea, and should keep working if the BOM disappears from the file in future.

    This works just after your Invoke-WebRequest call.

    Is that the best way to do it? Probably not. I just thought I'd post why it wasn't working for you There are a billion ways to do everything and every day you learn a better way to do x,y,z

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •