You never know when you might need an ad-hoc QR code and there are plenty of generators available - but what if you need it right now inside your PowerShell terminal?

@h_iben@nerdculture.de

ZXing.Net makes it possible

PowerShell can load .NET classes from DLLs and therefore all the hard work of QR code generation can just be outsourced to the very handy port of the ZXIng project to C#/.Net at GitHub -ZXIng.Net

This will only work with PowerShell 7 and higher (so not in 5.1) due to how the .NET framework is available.

Download the provided bindings (version 0.16.9.0 at time of writing) and extract the 'netstandard' folder to somewhere you like. For this document we will assume you have placed it into your home directory inside the folder zxing. We will use the version 2.1 DLL so the full path to this DLL will be $HOME/zxing/netstandard/2.1/zxing.dll.

Manual creation / Create QR Code

First we need to make the ZXIng classes available to PowerShell by adding the library types. Inside the terminal, move to the folder containing the DLL and execute:

Add-Type -Path .\zxing.dll

There is no output if this was successful - otherwise you may need to try a different version of the DLL.

Now we create a QR code writer:

$qrwriter = New-Object "ZXing.QrCode.QRCodeWriter"

And create a QR code:

$matrix = $qrwriter.encode("Hello Console!", [ZXing.BarcodeFormat]::QR_CODE, 0, 0, $NULL)

To get more insights into the parameters of the encode method you can check the code on GitHub but in short, the first parameter is the code content, the second one is the code format (QR Code), the third and fourth ones are the desired width and height and the last parameter can contain encoding hints.

The format must always be QR Code. Leaving width and height at 0 will create the smallest possible size. Setting the hints to $NULL is a shorcut to not setting any hints.

Now we can output the created code to the terminal via the toString method:

$matrix.ToString()

ToString()

This looks somewhat like a QR code but this would be very hard to read for a camera (but it is possible).

Of course the BitMatrix object provides an option for customization. We want to keep the set bits as spaces (black terminal background) but the unset ones should be fully white (terminal foreground).

Luckily, PowerShell supports Unicode characters so we can use Block Elements. We will use the full block (U+2588 = █) two times. Our call now becomes:

$matrix.ToString(" ", "██")

ToString-With-Blocks

And this now looks like a QR code as we know it.

But wait, there's more... / Error Correction

QR codes have built in error correction that allows readers to recover damaged codes and to improve the recognition rate of hard-to-read ones. By default, ZXIng uses the lowest error correction rate L but supports all four rates (L,M,Q,H). This is defined via the hints that we left empty before.

ZXIng requires the hints to be provided as an IDictionary object so we cannot simply provide an ad-hoc list or hashmap. We create a new dictionary via New-Object:

$hints = New-Object "System.Collections.Generic.Dictionary[ZXing.EncodeHintType,Object]"

Now we add our error correction hint:

$hints.Add([ZXing.EncodeHintType]::ERROR_CORRECTION, "H")

Valid error correction values are L,M,H and Q - other values are ignored and L will be used

Just for completenes: You can also directly use the pre-defined values via references if you prefer or need this:

$hints[[ZXing.EncodeHintType]::ERROR_CORRECTION]=[ZXing.QrCode.Internal.ErrorCorrectionLevel]::H

We can now recreate the code as previously shown but with the hints.

There are more hints possible - Check the sources on GitHub

$matrix = $qrwriter.encode("Hello Console!", [ZXing.BarcodeFormat]::QR_CODE, 0, 0, $hints)

For small content, you will likely not see much difference between error levels.

Wrapping up / Creating a PowerShell Function

Doing this manually every time you need a code defeats to purpose of having this quickly available - lets create a PowerShell function for our profile!

You can also just create a new PowerShell file and source it in your profile or if needed.

If you do not already have a PowerShell profile file, just create it. Check the $PROFILE variable inside your shell to find out were PowerShell expects to find it.

Definining the function

Start by adding the function to the script. Stick to common PowerShell verbs for the naming. I have choosen Get-ConsoleQrCode to reflect that this function returns a value for the console.

function Get-ConsoleQrCode {

Defining Parameters

We want to be able to set the content and the error correction level of our generated codes but also want to keep the default of L.

To accomplish this, we add a param block:

function Get-ConsoleQrCode {
  param(
    $Text,
    $ErrorCorrectionLevel = "L"
  )

This allows us to specify the parameters by name if needed and provides a default for the error correction.

Checking for ZXIng types

Adding the DLL is only required once per session so we should check if we need to add it. See this Stack Overflow dicussion for more details.

  if (-not ([System.Management.Automation.PSTypeName]'ZXing.QrCode.QRCodeWriter').Type) {
    # adjust to ZXIng.Net DLL location
    Add-Type -Path "$HOME/zxing/netstandard/2.1/zxing.dll"
  }

This snipped above shows how we will check for the presence of the ZXIng QR Code Writer and add the DLL if needed. Be sure to change it to the correct place of the DLL.

Creating the code

With the setup in place, we can now just write down the manual steps inside the function:

  $qrwriter = New-Object "ZXing.QrCode.QRCodeWriter"
  $hints = New-Object "System.Collections.Generic.Dictionary[ZXing.EncodeHintType,Object]"
  $hints[[ZXing.EncodeHintType]::ERROR_CORRECTION]=$ErrorCorrectionLevel

  $matrix = $qrwriter.encode($Text, [ZXing.BarcodeFormat]::QR_CODE, 0, 0, $hints)

  $matrix.ToString("  ", "██")
}

The call to ToString will produce the result of the function.

Complete Function

function Get-ConsoleQrCode {
  param(
    $Text,
    $ErrorCorrectionLevel = "L"
  )
 if (-not ([System.Management.Automation.PSTypeName]'ZXing.QrCode.QRCodeWriter').Type) {
   Add-Type -Path "$HOME/zxing/netstandard/2.1/zxing.dll"
  }

  $qrwriter = New-Object "ZXing.QrCode.QRCodeWriter"
  $hints = New-Object "System.Collections.Generic.Dictionary[ZXing.EncodeHintType,Object]"
  $hints[[ZXing.EncodeHintType]::ERROR_CORRECTION]=$ErrorCorrectionLevel

  $matrix = $qrwriter.encode($Text, [ZXing.BarcodeFormat]::QR_CODE, 0, 0, $hints)

  $matrix.ToString("  ", "██")
}

Testing

You can now open a new PowerShell terminal (or otherwise re-source the function) and create a QR Code:

Summary Image

Enjoy your new Power! :-)

Previous Post Next Post