13

I have a powershell Array object that is programmatically generated, something with arrays inside arrays, inside arrays, sometimes called a "property bag" or a "hashtable", but I think it's natively called an "Array containing Arrays" in the most native powershell terminology.

For example:

 @{
 Version  = '1.0.0'
 Name     = 'thing'
 Revision = 'c3a89cd20e19bb82f41e95e0806edc5b6cfd224e'
 Date     = '2016-12-09'
 Build    = '1234'
 Contents = @{
      "index.html" = "23dd7b993f40bb3ae8848fe104b3b767"
 }
 }

Generating a function to save only one specific set of contents to a .PSD1 file seems not general enough. I want to save that exact in-memory Array structure to a PSD1 file. Does any built-in way in Powershell exist to Persist an in-memory variable with the values above? The "opposite function" of Import-PowershellDataFile. I would have guessed it would be called Export-PowershellDatafile but no such function seems to exist.

Warren P
  • 65,725
  • 40
  • 181
  • 316
  • I was just wondering about modifying a psd1 without just doing text-manipulaion...timely question! – Mike Shepard Dec 12 '16 at 19:38
  • 3
    [Powershell Pipeworks](https://github.com/StartAutomating/Pipeworks) wrote a couple a functions that might do what you are looking for: `Export-PSData` and `Write-PowerShellHashtable` – BenH Dec 12 '16 at 20:48
  • whats wrong with `Export-Clixml`? – 4c74356b41 Dec 12 '16 at 20:59
  • 1
    Because I want to load it in as .PSD1. I guess I could just round-trip in XML, but why not have round trip in PSD1 too? – Warren P Dec 12 '16 at 20:59
  • Logged feature request on powershell project on github: https://github.com/PowerShell/PowerShell/issues/2875 – Warren P Dec 12 '16 at 21:00
  • Powershell-pipeworks functions works fine for this, they call it Property bags. Feel free to convert that comment to an answer. Total is about 185 lines of code. https://www.gitlab.com/warren.postma/hai/snippets/33366 – Warren P Dec 12 '16 at 21:28
  • 2
    Great question, and I suggest adding a link to your [feature suggestion on GitHub](https://github.com/PowerShell/PowerShell/issues/2875) to your answer. Note that these are _not_ arrays you're dealing with - only [nested] _hashtables_ (instances of `[hashtable]` (`[System.Collections.Hashtable]`)). – mklement0 Nov 24 '17 at 23:01
  • Did you ever solve this @WarrenP? This question is almost 2.5 years old – trebleCode May 03 '19 at 19:00

2 Answers2

1

Have you tried using New-ModuleManifest? Without knowing any additional details, it appears that you're creating something substantially similar to a manifest file used in a module... But even if your use case is different, you should still be able to use the cmdlet.

New-ModuleManifest has been around for a while (at least since v3, but I seem to recall using it with v2 as well). It allows you to define a hashtable of properties and save it down as a .psd1.

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/new-modulemanifest?view=powershell-5.1

genesys
  • 310
  • 1
  • 4
  • 11
1

Originated from this Save hash table in PowerShell object notation (PSON) question, I created (and still maintaining) a PowerShell cmdlet that evolved to a ConvertTo-Expression. The ultimate goal of this script is to be able to export and import PowerShell objects between systems based on a correct PowerShell syntax rather than an exotic format like [JSON]( or [XML].
This includes differentiating between an array of bytes and a byte array but also correctly accepting (and formatting) singletons.
The output is [ScriptBlock] which can be easily save as an expression. The point is that (depending on the usage) it might create a security hole when eventually invoking (c.q. dot sourcing) it (see: Running partly trusted PowerShell code in a restricted security environment. #12377).
Anyways, I also included an -Explore parameter which I belief gives exactly the same output as required for the PSD1 PowerShell Data File. I actually never thought about this usage earlier but now considering to alias this parameter and give it an exclusive meaning for PSD1 files in my next version.
In other words:

$Data = @{
 Version  = '1.0.0'
 Name     = 'thing'
 Revision = 'c3a89cd20e19bb82f41e95e0806edc5b6cfd224e'
 Date     = '2016-12-09'
 Build    = '1234'
 Contents = @{
      "index.html" = "23dd7b993f40bb3ae8848fe104b3b767"
 }
 }

ConvertTo-Expression -Explore $Data # | Out-File .\MyData.psd1

Returns a [ScriptBlock] which automatically converts to the following expression when e.g. exporting it to a file or simply displaying it:

@{
        'Date' = '2016-12-09'
        'Revision' = 'c3a89cd20e19bb82f41e95e0806edc5b6cfd224e'
        'Version' = '1.0.0'
        'Build' = '1234'
        'Contents' = @{'index.html' = '23dd7b993f40bb3ae8848fe104b3b767'}
        'Name' = 'thing'
}
iRon
  • 20,463
  • 10
  • 53
  • 79