lipkau / PsIni

Work with INI files in PowerShell using hashtables
http://lipkau.github.io/PsIni
MIT License
151 stars 50 forks source link

INI file that does not have a section #34

Closed kevinelwell closed 7 years ago

kevinelwell commented 7 years ago

Is there a way for this to read a non-standard INI file that does not contain a section?

example: Server="10.10.10.10"

I tried using: $out = Get-IniContent "C:\ini.ini $out["NoSection"]["Server"]

but that did not work. Any ideas? Thanks!

lipkau commented 7 years ago

If you are using the lastest version, the value should be available at $out["_"]["Server"] (the default NoSection is _) Please let me know or close this issue if this fixed the problem

Also, you are missing a closing " in your sample code

Screenshot: ScreenShort

kevinelwell commented 7 years ago

Thank you for the quick response and my apologies for missing the closing double quote.

If i import the PsIni module i am able to read the INI. Sample Code: Import-Module -Name PsIni

$Svr = $null $Port = $null $Val = Get-IniContent "C:\Temp\test\test\Server.ini" -Verbose -ErrorAction SilentlyContinue

$Svr = $Val[""]["SERVER"] $Port = $Val[""]["Port"]

Write-Host "Server: $Svr" Write-Host "Port: $Port"

Results: VERBOSE: Get-IniContent:: Function started VERBOSE: Get-IniContent:: Processing file: C:\Temp\test\test\Server.ini VERBOSE: Get-IniContent:: Adding key SERVER with value: "10.10.10.10" VERBOSE: Get-IniContent:: Adding key Port with value: 8080 VERBOSE: Get-IniContent:: Finished Processing file: C:\Temp\test\test\Server.ini VERBOSE: Get-IniContent:: Function ended Server: "10.10.10.10" Port: 8080

If i try to just the Get-IniContent function without the module, it fails to read the INI.

Sample Code: `Set-StrictMode -Version Latest Function Get-IniContent { <# .Synopsis Gets the content of an INI file

.Description
    Gets the content of an INI file and returns it as a hashtable

.Notes
    Author      : Oliver Lipkau <oliver@lipkau.net>
    Source      : https://github.com/lipkau/PsIni
                  http://gallery.technet.microsoft.com/scriptcenter/ea40c1ef-c856-434b-b8fb-ebd7a76e8d91
    Version     : 1.0.0 - 2010/03/12 - OL - Initial release
                  1.0.1 - 2014/12/11 - OL - Typo (Thx SLDR)
                                          Typo (Thx Dave Stiff)
                  1.0.2 - 2015/06/06 - OL - Improvment to switch (Thx Tallandtree)
                  1.0.3 - 2015/06/18 - OL - Migrate to semantic versioning (GitHub issue#4)
                  1.0.4 - 2015/06/18 - OL - Remove check for .ini extension (GitHub Issue#6)
                  1.1.0 - 2015/07/14 - CB - Improve round-tripping and be a bit more liberal (GitHub Pull #7)
                                       OL - Small Improvments and cleanup
                  1.1.1 - 2015/07/14 - CB - changed .outputs section to be OrderedDictionary
                  1.1.2 - 2016/08/18 - SS - Add some more verbose outputs as the ini is parsed,
                                            allow non-existent paths for new ini handling,
                                            test for variable existence using local scope,
                                            added additional debug output.

    #Requires -Version 2.0

.Inputs
    System.String

.Outputs
    System.Collections.Specialized.OrderedDictionary

.Parameter FilePath
    Specifies the path to the input file.

.Parameter CommentChar
    Specify what characters should be describe a comment.
    Lines starting with the characters provided will be rendered as comments.
    Default: ";"

.Parameter IgnoreComments
    Remove lines determined to be comments from the resulting dictionary.

.Example
    $FileContent = Get-IniContent "C:\myinifile.ini"
    -----------
    Description
    Saves the content of the c:\myinifile.ini in a hashtable called $FileContent

.Example
    $inifilepath | $FileContent = Get-IniContent
    -----------
    Description
    Gets the content of the ini file passed through the pipe into a hashtable called $FileContent

.Example
    C:\PS>$FileContent = Get-IniContent "c:\settings.ini"
    C:\PS>$FileContent["Section"]["Key"]
    -----------
    Description
    Returns the key "Key" of the section "Section" from the C:\settings.ini file

.Link
    Out-IniFile
#>

[CmdletBinding()]
[OutputType(
    [System.Collections.Specialized.OrderedDictionary]
)]
Param(
    [ValidateNotNullOrEmpty()]
    [Parameter(ValueFromPipeline=$True,Mandatory=$True)]
    [string]$FilePath,
    [char[]]$CommentChar = @(";"),
    [switch]$IgnoreComments
)

Begin
{
    Write-Debug "PsBoundParameters:"
    $PSBoundParameters.GetEnumerator() | ForEach-Object { Write-Debug $_ }
    if ($PSBoundParameters['Debug']) { $DebugPreference = 'Continue' }
    Write-Debug "DebugPreference: $DebugPreference"

    Write-Verbose "$($MyInvocation.MyCommand.Name):: Function started"

    $commentRegex = "^([$($CommentChar -join '')].*)$"
    Write-Debug ("commentRegex is {0}." -f $commentRegex)
}

Process
{
    Write-Verbose "$($MyInvocation.MyCommand.Name):: Processing file: $Filepath"

    $ini = New-Object System.Collections.Specialized.OrderedDictionary([System.StringComparer]::OrdinalIgnoreCase)

    if (!(Test-Path $Filepath))
    {
        Write-Verbose ("Warning: `"{0}`" was not found." -f $Filepath)
        return $ini
    }

    $commentCount = 0
    switch -regex -file $FilePath
    {
        "^\s*\[(.+)\]\s*$" # Section
        {
            $section = $matches[1]
            Write-Verbose "$($MyInvocation.MyCommand.Name):: Adding section : $section"
            $ini[$section] = New-Object System.Collections.Specialized.OrderedDictionary([System.StringComparer]::OrdinalIgnoreCase)
            $CommentCount = 0
            continue
        }
        $commentRegex # Comment
        {
            if (!$IgnoreComments)
            {
                if (!(test-path "variable:local:section"))
                {
                    $section = $script:NoSection
                    $ini[$section] = New-Object System.Collections.Specialized.OrderedDictionary([System.StringComparer]::OrdinalIgnoreCase)
                }
                $value = $matches[1]
                $CommentCount++
                Write-Debug ("Incremented CommentCount is now {0}." -f $CommentCount)
                $name = "Comment" + $CommentCount
                Write-Verbose "$($MyInvocation.MyCommand.Name):: Adding $name with value: $value"
                $ini[$section][$name] = $value
            }
            else { Write-Debug ("Ignoring comment {0}." -f $matches[1]) }

            continue
        }
        "(.+?)\s*=\s*(.*)" # Key
        {
            if (!(test-path "variable:local:section"))
            {
                $section = $script:NoSection
                $ini[$section] = New-Object System.Collections.Specialized.OrderedDictionary([System.StringComparer]::OrdinalIgnoreCase)
            }
            $name,$value = $matches[1..2]
            Write-Verbose "$($MyInvocation.MyCommand.Name):: Adding key $name with value: $value"
            $ini[$section][$name] = $value
            continue
        }
    }
    Write-Verbose "$($MyInvocation.MyCommand.Name):: Finished Processing file: $FilePath"
    Return $ini
}

End
    {Write-Verbose "$($MyInvocation.MyCommand.Name):: Function ended"}

}

Set-Alias gic Get-IniContent $Svr = $null $Port = $null $Val = Get-IniContent "C:\Temp\test\test\Server.ini" -Verbose -ErrorAction SilentlyContinue

$Svr = $Val[""]["SERVER"] $Port = $Val[""]["Port"]

Write-Host "Server: $Svr" Write-Host "Port: $Port" '

Results: VERBOSE: Get-IniContent:: Function started VERBOSE: Get-IniContent:: Processing file: C:\Temp\test\test\Server.ini VERBOSE: Get-IniContent:: Adding key SERVER with value: "10.10.10.10" VERBOSE: Get-IniContent:: Adding key Port with value: 8080 VERBOSE: Get-IniContent:: Finished Processing file: C:\Temp\test\test\Server.ini VERBOSE: Get-IniContent:: Function ended Cannot index into a null array.At line:166 char:1

Cannot index into a null array.At line:167 char:1

Server: Port:

Am i able to use the function without importing the module?

kevinelwell commented 7 years ago

INI content:

SERVER = "10.10.10.10" Port=8080

kevinelwell commented 7 years ago

Disregard, i found out why. I see the $script:NoSection = "_" entry in the PsIni.psm1.

If i add that code just below the Get-IniContent function, I am able to get the desired results.

Thank you for creating this fantastic module. It is extremely useful to me.

-Kevin

lipkau commented 7 years ago

Glad to hear that. :-)