Kine's Info

What I found and what I know about Microsoft Dynamics NAV

Reading/Writing NAV Blob data from PowerShell

I hope you will find this article when you will need what I needed last days – to read anything from NAV Blob field from PowerShell. The functions could be used e.g. to read Object Metadata, Profile Metadata etc.

First, I was inspired by scripts from this blog article: https://blog.karstein-consulting.com/2010/10/19/how-to-embedd-compressed-scripts-in-other-powershell-scripts/

It shows how to decompress and compress data using the Streams in powershell. Of course, there are some Blogs about how to read NAV Blob from outside NAV describing the same thing like this or this. From there, you can see that first 4 bytes are "Magic constant" we need to skip. Mix all this shared knowledge, add PowerShell and the result is this:

function Get-NAVBlobToString
{
  [CmdletBinding()]
  [OutputType([PSObject])]
  Param
  (
    [Parameter(Mandatory=$true,
      ValueFromPipelineByPropertyName=$true,Position=0)] 
    
[byte[]]$CompressedByteArray
  )  

  try {
    $ms = New-Object System.IO.MemoryStream
    $ms.Write($CompressedByteArray,4,$CompressedByteArray.Length-4) | Out-Null
    $ms.Seek(0,0) | Out-Null

    $cs = New-Object System.IO.Compression.DeflateStream($ms, [System.IO.Compression.CompressionMode]::Decompress)

    $sr = New-Object System.IO.StreamReader($cs)

    $t = $sr.ReadToEnd()

  } catch {
  } finally {
    $sr.Close()| Out-Null
    $cs.Close()| Out-Null
    $ms.Close()| Out-Null
  }

  return @{MagicConstant=$CompressedByteArray[0,1,2,3];Data=$t}
}

 

function Get-StringToNAVBlob
{
  [CmdletBinding()]
  [OutputType([byte[]])]
 
Param 
  (
    [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true,Position=0)]
   
[byte[]]$MagicConstant,
   
[Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=1)]
   
[String]$Data
 
)

  try {
    $ms = New-Object System.IO.MemoryStream 
    $cs = New-Object System.IO.Compression.DeflateStream($ms, [System.IO.Compression.CompressionMode]::Compress) 
    $sw = New-Object System.IO.StreamWriter($cs)

    $sw.Write($Data)

    $sw.Close();

    [byte[]]$result = $ms.ToArray()
  } catch {
  } finally {
    $sw.Close()| Out-Null
    $cs.Close()| Out-Null
    $ms.Close()| Out-Null 
  }

  $result = $MagicConstant+$result
  return $result
}

 

I have used these functions to solve some Profile problems in NAV (see http://dynamicsuser.net/blogs/kine/archive/2014/12/08/nav-profile-madness.aspx) and all is working correctly. If you get these functions and connect them with other powershell scripts like getting all NAV servers and databases on SQL which they are using, you can go through all data you have on the server and do whatever you need, e.g. export object metadata, synchronize profiles, apply some changes to profiles by script...

 

As always, you can find these functions in the CommonPSFunctions module which is part of "NAV PowerShell Scripts and TFS Build Templates" project on Codeplex. I am updating the scripts there each time I found some bug or add new functionality, thus use the git to clone the repository and to update it, or subscribe to the project changes. Because there are no many testers, there are bugs to be hunted and killed each time.