I have a command line tool that outputs a block of information about a series of packages on a system.
Each package is separated by a pair of newlines, and each property of a given package is separated by a newline.
I'm trying to use Powershell's ConvertFrom-String commandlet to produce appropriate outputs, but I can't figure out how to write the templateFile.
Example (shortened) output from cmd:
Architecture: windows_all
CompatibilityVersion: 0
Depends: system-windows-x86 (>= 20.5.0) | system-windows-x64 (>= 20.5.0)
DisplayName: NI Package Manager Deployment Support
DisplayVersion: 20.5.0
Essential: yes
Filename: ni-package-manager-deployment-support_20.5.0.49152-0+f0_windows_all.nipkg
Package: ni-package-manager-deployment-support
Plugin: wininst
Provides: ni-package-manager-deployment-support (= 20.5.0.49152-0+f0)
Size: 82809748
Version: 20.5.0.49152-0+f0
Architecture: windows_all
CompatibilityVersion: 0
Depends: system-windows-x86 (>= 20.6.0) | system-windows-x64 (>= 20.6.0)
DisplayName: NI Package Manager Deployment Support
DisplayVersion: 20.6.0
Essential: yes
Filename: ni-package-manager-deployment-support_20.6.0.49316-0+f164_windows_all.nipkg
Package: ni-package-manager-deployment-support
Plugin: wininst
Provides: ni-package-manager-deployment-support (= 20.6.0.49316-0+f164)
Size: 83414756
Version: 20.6.0.49316-0+f164
Architecture: windows_x64
CompatibilityVersion: 0
Depends: system-windows-x64 (>= 20.7.0)
DisplayName: NI Package Manager Deployment Support
DisplayVersion: 20.7.0
Essential: yes
Eula: eula-ni-standard
Filename: ni-package-manager-deployment-support_20.7.0.49347-0+f195_windows_x64.nipkg
OsRequires: >= 10
Package: ni-package-manager-deployment-support
Plugin: wininst
Provides: ni-package-manager-deployment-support (= 20.7.0.49347-0+f195)
Size: 83882240
Version: 20.7.0.49347-0+f195
Architecture: windows_x64
CompatibilityVersion: 170006
Conflicts: e2cfc358-ea97-42b7-8400-4dc41fbda64a (< 17.0.0)
Depends: ni-mdfsupport (>= 17.0.0),ni-metauninstaller (>= 17.0.0)
DisplayName: NI-Cabled PCIe
DisplayVersion: 17.3.0
Eula: eula-ni-standard,
Filename: ../../../../pool/ni-c/ni-cabled-pcie_17.3.0.49152-0+f0_windows_x64.nipkg
Homepage: http://www.ni.com
Package: ni-cabled-pcie
Plugin: wininst
Provides: 6a17ed9f-8c3a-4d81-91ad-7af5a7cb8f51 (= 17.30.49152),e2cfc358-ea97-42b7-8400-4dc41fbda64a (= 17.30.49152),ni-cabled-pcie (= 17.3.0.49152-0+f0)
Recommends: ni-certificates (>= 2.0.0)
Replaces: e2cfc358-ea97-42b7-8400-4dc41fbda64a (< 17.0.0)
Size: 1358368
Version: 17.3.0.49152-0+f0
Architecture: windows_x64
CompatibilityVersion: 210000
Conflicts: e2cfc358-ea97-42b7-8400-4dc41fbda64a (< 17.0.0)
Depends: ni-mdfsupport (>= 21.0.0),ni-metauninstaller (>= 21.0.0)
DisplayName: NI-Cabled PCIe
DisplayVersion: 21.0.0
Eula: eula-ni-standard
Filename: ../../../../../pool/ni-c/ni-cabled-pcie/21.0.0/21.0.0.49344-0+f192/ni-cabled-pcie_21.0.0.49344-0+f192_windows_x64.nipkg
OsRequires: >= 10
Package: ni-cabled-pcie
Plugin: wininst
Provides: 6a17ed9f-8c3a-4d81-91ad-7af5a7cb8f51 (= 21.00.49344),e2cfc358-ea97-42b7-8400-4dc41fbda64a (= 21.00.49344),ni-cabled-pcie (= 21.0.0.49344-0+f192)
Recommends: ni-certificates (>= 21.0.0)
Replaces: e2cfc358-ea97-42b7-8400-4dc41fbda64a (< 17.0.0)
Section: Infrastructure
Size: 1514650
UserVisible: no
Version: 21.0.0.49344-0+f192
I removed some fields from the above, but it can still be seen that the packages don't all have identical fields, for example, some have an OsRequires, and some do not. Some define UserVisible, others do not.
I want to extract an array of objects with at least the CompatibilityVersion, Conflicts, Depends, Package, Provides, amd Replaces properties, but being able to get a 'full' set would be ideal.
My initial attempt at a template file was as follows (to capture just a couple of properties):
{Object*:
{Architecture: windows_x86}
{CompatibilityVersion: 0}
{Version: 17.3.0.49152-0+f0}
}
{Object*:
{Architecture: windows_all}
{CompatibilityVersion: 0}
{Version: 20.0.0.49152-0+f0}
}
{Object*:
{Architecture: windows_x64}
{CompatibilityVersion: 190601}
{Version: 21.0.0.49344-0+f192}
}
Should I be grouping my collections of properties in an outer element? If so, is this the correct method?
When I run this without the "Version" property in the template, I get the following (for a subset of the input, that is, only the 'ni-cabled-pcie' matching packages):
nipkg info ni-cabled-pcie | ConvertFrom-String -TemplateFile .\PackageInfoTemplate2.txt
Object
------
{@{CompatibilityVersion= 170006}}
Description: NI-Cabled PCIe
LanguageSupport: en
Package: ni-cabled-pcie
Section: Infrastructure
{@{CompatibilityVersion= 190006}}
Description: NI-Cabled PCIe
MD5sum: ac911971f7579d9ec6644a1fc6fb518a
Package: ni-cabled-pcie
Section: Infrastructure
{@{CompatibilityVersion= 200003}}
Description: NI-Cabled PCIe
{@{CompatibilityVersion= 6102}}
Package: ni-cabled-pcie
Section: Infrastructure
{@{CompatibilityVersion= 210000}}
Description: NI-Cabled PCIe
{@{CompatibilityVersion= 4}}
{@{CompatibilityVersion= 10}}
Package: ni-cabled-pcie
Section: Infrastructure
which looks vaguely promising, but adding the version tag throws me the "ConvertFrom-String appears to be having trouble parsing your data using the template you've provided." message.
Beyond this, the output from that command is still an array of strings, one per line - I'd like to get an array of objects with multiple properties per object so that I could meaningfully, for example, pipe them to Format-Table.
Edit:
Following the solution given by @Theo, I discover the problem with simplifying an example. Some of the packages have duplicate (via case insensitivity) keys which breaks the ConvertFrom-StringData call.
A working replacement looks like:
$data2 = $cmdOutput -replace '(?<!:.*):', '=' -split '(\r?\n){4,}' |
Where-Object { $_ -match '\S' } | ForEach-Object {
# convert the resulting data into Hashtables and cast to PsCustomObject
$o = new-object -typename PSObject;
$_.split([Environment]::NewLine) | Where-Object { $_ -match '\S' } | ForEach-Object {
$o | Add-Member -NotePropertyName $_.split('=')[0] -NotePropertyValue $_.split('=')[1] -Force
}; $o
}
Here the -Force argument handles duplicate arguments (the value is the same in each case) but it seems likely an untidy solution.
How should I handle this case? (Or is the use of New-Object and iteratively adding each property the appropriate solution)?
Small reproduction here-string for the input with duplicate key:
$c1 = @'
Architecture= windows_x64
MD5Sum= 09e5ccbd2dd2bede51d0ff8e2077d415
MD5sum= 09e5ccbd2dd2bede51d0ff8e2077d415
'@
$c1 | ConvertFrom-StringData