Search code examples
dockerpowershellstartswithwhere-object

How to use Where-Object with StartsWith to filter Powershell command outputs


I have a powershell script written by somebody else that makes use of uses the output of a command to filter and extract the results. I think I understand what it is attempting to do but not why I am getting an error.

pertinent part of Script is

$dockerInfo = (docker info)
$dockerOsMode = ($dockerInfo | Where-Object { $_.StartsWith('OSType: ') }).SubString(8)

I however get the error message

Checking Docker Service Settings...
You cannot call a method on a null-valued expression.
At C:\Users\MichaelC\Documents\DockerCleanup.ps1:29 char:1
+ $dockerOsMode = ($dockerInfo | Where-Object { $_.StartsWith('OSType:  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : InvokeMethodOnNull

My understanding of the error message is that the $dockerInfo variable is null but it isnt. If I run the variable directly I can see its output.

PS C:\Users\MichaelC> $dockerinfo
Client:
 Version:    24.0.4
 Context:    default
 Debug Mode: false

Server:
 Containers: 2
  Running: 0
  Paused: 0
  Stopped: 2
 Images: 47
 Server Version: 24.0.4
 Storage Driver: windowsfilter
  Windows:
 Logging Driver: json-file
 Plugins:
  Volume: local
  Network: ics internal l2bridge l2tunnel nat null overlay private transparent
  Log: awslogs etwlogs fluentd gcplogs gelf json-file local logentries splunk syslog
 Swarm: inactive
 Default Isolation: process
 Kernel Version: 10.0 17763 (17763.1.amd64fre.rs5_release.180914-1434)
 Operating System: Microsoft Windows Server Version 1809 (OS Build 17763.5329)
 OSType: windows
 Architecture: x86_64
 CPUs: 6
 Total Memory: 31.98GiB
 Name: MCNAV
 ID: 5dbd48b8-ca1b-44bf-9495-5a504c435305
 Docker Root Dir: D:\docker
 Debug Mode: false
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false
 Product License: Community Engine

Is there some other global setting that I need to have turned on to be able to use the filter command on the Command output


Solution

  • The exception is being thrown because

    ($dockerInfo | Where-Object { $_.StartsWith('OSType: ') })
    

    returns $null - i.e. doesn't return any matches (for reasons mentioned by commenters re the leading space in the text), meaning your Substring is equivalent to:

    $null.SubString(8)
    

    And that's what's giving the exception.

    There's some options given by commenters and other answers, but here's a quick and dirty one - trim the lines before you compare them:

    $dockerOsMode = ($dockerInfo.Trim() | Where-Object { $_.StartsWith('OSType: ') }).Substring(8)
    #                           ^^^^^^^
    
    $dockerOsMode
    # Windows
    

    This uses Member Access Enumeration to build a new array of text lines that contain the results of invoking Trim() on each line of text the $dockerInfo variable, and then passes the trimmed values into Where-Object.