Export-PSObjectToINI.ps1

<#PSScriptInfo
 
.VERSION 0.0.0.1
 
.GUID a97d917e-d6bc-4a98-93be-edf84a8e0fe2
 
.AUTHOR Luke Dalton
 
.COPYRIGHT GNU GPL v3
 
.TAGS INI
 
.LICENSEURI https://www.gnu.org/licenses/gpl-3.0.en.html
 
.PROJECTURI https://psytechnic.blogspot.co.uk
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
  (c) 25 September 2018
  Version History:
  0.0.0.1 - First Write
 
.DESCRIPTION
  Exports a custom PSObject to an INI file
  PSObject Template:
  $example=[pscustomobject]@{
    rootProp1='value1'
    rootProp2='value2'
    section1=[pscustomobject]@{
      sectProp1='value3'
      sectProp2='value4'
    }
    section2=[pscustomobject]@{
      sectProp1='value5'
      sectProp2='value6'
    }
  }
#>

Function Export-PSObjectToINI{
  [CmdletBinding()]
  [OutputType([System.IO.FileInfo])]
  param(
    # PSObject to write to file
    [Parameter(Position=0,ValueFromPipeline=$True,Mandatory=$True)][ValidateNotNullOrEmpty()][psobject]$Object,
    # Full path of destination .ini file
    [Parameter(Position=1,Mandatory=$True)][ValidateNotNullOrEmpty()][string]$Path,
    # Select text file encoding from: ASCII, BigEndianUnicode, Default, OEM, Unicode, UTF32, UTF7, UTF8
    [Parameter(Mandatory=$false)][ValidateSet('ASCII','BigEndianUnicode','Default','OEM','Unicode','UTF32','UTF7','UTF8')][string]$Encoding="Unicode",
    # Add information to existing file instead of overwriting
    [switch]$Append,
    # Output will have no blank line spaces between sections
    [switch]$NoEmptyLines,
    # Output will enclose section names with the selected QuoteCharacter
    [switch]$QuoteSectionNames,
    # Output will enclose property names with the selected QuoteCharacter
    [switch]$QuotePropertyNames,
    # Output will enclose property values with the selected QuoteCharacter
    [switch]$QuotePropertyValues,
    # Character to use for quoting sections and properties. Default value is "
    [char]$QuoteCharacter='"',
    # Force overwrite of file if it exists
    [switch]$Force,
    # Return FileInfo object after writing
    [switch]$PassThru
  )
  Begin{
    $commandName=$MyInvocation.MyCommand.Name
    $returnLines=@()
    $Script:patternComment='^;Comment[\d]+'
    $Script:patternInline='^;InlineComment[\d]+'
    $inlineAttach=$null
    Function Create-INIString([parameter(Mandatory=$True)][object]$Property){
      if($Property.Value.GetType().Name-eq'PSCustomObject'){
        $line=$(if($QuoteSectionNames){"[$QuoteCharacter$($Property.Name)$QuoteCharacter]"}else{"[$($Property.Name)]"})
        if($Script:inlineAttach){$line=$line+$Script:inlineAttach;$Script:inlineAttach=$null}
        Write-Verbose -Message "Section: $line"
        $line
      }else{
        switch -Regex ($Property.Name){
          $Script:patternComment{"`; $($Property.Value)";Write-Verbose -Message "Comment: $($Property.Value)";Continue}
          $Script:patternInline{$Script:inlineAttach=" `; $($Property.Value)";Write-Verbose -Message "Inline Comment: $Script:inlineAttach";Continue}
          Default{
            $name=$(if($QuotePropertyNames){"$QuoteCharacter$($Property.Name)$QuoteCharacter"}else{$Property.Name})
            $value=$(if($QuotePropertyValues){"$QuoteCharacter$($Property.Value)$QuoteCharacter"}else{$Property.Value})
            $line="$name=$value"
            if($Script:inlineAttach){$line=$line+$Script:inlineAttach;$Script:inlineAttach=$null}
            Write-Verbose -Message "Property: $line"
            $line
            Continue
          }
        }
      }
    }
  }
  Process{
    $Object.psobject.Properties|Where-Object{$_.Value-eq$null}|ForEach-Object{$_.Value=''}
    ForEach($rootProperty in $($Object.psobject.Properties|Where-Object{($_.Value.GetType().Name)-ne'PSCustomObject'})){$returnLines+=Create-INIString -Property $rootProperty}
    if(-not$NoEmptyLines){$returnLines+=''}
    
    ForEach($section in $($Object.psobject.Properties|Where-Object{($_.Value.GetType().Name)-eq'PSCustomObject'})){
      $returnLines+=Create-INIString -Property $section
      ForEach($sectionProperty in $Object."$($section.Name)".psobject.Properties){$returnLines+=Create-INIString -Property $sectionProperty}
      if(-not$NoEmptyLines){$returnLines+=''}
    }
  }
  End{
    try{
      if((-not($Append))-and(Test-Path -Path $Path)){$Confirm=(-not($Force));''|Out-File -FilePath $Path -Encoding:$Encoding -NoNewline -Force:$Force -Confirm:$Confirm -ErrorAction Stop}
      $returnLines|Out-File -FilePath $Path -Append -Encoding:$Encoding -Force:$Force -ErrorAction Stop
      if($Passthru){Get-Item -Path $Path}
    }catch{$_}
  }
}