Skip to content

Commit

Permalink
Merge pull request #66 from lipkau/feature/#65-allow_keys_without_value
Browse files Browse the repository at this point in the history
Feature/#65 allow keys without value
  • Loading branch information
lipkau authored Jun 17, 2024
2 parents 678df4f + a15f2c0 commit 5ce8bef
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 21 deletions.
11 changes: 10 additions & 1 deletion PSIni/Private/Out-Keys.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@

[Parameter()]
[Switch]
$IgnoreComments
$IgnoreComments,

[Parameter()]
[Switch]
$SkipTrailingEqualSign
)

begin {
Expand All @@ -62,6 +66,11 @@
Out-File -InputObject "$CommentChar$($InputObject[$key])" @outFileParameter
}
}
elseif (-not $InputObject[$key]) {
Write-Verbose "$($MyInvocation.MyCommand.Name):: Writing key: $key without value"
$keyToWrite = if ($SkipTrailingEqualSign) { "$key" } else { "$key$delimiter" }
Out-File -InputObject $keyToWrite @outFileParameter
}
else {
foreach ($entry in $InputObject[$key]) {
Write-Verbose "$($MyInvocation.MyCommand.Name):: Writing key: $key"
Expand Down
57 changes: 40 additions & 17 deletions PSIni/Public/Export-Ini.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@ function Export-Ini {
Description
Creating a custom Hashtable and saving it to C:\MyNewFile.ini
.Example
$Winpeshl = @{
LaunchApp = @{
AppPath = %"SYSTEMDRIVE%\Fabrikam\shell.exe"
}
LaunchApps = @{
"%SYSTEMDRIVE%\Fabrikam\app1.exe" = $null
'%SYSTEMDRIVE%\Fabrikam\app2.exe, /s "C:\Program Files\App3"' = $null
}
}
Export-Ini -InputObject $Winpeshl -FilePath "winpeshl.ini" -SkipTrailingEqualSign
-----------
Description
Example as per https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/winpeshlini-reference-launching-an-app-when-winpe-starts
.Link
Import-Ini
ConvertFrom-Ini
Expand All @@ -51,6 +66,18 @@ function Export-Ini {
[CmdletBinding()]
[OutputType( [System.IO.FileSystemInfo] )]
param(
# Specifies the Hashtable to be written to the file.
# Enter a variable that contains the objects or type a command or expression that gets the objects.
[Parameter( Mandatory, ValueFromPipeline )]
[System.Collections.IDictionary]
$InputObject,

# Specifies the path to the output file.
[Parameter( Mandatory )]
[ValidateScript( { Invoke-ConditionalParameterValidationPath -InputObject $_ } )]
[String]
$Path,

# Adds the output to the end of an existing file, instead of replacing the file contents.
[Switch]
$Append,
Expand All @@ -62,12 +89,6 @@ function Export-Ini {
[String]
$Encoding = "UTF8",

# Specifies the path to the output file.
[Parameter( Position = 0, Mandatory )]
[ValidateScript( { Invoke-ConditionalParameterValidationPath -InputObject $_ } )]
[String]
$Path,

# Allows the cmdlet to overwrite an existing read-only file.
# Even using the Force parameter, the cmdlet cannot override security restrictions.
[Parameter()]
Expand All @@ -84,12 +105,6 @@ function Export-Ini {
[String]
$Format = "pretty",

# Specifies the Hashtable to be written to the file.
# Enter a variable that contains the objects or type a command or expression that gets the objects.
[Parameter( Mandatory, ValueFromPipeline )]
[System.Collections.IDictionary]
$InputObject,

# Passes an object representing the location to the pipeline.
# By default, this cmdlet does not generate any output.
[Parameter()]
Expand All @@ -99,7 +114,14 @@ function Export-Ini {
# Will not write comments to the output file
[Parameter()]
[Switch]
$IgnoreComments
$IgnoreComments,

# Does not add trailing = sign to keys without value.
# This behavior is needed for specific OS files, such as:
# https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/winpeshlini-reference-launching-an-app-when-winpe-starts
[Parameter()]
[Switch]
$SkipTrailingEqualSign
)

begin {
Expand Down Expand Up @@ -129,10 +151,11 @@ function Export-Ini {
if ($section -ne $script:NoSection) { Out-File -InputObject "[$section]" @fileParameters }

$outKeysParam = @{
InputObject = $InputObject[$section]
Delimiter = $delimiter
IgnoreComments = $IgnoreComments
CommentChar = ";"
InputObject = $InputObject[$section]
Delimiter = $delimiter
IgnoreComments = $IgnoreComments
CommentChar = ";"
SkipTrailingEqualSign = $SkipTrailingEqualSign
}
Out-Keys @outKeysParam @fileParameters

Expand Down
13 changes: 13 additions & 0 deletions PSIni/Public/Import-Ini.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,19 @@ function Import-Ini {
}
continue
}
Default {
# No match
# As seen in https://github.com/lipkau/PsIni/issues/65, some software writes keys without
# the `=` sign.
if (-not $section) {
$section = $script:NoSection
$ini[$section] = New-Object System.Collections.Specialized.OrderedDictionary([System.StringComparer]::OrdinalIgnoreCase)
}
$name = $_
Write-Verbose "$($MyInvocation.MyCommand.Name):: Adding key $name without a value"
$ini[$section][$name] = $null
continue
}
}

$ini
Expand Down
2 changes: 1 addition & 1 deletion Tests/ConvertFrom-Ini.Unit.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Describe "ConvertFrom-Ini" -Tag "Unit" {
It "has the ini sections and keys without a section as root properties" {
$convertedObject = ConvertFrom-Ini -Path $iniFile

($convertedObject | Get-Member -MemberType *Property).Name | Should -Be @("Arrays", "Comment1", "Key", "Strings")
($convertedObject | Get-Member -MemberType *Property).Name | Should -Be @("Arrays", "Comment1", "Key", "NoValues", "Strings")
}

It "treats the value of a key as string" {
Expand Down
23 changes: 23 additions & 0 deletions Tests/Export-Ini.Unit.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ Describe "Export-Ini" -Tag "Unit" {
$additionalObject["Additional"]["Key1"] = "Value1"

$additionalFileContent = "[Additional]${lf}Key1 = Value1${lf}"

$objectWithEmptyKeys = New-Object System.Collections.Specialized.OrderedDictionary([System.StringComparer]::OrdinalIgnoreCase)
$objectWithEmptyKeys["NoValues"] = New-Object System.Collections.Specialized.OrderedDictionary([System.StringComparer]::OrdinalIgnoreCase)
$objectWithEmptyKeys["NoValues"]["Key1"] = $null
$objectWithEmptyKeys["NoValues"]["Key2"] = ""
}

It "saves an object as ini file" {
Expand Down Expand Up @@ -164,5 +169,23 @@ Describe "Export-Ini" -Tag "Unit" {

(Get-FileEncoding -Path $testPath).Encoding | Should -Be "UTF32-LE"
}

It "writes out keys without a value" {
Export-Ini @commonParameter -InputObject $objectWithEmptyKeys -Format minified

$fileContent = Get-Content -Path $testPath -Raw
$expectedFileContent = "[NoValues]${lf}Key1=${lf}Key2=${lf}"

$fileContent | Should -Be $expectedFileContent
}

It "writes out keys without trailing equal sign when no value is assigned" {
Export-Ini @commonParameter -InputObject $objectWithEmptyKeys -Format minified -SkipTrailingEqualSign

$fileContent = Get-Content -Path $testPath -Raw
$expectedFileContent = "[NoValues]${lf}Key1${lf}Key2${lf}"

$fileContent | Should -Be $expectedFileContent
}
}
}
16 changes: 14 additions & 2 deletions Tests/Import-Ini.Unit.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ Describe "Import-Ini" -Tag "Unit" {
It "loads the sections as expected" {
$dictOut = Import-Ini -Path $iniFile

$dictOut.Keys | Should -Be "_", "Strings", "Arrays"
$dictOut.Keys | Should -Be "_", "Strings", "Arrays", "NoValues"
}

It "uses a module-wide variable for the keys that don't have a section" {
InModuleScope PsIni { $script:NoSection = "NoName" }
$dictOut = Import-Ini -Path $iniFile

$dictOut.Keys | Should -Be "NoName", "Strings", "Arrays"
$dictOut.Keys | Should -Be "NoName", "Strings", "Arrays", "NoValues"
$dictOut["NoName"]["Key"] | Should -Be "With No Section"
}

Expand Down Expand Up @@ -127,5 +127,17 @@ Describe "Import-Ini" -Tag "Unit" {
$withComments["Strings"].Keys | Should -Contain "Comment1"
$withoutComments["Strings"].Keys | Should -Not -Contain "Comment1"
}

It "stores keys without a value" {
$dictOut = Import-Ini -Path $iniFile

$dictOut["NoValues"]["Key1"] | Should -BeNullOrEmpty
}

It "stores keys without a value even when they don't have an `=` sign" {
$dictOut = Import-Ini -Path $iniFile

$dictOut["NoValues"]["Key2"] | Should -BeNullOrEmpty
}
}
}
3 changes: 3 additions & 0 deletions Tests/sample.ini
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ Array1 = 1,2,3
Array1 = 4,5,6
Array1 = 7,8,9
String1 = 0,0,0
[NoValues]
Key1=
Key2

0 comments on commit 5ce8bef

Please sign in to comment.