8
0
Skriptentwickung/current/Modules/Read-ConfigFile2.psm1

366 lines
27 KiB
PowerShell
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Function Read-ConfigFile2 {
<#
.SYNOPSIS
Function will read the given ConfigFile, and returns a HashTable with all Keys and Values.
.DESCRIPTION
This Function will get Script configurations from a ASCII/ANSI based ConfigFile (INI).
The important criterion is, that every Value the should be read, has to look like this: ConfigLabel = ConfigValue
The ConfigFile should be formated within UTF8 and every Line in a ConfigFile which is beginning with a "#", will be ignored!
The Return Value of this Function will be a HashTable Object, with two columns (key column and value/values column).
Every Value in the Value column will be saved as Array value, even there is only one value.
For every line in the ConfigFile, there will be an additional line in HashTable, which says how many line (profiles) where read.
.REQUIREMENT General
PowerShell V3
.REQUIREMENT Assembly
<NONE>
.REQUIREMENT Variables
Counter1, Counter2, ConfigFile, ConfigLabels, ConfigFileLine, ConfigFileLines, ConfigValue, ConfigValues, ConfigFileLineKey, ConfigLinesValue, ConfigLinesValues, ConfigLinesValueSeparator, ConfigFileLineValuesTEMP, HashTable_MetaData
.REQUIREMENT Variables preSet
<NONE>
.REQUIREMENT Functions
<NONE>
.VERSION
Number: 1.2.0.0 / Date: 23.02.2024
.PARAMETER ConfigFile
Optional Parameter. Give the full path to the ConfigFile (eg. <ScriptName>_Settings.ini). (Default: If you dont give it, Function will try the retrieve ConfigFile (Path and Name) from the Global Variables, set by the calling Script.)
.PARAMETER ConfigLabels
Optional Parameter. Give the ConfigLabels (Seperate with a ",") which are very mandatory for a working Script. Script will exit, if one or more are missing or have no Values.
.PARAMETER ConfigLinesDelimiter
Optional Parameter. Set the Delimiter which is in between the ConfigLabel and ConfigValue(s) in the ConfigFile (Default: "=").
.PARAMETER ConfigLinesValueSeparator
Optional Parameter. Set the symbol or character for Value separation (Default: ";"). Please Mask with a "\", if you want that Separator ignored (e.g in a RegEx).
.PARAMETER RemoveMaskingOfConfigLinesValueSeparator
Optional Parameter. Enable or disable, if the masking ("\") mark for ConfigLinesValueSeparator, should be removed after reading it (Default: $False).
.EXAMPLE
Read-ConfigFile2 -ConfigFile <Path>\<ScriptName>_Settings.ini
.EXAMPLE
Read-ConfigFile2 -ConfigFile <Path>\<ScriptName>_Settings.ini -ConfigLabels LogPath
.EXAMPLE
Read-ConfigFile2 -ConfigFile <Path>\<ScriptName>_Settings.ini -ConfigLabels LogPath, LogKeepTime -RemoveMaskingOfConfigLinesValueSeparator
#>
Param (
[Parameter(Position=0,Mandatory=$False,HelpMessage='Optional Parameter. Give the full path to the ConfigFile (eg. <ScriptName>_Settings.ini). (Default: If you dont give it, Function will try the retrieve ConfigFile (Path and Name) from the Global Variables, set by the calling Script.)')]
[ValidateNotNullOrEmpty()]
[STRING]$ConfigFile=(Get-Variable -Name ConfigFile -Scope Global -ValueOnly),
[Parameter(Position=1,Mandatory=$False,HelpMessage='Optional Parameter. Give the ConfigLabels (Seperate with a ",") which are very mandatory for a working Script. Script will exit, if one or more are missing or have no Values.')]
[ValidateNotNullOrEmpty()]
[ARRAY]$ConfigLabels=@(),
[Parameter(Position=2,Mandatory=$False,HelpMessage='Optional Parameter. Set the Delimiter which is in between the ConfigLabel and ConfigValue(s) in the ConfigFile (Default: "=").')]
[ValidateNotNullOrEmpty()]
[STRING]$ConfigLinesDelimiter='=',
[Parameter(Position=3,Mandatory=$False,HelpMessage='Optional Parameter. Set the symbol or character for Value separation (Default: ";"). Please Mask with a "\", if you want that Separator ignored (e.g in a RegEx).')]
[ValidateNotNullOrEmpty()]
[STRING]$ConfigLinesValueSeparator=';',
[Parameter(Position=4,Mandatory=$False,HelpMessage='Optional Parameter. Enable or disable, if the masking ("\") mark for ConfigLinesValueSeparator, should be removed after reading it (Default: $False).')]
[ValidateNotNullOrEmpty()]
[SWITCH]$RemoveMaskingOfConfigLinesValueSeparator=$False
) #end param
#Clear Error Variable
$error.clear()
#Check if ConfigFile exists
IF ((Test-Path -Path $ConfigFile -PathType Leaf -ErrorAction Stop) -eq $true) {
Write-Host "DEBUG Info - Read-ConfigFile2: Module begins reading of ConfigFile:"
Write-Host "DEBUG Info - Read-ConfigFile2: $ConfigFile"
Try {
#Prepare Variables
[INT]$Counter1 = 0
[INT]$Counter2 = 0
[ARRAY]$ConfigFileLine = @()
[ARRAY]$ConfigFileLines = (Select-String -Path $ConfigFile -Pattern "$ConfigLinesDelimiter" -ErrorAction Stop | Where-Object {-not($_-match ":[0-9]{1,}:#")})
[STRING]$ConfigFileLineKey = $NULL
[STRING]$ConfigFileLineValue = $NULL
[ARRAY]$ConfigFileLineValues = @()
[System.Collections.ArrayList]$ConfigFileLineValuesTEMP = @()
[ARRAY]$HashTable_MetaData = @($($ConfigFile),$(Get-Date -Format 'ddMMyyyy_HHmmssffff'))
Write-Host "DEBUG Info - Read-ConfigFile2: Found $($ConfigFileLines.count) relevant Lines in ConfigFile!"
#Prepare HashTable incl. Fallback to PowerShell Version 2 compatibility
Try {
$ConfigFileTable = [ordered]@{}
} #end try
Catch {
$ConfigFileTable = New-Object [System.Collections.Specialized.OrderedDictionary]([System.StringComparer]::OrdinalIgnoreCase) -ErrorAction Stop
Try {
$ConfigFileTable = New-Object [System.Collections.Specialized.OrderedDictionary] -ErrorAction Stop
} #end try
Catch {
Write-Host "DEBUG Info - Read-ConfigFile2: Cannot create HashTable for Config Values!"
Write-Host "DEBUG Info - Read-ConfigFile2: Exiting, because of this Issue."
Write-Host $Error
EXIT
} #end catch
} #end catch
#First Key and Value in HashTable was about its own Metadata Informations
$ConfigFileTable.Add("HashTable_MetaData",$HashTable_MetaData)
Write-Host ""
Write-Host "DEBUG Info - Read-ConfigFile2: HashTable Key with name: HashTable_MetaData,"
Write-Host "DEBUG Info - Read-ConfigFile2: got this Value: $HashTable_MetaData)"
} #end try
Catch {
Write-Host "DEBUG Info - Read-ConfigFile2: Module cannot read ConfigFile:"
Write-Host "DEBUG Info - Read-ConfigFile2: $ConfigFile"
Write-Host "DEBUG Info - Read-ConfigFile2: Exiting, because of this Issue."
Write-Host $Error
EXIT
} #end catch
DO {
#Loop for each Line in ConfigFile
$ConfigFileLine = ($ConfigFileLines.SyncRoot[$Counter1]).line
IF ([INT](([REGEX]::Matches($ConfigFileLine,"$ConfigLinesDelimiter")).count) -gt 1) {
Write-Host "DEBUG Info - Read-ConfigFile2: Multiple ConfigLinesDelimiters found $((([REGEX]::Matches($ConfigFileLine,"$ConfigLinesDelimiter")).count)) "
$ConfigFileLine = ($ConfigFileLine -split "$ConfigLinesDelimiter",2)
} #end elseif
ELSE {
$ConfigFileLine = ($ConfigFileLine -split "$ConfigLinesDelimiter")
} #end else
$Counter1++ | Out-Null
Write-Host ""
#The Key is easy to determ
($ConfigFileLine[0]) = ($ConfigFileLine[0].TrimStart())
($ConfigFileLine[0]) = ($ConfigFileLine[0].TrimEnd())
($ConfigFileLineKey) = ($ConfigFileLine[0])
Write-Host "DEBUG Info - Read-ConfigFile2: HashTable Key with name: $($ConfigFileLine[0]),"
#The Value is more work - first we have to check if Value is empty and if Failsave Value is available
IF (([String]::IsNullOrEmpty($ConfigFileLine[1])) -or ([String]::IsNullOrWhiteSpace($ConfigFileLine[1]))) {
Try {
Write-Host "DEBUG Info - Read-ConfigFile2: $($ConfigFileLine[0]) has no Value, trying to get FailSafe Value from main Script!"
($ConfigFileLine[1]) = (Get-Variable -Name $($ConfigFileLine[0]) -Scope Global -ValueOnly -ErrorAction Stop)
#If a object returns, set Array value back to an empty string,
#because this happens if a config line in the ini file is empty (like: Profile = )
If ($ConfigFileLine[1].gettype() -is [System.Object]) {
$ConfigFileLine[1] = [String]$Null
} #end if
Write-Host "DEBUG Info - Read-ConfigFile2: FailSafe Value returnd and set!"
Write-Host "DEBUG Info - Read-ConfigFile2: Got this Value: $($ConfigFileLine[1])"
} #end try
Catch {
Write-Host "DEBUG Info - Read-ConfigFile2: FailSafe cannot be found, leaving empty!"
Write-Host "DEBUG Info - Read-ConfigFile2: ... could be a Issue, if the ConfigLabel was mandatory set by function call!"
} #end catch
} #end if
ELSE {
Write-Host "DEBUG Info - Read-ConfigFile2: got this Value: $($ConfigFileLine[1])"
} #end else
#If the Value line includes the ValueSeperator, split the Value! Except ValueSeperator is escaped/masked by a "\", like its standard in a RegEx
IF ($($ConfigFileLine[1]) | Where-Object {($_-match "$ConfigLinesValueSeparator")} | Where-Object {-not($_-match "\\$ConfigLinesValueSeparator")}) {
Write-Host "DEBUG Info - Read-ConfigFile2: Found ConfigLinesValueSeparator in Value from $($ConfigFileLine[0])"
($ConfigFileLineValues) = ($ConfigFileLine[1] -split "$ConfigLinesValueSeparator")
FOREACH ($ConfigFileLineValue in $ConfigFileLineValues) {
$ConfigFileLineValue = ($ConfigFileLineValue.TrimStart())
$ConfigFileLineValue = ($ConfigFileLineValue.TrimEnd())
$ConfigFileLineValuesTEMP.Add($ConfigFileLineValue) | Out-Null
} #end foreach
$ConfigFileLineValues = @($ConfigFileLineValuesTEMP)
$ConfigFileLineValuesTEMP = @()
} #end if
ELSE {
#Maybe you want the remove the "\", because ConfigLinesValueSeparator was set but for one line or case not used
IF ($RemoveMaskingOfConfigLinesValueSeparator -eq $True) {
($ConfigFileLine[1]) = ($ConfigFileLine[1].Replace("\$ConfigLinesValueSeparator","$ConfigLinesValueSeparator"))
} #end if
($ConfigFileLine[1]) = ($ConfigFileLine[1].TrimStart())
($ConfigFileLine[1]) = ($ConfigFileLine[1].TrimEnd())
($ConfigFileLineValues) = ($ConfigFileLine[1])
} #end else
#Finally fill keys and values into the HashTable
Try {
#If the Key is first time inserting
IF (($ConfigFileTable.Contains($ConfigFileLineKey)) -eq $False) {
Write-Host "DEBUG Info - Read-ConfigFile2: Inserting a single line Value into the HashTable!"
$Counter2++ | Out-Null
$ConfigFileTable.Add($ConfigFileLineKey,$($Counter2,"Profile(s)"))
$ConfigFileTable.Add(($ConfigFileLineKey+'_'+$Counter2),$ConfigFileLineValues)
$Counter2=0 | Out-Null
} #end if
#If the Key is second and more time(s) inserting, like its used in profiles
ELSE {
Write-Host "DEBUG Info - Read-ConfigFile2: Inserting multi line Values into the HashTable!"
DO {
$Counter2++ | Out-Null
} #end do
UNTIL (($ConfigFileTable.Contains($ConfigFileLineKey+'_'+$Counter2)) -eq $False)
$ConfigFileTable.$ConfigFileLineKey = @($Counter2,"Profile(s)")
$ConfigFileTable.Add(($ConfigFileLineKey+'_'+$Counter2),$ConfigFileLineValues)
$Counter2=0 | Out-Null
} #end elseif
} #end try
#Getting last Exeption Message or Code: $Error[0] | fl * -Force
Catch {
Write-Host "DEBUG Info - Read-ConfigFile2: Error inserting into HashTable!"
Write-Host $Error
} #end catch
} #end do
UNTIL ($Counter1 -eq ($ConfigFileLines.Count))
Write-Host ""
Write-Host "DEBUG Info - Read-ConfigFile2: Set $($ConfigFileTable.Count) lines in HashTable!"
#Check for mandatory Keys and Values! Exit whole Script if something is missing!
IF ($ConfigLabels.count -gt 0) {
FOREACH ($ConfigLabel in $ConfigLabels) {
Write-Host ""
Write-Host "DEBUG Info - Read-ConfigFile2: Checking if mandatory ConfigLabel: $ConfigLabel - exists in HashTable"
IF ($ConfigFileTable.Contains($ConfigLabel) -eq $True) {
Write-Host "DEBUG Info - Read-ConfigFile2: Yes, ConfigLabel exisits!"
Write-Host "DEBUG Info - Read-ConfigFile2: Checking if mandatory ConfigLabel: $ConfigLabel - has a Value"
IF (!([String]::IsNullOrEmpty($ConfigFileTable.Get_Item($ConfigLabel))) -or (![String]::IsNullOrWhiteSpace($ConfigFileTable.Get_Item($ConfigLabel)))) {
Write-Host "DEBUG Info - Read-ConfigFile2: Yes, value for ConfigLabel exisits!"
} #end if
ELSE {
Write-Host "DEBUG Info - Read-ConfigFile2: No, value for ConfigLabel does exisit!"
Write-Host "DEBUG Info - Read-ConfigFile2: Exiting, because of this Issue."
Write-Host $Error
EXIT
} #end else
} #end if
ELSE {
Write-Host "DEBUG Info - Read-ConfigFile2: No, ConfigLabel does not exisit!"
Write-Host "DEBUG Info - Read-ConfigFile2: Exiting, because of this Issue."
Write-Host $Error
EXIT
} #end else
} #end foreach
} #end if
ELSE {
Write-Host ""
Write-Host "DEBUG Info - Read-ConfigFile2: No mandatory ConfigLabels are set!"
} #end else
#Show the whole HashTable in GUI - for Debug reasons
#$ConfigFileTable | Out-GridView
#Return the whole HashTable
Return $ConfigFileTable
} #end try
ELSE {
Write-Host "DEBUG Info - Read-ConfigFile2: Module cannot get content of ConfigFile:"
Write-Host "DEBUG Info - Read-ConfigFile2: $ConfigFile"
Write-Host "DEBUG Info - Read-ConfigFile2: Exiting, because of this Issue."
Write-Host $Error
EXIT
} #end catch
} #end function