diff --git a/Examples/IniConfigDemo.ps1 b/Examples/IniConfigDemo.ps1
new file mode 100644
index 0000000..cf85d79
--- /dev/null
+++ b/Examples/IniConfigDemo.ps1
@@ -0,0 +1,12 @@
+
+# Load the default configuration file in INI format
+$Config = Get-ScriptConfig -Format INI
+
+# Access the configuration settings
+Write-Host "String :" $Config.MyString
+Write-Host "Integer Positive :" $Config.MyIntegerPositive
+Write-Host "Integer Negative :" $Config.MyIntegerNegative
+Write-Host "Boolean True :" $Config.MyBooleanTrue
+Write-Host "Boolean False :" $Config.MyBooleanFalse
+Write-Host "Array :" "@(" (($Config.MyArray | ForEach-Object { '"{0}"' -f $_ }) -join ', ') ")"
+Write-Host "Hashtable :" "@{" (($Config.MyHashtable.GetEnumerator() | ForEach-Object { '{0} = "{1}"' -f $_.Name, $_.Value }) -join '; ') "}"
diff --git a/Examples/IniConfigDemo.ps1.config b/Examples/IniConfigDemo.ps1.config
new file mode 100644
index 0000000..e6d35c4
--- /dev/null
+++ b/Examples/IniConfigDemo.ps1.config
@@ -0,0 +1,9 @@
+MyString=This is a test INI config file!
+MyIntegerPositive=42
+MyIntegerNegative=-153
+MyBooleanTrue=True
+MyBooleanFalse=False
+MyArray[]=Lorem
+MyArray[]=Ipsum
+MyHashtable[Foo]=Bar
+MyHashtable[Hello]=World
diff --git a/Examples/JsonConfigDemo.ps1 b/Examples/JsonConfigDemo.ps1
new file mode 100644
index 0000000..48d12c6
--- /dev/null
+++ b/Examples/JsonConfigDemo.ps1
@@ -0,0 +1,12 @@
+
+# Load the default configuration file in JSON format
+$Config = Get-ScriptConfig -Format JSON
+
+# Access the configuration settings
+Write-Host "String :" $Config.MyString
+Write-Host "Integer Positive :" $Config.MyIntegerPositive
+Write-Host "Integer Negative :" $Config.MyIntegerNegative
+Write-Host "Boolean True :" $Config.MyBooleanTrue
+Write-Host "Boolean False :" $Config.MyBooleanFalse
+Write-Host "Array :" "@(" (($Config.MyArray | ForEach-Object { '"{0}"' -f $_ }) -join ', ') ")"
+Write-Host "Hashtable :" "@{" (($Config.MyHashtable.GetEnumerator() | ForEach-Object { '{0} = "{1}"' -f $_.Name, $_.Value }) -join '; ') "}"
diff --git a/Examples/JsonConfigDemo.ps1.config b/Examples/JsonConfigDemo.ps1.config
new file mode 100644
index 0000000..1853b4f
--- /dev/null
+++ b/Examples/JsonConfigDemo.ps1.config
@@ -0,0 +1,15 @@
+{
+ "MyString": "This is a test JSON config file!",
+ "MyIntegerPositive": 42,
+ "MyIntegerNegative": -153,
+ "MyBooleanTrue": true,
+ "MyBooleanFalse": false,
+ "MyArray": [
+ "Lorem",
+ "Ipsum"
+ ],
+ "MyHashtable": {
+ "Foo": "Bar",
+ "Hello": "World"
+ }
+}
diff --git a/Examples/XmlConfigDemo.ps1 b/Examples/XmlConfigDemo.ps1
new file mode 100644
index 0000000..20429e9
--- /dev/null
+++ b/Examples/XmlConfigDemo.ps1
@@ -0,0 +1,12 @@
+
+# Load the default configuration file in XML format
+$Config = Get-ScriptConfig -Format XML
+
+# Access the configuration settings
+Write-Host "String :" $Config.MyString
+Write-Host "Integer Positive :" $Config.MyIntegerPositive
+Write-Host "Integer Negative :" $Config.MyIntegerNegative
+Write-Host "Boolean True :" $Config.MyBooleanTrue
+Write-Host "Boolean False :" $Config.MyBooleanFalse
+Write-Host "Array :" "@(" (($Config.MyArray | ForEach-Object { '"{0}"' -f $_ }) -join ', ') ")"
+Write-Host "Hashtable :" "@{" (($Config.MyHashtable.GetEnumerator() | ForEach-Object { '{0} = "{1}"' -f $_.Name, $_.Value }) -join '; ') "}"
diff --git a/Examples/XmlConfigDemo.ps1.config b/Examples/XmlConfigDemo.ps1.config
new file mode 100644
index 0000000..bf3720a
--- /dev/null
+++ b/Examples/XmlConfigDemo.ps1.config
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Functions/ConvertFrom-ScriptConfigIni.ps1 b/Functions/ConvertFrom-ScriptConfigIni.ps1
new file mode 100644
index 0000000..64742f2
--- /dev/null
+++ b/Functions/ConvertFrom-ScriptConfigIni.ps1
@@ -0,0 +1,99 @@
+<#
+.SYNOPSIS
+ Convert the INI file content to a hashtable containing the configuration.
+
+.DESCRIPTION
+ Convert the INI file content to a hashtable containing the configuration.
+
+.PARAMETER Content
+ An array of strings with the INI file content. Each array item is a line.
+
+.EXAMPLE
+ C:\> Get-Content -Path 'config.ini' | ConvertFrom-ScriptConfigIni
+ Use the pipeline input to parse the INI file content.
+#>
+
+function ConvertFrom-ScriptConfigIni
+{
+ [CmdletBinding()]
+ param
+ (
+ [Parameter(Position=0,
+ Mandatory=$true,
+ ValueFromPipeline=$true)]
+ [AllowEmptyString()]
+ [String[]] $Content
+ )
+
+ Write-Verbose "Parse script configuration file as INI format ..."
+
+ $Config = @{}
+
+ try
+ {
+ # Iterating each line and parse the setting
+ foreach ($Line in $Content)
+ {
+ switch -Wildcard ($Line)
+ {
+ # Comment
+ ';*' {
+
+ break
+ }
+
+ # Array
+ '*`[`]=*'{
+ $Key = $Line.Split('[]=', 4)[0]
+ $Value = $Line.Split('[]=', 4)[3]
+
+ if ($null -eq $Config[$Key])
+ {
+ $Config[$Key] = @()
+ }
+
+ $Config[$Key] += $Value
+
+ break
+ }
+
+ # Hashtable
+ '*`[*`]=*' {
+ $Key = $Line.Split('[]=', 4)[0]
+ $Hash = $Line.Split('[]=', 4)[1]
+ $Value = $Line.Split('[]=', 4)[3]
+
+ if ($null -eq $Config[$Key])
+ {
+ $Config[$Key] = @{}
+ }
+
+ $Config[$Key][$Hash] = $Value
+
+ break
+ }
+
+ # String, Integer or Boolean
+ '*=*' {
+ $Key = $Line.Split('=', 2)[0]
+ $Value = $Line.Split('=', 2)[1]
+
+ try { $Value = [Int32]::Parse($Value) } catch { }
+
+ if ('True'.Equals($Value)) { $Value = $true }
+ if ('False'.Equals($Value)) { $Value = $false }
+
+ $Config[$Key] = $Value
+
+ break
+ }
+ }
+ }
+
+ Write-Output $Config
+ }
+ catch
+ {
+ throw "The configuration file content was in an invalid format: $_"
+ }
+}
diff --git a/Functions/ConvertFrom-ScriptConfigJson.ps1 b/Functions/ConvertFrom-ScriptConfigJson.ps1
new file mode 100644
index 0000000..2558775
--- /dev/null
+++ b/Functions/ConvertFrom-ScriptConfigJson.ps1
@@ -0,0 +1,70 @@
+<#
+.SYNOPSIS
+ Convert the JSON file content to a hashtable containing the configuration.
+
+.DESCRIPTION
+ Convert the JSON file content to a hashtable containing the configuration.
+
+.PARAMETER Content
+ An array of strings with the JSON file content. Each array item is a line.
+
+.EXAMPLE
+ C:\> Get-Content -Path 'config.json' | ConvertFrom-ScriptConfigJson
+ Use the pipeline input to parse the JSON file content.
+#>
+
+function ConvertFrom-ScriptConfigJson
+{
+ [CmdletBinding()]
+ param
+ (
+ [Parameter(Position=0,
+ Mandatory=$true,
+ ValueFromPipeline=$true)]
+ [AllowEmptyString()]
+ [String[]] $Content
+ )
+
+ Write-Verbose "Parse script configuration file as JSON format ..."
+
+ $Config = @{}
+
+ try
+ {
+ # Join all lines into one string
+ $Content = $Content -join ''
+
+ # Parse the JSON content
+ $JsonContent = $Content | ConvertFrom-Json
+
+ # Extract all propeties from the json content
+ $JsonNodes = $JsonContent | Get-Member -MemberType NoteProperty
+
+ foreach ($JsonNode in $JsonNodes)
+ {
+ $Key = $JsonNode.Name
+ $Value = $JsonContent.$Key
+
+ # Hashtable / Other
+ if ($Value -is [System.Management.Automation.PSCustomObject])
+ {
+ $Config[$Key] = @{}
+
+ foreach ($Property in $Value.PSObject.Properties)
+ {
+ $Config[$Key][$Property.Name] = $Property.Value
+ }
+ }
+ else
+ {
+ $Config[$Key] = $Value
+ }
+ }
+
+ Write-Output $Config
+ }
+ catch
+ {
+ throw "The configuration file content was in an invalid format: $_"
+ }
+}
diff --git a/Functions/ConvertFrom-ScriptConfigXml.ps1 b/Functions/ConvertFrom-ScriptConfigXml.ps1
new file mode 100644
index 0000000..0850cb1
--- /dev/null
+++ b/Functions/ConvertFrom-ScriptConfigXml.ps1
@@ -0,0 +1,85 @@
+<#
+.SYNOPSIS
+ Convert the XML file content to a hashtable containing the configuration.
+
+.DESCRIPTION
+ Convert the XML file content to a hashtable containing the configuration.
+
+.PARAMETER Content
+ An array of strings with the XML file content. Each array item is a line.
+
+.EXAMPLE
+ C:\> Get-Content -Path 'config.xml' | ConvertFrom-ScriptConfigXml
+ Use the pipeline input to parse the XML file content.
+#>
+
+function ConvertFrom-ScriptConfigXml
+{
+ [CmdletBinding()]
+ param
+ (
+ [Parameter(Position=0,
+ Mandatory=$true,
+ ValueFromPipeline=$true)]
+ [AllowEmptyString()]
+ [String[]] $Content
+ )
+
+ Write-Verbose "Parse script configuration file as XML format ..."
+
+ $Config = @{}
+
+ try
+ {
+ # Try to cast the content into an XmlDocument
+ $XmlContent = [Xml] $Content
+
+ # Extract all setting objects
+ $Settings = $XmlContent.Configuration.Settings.Setting
+
+ foreach ($Setting in $Settings)
+ {
+ switch ($Setting.Type)
+ {
+ # String
+ 'string' {
+ $Config[$Setting.Key] = $Setting.Value
+ }
+
+ # Integer
+ 'integer' {
+ $Config[$Setting.Key] = [Int32]::Parse($Setting.Value)
+ }
+
+ # Boolean
+ 'boolean' {
+ $Config[$Setting.Key] = 'True' -eq $Setting.Value
+ }
+
+ # Array
+ 'array' {
+ $Config[$Setting.Key] = @()
+ foreach ($Item in $Setting.Item)
+ {
+ $Config[$Setting.Key] += $Item.Value
+ }
+ }
+
+ # Hashtable
+ 'hashtable' {
+ $Config[$Setting.Key] = @{}
+ foreach ($Item in $Setting.Item)
+ {
+ $Config[$Setting.Key][$Item.Key] = $Item.Value
+ }
+ }
+ }
+ }
+
+ Write-Output $Config
+ }
+ catch
+ {
+ throw "The configuration file content was in an invalid format: $_"
+ }
+}
diff --git a/Functions/Get-ScriptConfig.ps1 b/Functions/Get-ScriptConfig.ps1
new file mode 100644
index 0000000..0a0ae15
--- /dev/null
+++ b/Functions/Get-ScriptConfig.ps1
@@ -0,0 +1,73 @@
+<#
+.SYNOPSIS
+ Load a script configuration from a config file.
+
+.DESCRIPTION
+ Load a script configuration from a config file. By default, the config file
+ next to the script is loaded. So for the script MyScript.ps1, the config
+ file MyScript.ps1.config will be loaded. By default, the script should be
+ in XML format.
+
+.PARAMETER Path
+ You can override the default dynamic config file path with this parameter.
+
+.PARAMETER Format
+ The default format is XML. You can override the format with this parameter.
+
+.EXAMPLE
+ C:\> $Config = Get-ScriptConfig
+ Loads the default XML formatted configuration file.
+
+.EXAMPLE
+ C:\> $Config = Get-ScriptConfig -Path 'C:\MyApp\global.config'
+ Loads a custom configuration file, with default XML format.
+
+.EXAMPLE
+ C:\> $Config = Get-ScriptConfig -Format JSON
+ Loads the default configuration file but in JSON format.
+#>
+
+function Get-ScriptConfig
+{
+ [CmdletBinding()]
+ param
+ (
+ [Parameter(Mandatory=$false)]
+ [ValidateScript({Test-Path -Path $_})]
+ $Path = $Global:MyInvocation.MyCommand.Definition.Trim() + '.config',
+
+ [Parameter(Mandatory=$false)]
+ [ValidateSet('XML', 'JSON', 'INI')]
+ $Format = 'XML'
+ )
+
+ # Only work with absolute path, makes error handling easier
+ $Path = (Resolve-Path -Path $Path).Path
+
+ Write-Verbose "Load script configuration from file $Path ..."
+
+ # Load raw content, parse it later
+ $Content = Get-Content -Path $Path -ErrorAction Stop
+
+ # Use custom functions to parse the files
+ switch ($Format)
+ {
+ 'XML' {
+ $ConfigHashtable = ConvertFrom-ScriptConfigXml -Content $Content
+ }
+
+ 'JSON' {
+ $ConfigHashtable = ConvertFrom-ScriptConfigJson -Content $Content
+ }
+
+ 'INI' {
+ $ConfigHashtable = ConvertFrom-ScriptConfigIni -Content $Content
+ }
+ }
+
+ # Create a config object with a custom type
+ $Config = New-Object -TypeName PSObject -Property $ConfigHashtable
+ $Config.PSTypeNames.Insert(0, 'ScriptConfig.Configuration')
+
+ Write-Output $Config
+}
diff --git a/README.md b/README.md
index fe777cc..a7288a0 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,117 @@
-# ScriptConfig
-PowerShell Module to handle configuration files for PowerShell Controller Scripts.
+[](https://ci.appveyor.com/project/claudiospizzi/scriptconfig/branch/master) [](https://ci.appveyor.com/project/claudiospizzi/scriptconfig/branch/dev)
+
+# ScriptConfig PowerShell Module
+PowerShell Module to handle configuration files for PowerShell controller scripts.
+
+
+## Introduction
+
+With the ScriptConfig module, configuration data can be loaded into a PowerShell script from a file. Thanks to the module, it is no longer necessary to hardcode or paramter-pass the configuration data. Especialy usefull for scripts, which run unattended. The module support `XML`, `JSON` and `INI` formatted config files.
+
+
+## Requirenments
+
+The following minimum requirenments are necessary to use the module:
+
+* Windows PowerShell 3.0
+* Windows Server 2008 R2 / Windows 7
+
+
+## Installation
+
+Install the module automatically from the [PowerShell Gallery](https://www.powershellgallery.com/packages/ScriptConfig):
+
+```powershell
+Install-Module ScriptConfig
+```
+
+To install the module mannually, perform the following steps:
+
+1. Download the latest release ([here](https://github.com/claudiospizzi/ScriptConfig/releases))
+2. Extract the downloaded module into one of the module paths (e.g. `C:\Users\[Usermame]\Documents\WindowsPowerShell\Modules`)
+
+
+## Cmdlets
+
+Currently, the module has just one single cmdlet, to load the configuration file:
+
+| Cmdlet | Description |
+| -------------------- | --------------------------------------------- |
+| `Get-ScriptConfig` | Loads the configuration from a config file. |
+
+
+## Supported Types
+
+The cmdlet supports multiple types. Depending on the used format, the types have to be specified differently inside the config file.
+
+| Type | Description |
+| ----------- | -------------------------------------------------------------------- |
+| String | Default: A settings is stored as a simple string. |
+| Integer | If the setting is an integer, it will be casted this type. |
+| Boolean | If you specify True or False, it will be casted to a boolean type. |
+| Array | An array of strings can be specified. |
+| Hashtable | A dictionary of key-value-pairs is supported too, both setings. |
+
+
+## Supportet Formats
+
+The following formats are suppoted: `XML`, `JSON` and `INI`.
+
+### XML
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### JSON
+
+```json
+{
+ "MyString": "This is a test JSON config file!",
+ "MyIntegerPositive": 42,
+ "MyIntegerNegative": -153,
+ "MyBooleanTrue": true,
+ "MyBooleanFalse": false,
+ "MyArray": [
+ "Lorem",
+ "Ipsum"
+ ],
+ "MyHashtable": {
+ "Foo": "Bar",
+ "Hello": "World"
+ }
+}
+
+```
+
+### INI
+
+```ini
+MyString=This is a test INI config file!
+MyIntegerPositive=42
+MyIntegerNegative=-153
+MyBooleanTrue=True
+MyBooleanFalse=False
+MyArray[]=Lorem
+MyArray[]=Ipsum
+MyHashtable[Foo]=Bar
+MyHashtable[Hello]=World
+```
diff --git a/ScriptConfig.psd1 b/ScriptConfig.psd1
new file mode 100644
index 0000000..64ae0da
Binary files /dev/null and b/ScriptConfig.psd1 differ
diff --git a/ScriptConfig.psm1 b/ScriptConfig.psm1
new file mode 100644
index 0000000..9ac8cd3
--- /dev/null
+++ b/ScriptConfig.psm1
@@ -0,0 +1,6 @@
+
+# Dot source all nested functions (.ps1 files) inside the \Functions folder
+Split-Path -Path $PSCommandPath |
+ Join-Path -ChildPath 'Functions' |
+ Get-ChildItem -Include '*.ps1' -Exclude '*.Tests.*' -Recurse |
+ ForEach-Object { . $_.FullName; }
diff --git a/ScriptConfig.pssproj b/ScriptConfig.pssproj
new file mode 100644
index 0000000..93c4149
--- /dev/null
+++ b/ScriptConfig.pssproj
@@ -0,0 +1,57 @@
+
+
+
+ Debug
+ 2.0
+ {6cafc0c6-a428-4d30-a9f9-700e829fea51}
+ Exe
+ MyApplication
+ MyApplication
+ ScriptConfig
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ScriptConfig.sln b/ScriptConfig.sln
new file mode 100644
index 0000000..84793a0
--- /dev/null
+++ b/ScriptConfig.sln
@@ -0,0 +1,29 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.24720.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{F5034706-568F-408A-B7B3-4D38C6DB8A32}") = "ScriptConfig", "ScriptConfig.pssproj", "{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EFAC8665-F634-4593-8058-38DD51604FC9}"
+ ProjectSection(SolutionItems) = preProject
+ appveyor.yml = appveyor.yml
+ LICENSE = LICENSE
+ README.md = README.md
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Scripts/build.ps1 b/Scripts/build.ps1
new file mode 100644
index 0000000..e924e10
--- /dev/null
+++ b/Scripts/build.ps1
@@ -0,0 +1,22 @@
+
+# Definition for build
+$Module = 'ScriptConfig'
+$Source = "C:\Projects\$Module"
+$Target = "C:\Program Files\WindowsPowerShell\Modules\$Module"
+
+# Create target module folder
+New-Item -Path $Target -ItemType Directory | Out-Null
+
+# Copy all module items
+Copy-Item -Path "$Source\Examples" -Destination $Target -Recurse
+Copy-Item -Path "$Source\Functions" -Destination $Target -Recurse
+Copy-Item -Path "$Source\Tests" -Destination $Target -Recurse
+Copy-Item -Path "$Source\$Module.psd1" -Destination $Target
+Copy-Item -Path "$Source\$Module.psm1" -Destination $Target
+
+# Extract module version
+$ModuleVersion = (Invoke-Expression -Command (Get-Content -Path "$Target\$Module.psd1" -Raw)).ModuleVersion
+
+# Push appveyor artifacts
+Compress-Archive -Path $Target -DestinationPath "$Source\$Module-$ModuleVersion-$env:APPVEYOR_BUILD_VERSION.zip"
+Push-AppveyorArtifact -Path "$Source\$Module-$ModuleVersion-$env:APPVEYOR_BUILD_VERSION.zip" -DeploymentName $Module
diff --git a/Scripts/test.ps1 b/Scripts/test.ps1
new file mode 100644
index 0000000..e1b4382
--- /dev/null
+++ b/Scripts/test.ps1
@@ -0,0 +1,18 @@
+
+# Definition for test
+$Module = 'ScriptConfig'
+$Output = "C:\Projects\$Module\TestsResults.xml"
+$Target = "C:\Program Files\WindowsPowerShell\Modules\$Module"
+
+# Execute tests
+$TestResults = Invoke-Pester -Path $Target -OutputFormat NUnitXml -OutputFile $Output -PassThru
+
+# Upload test result
+$WebClient = New-Object -TypeName 'System.Net.WebClient'
+$WebClient.UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", $Output)
+
+# Throw error if tests are failed
+if ($TestResults.FailedCount -gt 0)
+{
+ throw "$($TestResults.FailedCount) tests failed."
+}
diff --git a/Tests/ConvertFrom-ScriptConfigIni.Tests.ps1 b/Tests/ConvertFrom-ScriptConfigIni.Tests.ps1
new file mode 100644
index 0000000..13a0bd5
--- /dev/null
+++ b/Tests/ConvertFrom-ScriptConfigIni.Tests.ps1
@@ -0,0 +1,87 @@
+
+# Load module
+if ($Env:APPVEYOR -eq 'True')
+{
+ $Global:TestRoot = (Get-Module ScriptConfig -ListAvailable).ModuleBase
+
+ Import-Module ScriptConfig -Force
+}
+else
+{
+ $Global:TestRoot = (Split-Path -Parent $MyInvocation.MyCommand.Path | Join-Path -ChildPath '..' | Resolve-Path).Path
+
+ Import-Module "$Global:TestRoot\ScriptConfig.psd1" -Force
+}
+
+# Execute tests
+InModuleScope ScriptConfig {
+
+ Describe 'ConvertFrom-ScriptConfigIni' {
+
+ $ResultString = 'This is a test INI config file!'
+ $ResultIntegerPositive = 42
+ $ResultIntegerNegative = -153
+ $ResultBooleanTrue = $true
+ $ResultBooleanFalse = $false
+ $ResultArray = @( 'Lorem', 'Ipsum' )
+ $ResultHashtable = @{ Foo = 'Bar'; Hello = 'World' }
+
+ $Content = Get-Content -Path "$Global:TestRoot\Examples\IniConfigDemo.ps1.config"
+
+ It 'should be able to convert the example config file' {
+
+ $Config = ConvertFrom-ScriptConfigIni -Content $Content
+
+ $Config | Should Not BeNullOrEmpty
+ }
+
+ It 'shloud be able to parse a string' {
+
+ $Config = ConvertFrom-ScriptConfigIni -Content $Content
+
+ $Config.MyString | Should Be $ResultString
+ $Config.MyString.GetType() | Should Be ([System.String])
+ }
+
+ It 'shloud be able to parse an integer' {
+
+ $Config = ConvertFrom-ScriptConfigIni -Content $Content
+
+ $Config.MyIntegerPositive | Should Be $ResultIntegerPositive
+ $Config.MyIntegerPositive.GetType() | Should Be ([System.Int32])
+
+ $Config.MyIntegerNegative | Should Be $ResultIntegerNegative
+ $Config.MyIntegerNegative.GetType() | Should Be ([System.Int32])
+ }
+
+ It 'shloud be able to parse an boolean' {
+
+ $Config = ConvertFrom-ScriptConfigIni -Content $Content
+
+ $Config.MyBooleanTrue | Should Be $ResultBooleanTrue
+ $Config.MyBooleanTrue.GetType() | Should Be ([System.Boolean])
+
+ $Config.MyBooleanFalse | Should Be $ResultBooleanFalse
+ $Config.MyBooleanFalse.GetType() | Should Be ([System.Boolean])
+ }
+
+ It 'shloud be able to parse an array' {
+
+ $Config = ConvertFrom-ScriptConfigIni -Content $Content
+
+ $Config.MyArray | Should Not BeNullOrEmpty
+ $Config.MyArray | Should Be $ResultArray
+ $Config.MyArray.GetType() | Should Be ([System.Object[]])
+ }
+
+ It 'shloud be able to parse an hashtable' {
+
+ $Config = ConvertFrom-ScriptConfigIni -Content $Content
+
+ $Config.MyHashtable | Should Not BeNullOrEmpty
+ $Config.MyHashtable.Keys | Should Be $ResultHashtable.Keys
+ $Config.MyHashtable.Values | Should Be $ResultHashtable.Values
+ $Config.MyHashtable.GetType() | Should Be ([System.Collections.Hashtable])
+ }
+ }
+}
diff --git a/Tests/ConvertFrom-ScriptConfigJson.Tests.ps1 b/Tests/ConvertFrom-ScriptConfigJson.Tests.ps1
new file mode 100644
index 0000000..bc0c511
--- /dev/null
+++ b/Tests/ConvertFrom-ScriptConfigJson.Tests.ps1
@@ -0,0 +1,87 @@
+
+# Load module
+if ($Env:APPVEYOR -eq 'True')
+{
+ $Global:TestRoot = (Get-Module ScriptConfig -ListAvailable).ModuleBase
+
+ Import-Module ScriptConfig -Force
+}
+else
+{
+ $Global:TestRoot = (Split-Path -Parent $MyInvocation.MyCommand.Path | Join-Path -ChildPath '..' | Resolve-Path).Path
+
+ Import-Module "$Global:TestRoot\ScriptConfig.psd1" -Force
+}
+
+# Execute tests
+InModuleScope ScriptConfig {
+
+ Describe 'ConvertFrom-ScriptConfigJson' {
+
+ $ResultString = 'This is a test JSON config file!'
+ $ResultIntegerPositive = 42
+ $ResultIntegerNegative = -153
+ $ResultBooleanTrue = $true
+ $ResultBooleanFalse = $false
+ $ResultArray = @( 'Lorem', 'Ipsum' )
+ $ResultHashtable = @{ Foo = 'Bar'; Hello = 'World' }
+
+ $Content = Get-Content -Path "$Global:TestRoot\Examples\JsonConfigDemo.ps1.config"
+
+ It 'should be able to convert the example config file' {
+
+ $Config = ConvertFrom-ScriptConfigJson -Content $Content
+
+ $Config | Should Not BeNullOrEmpty
+ }
+
+ It 'shloud be able to parse a string' {
+
+ $Config = ConvertFrom-ScriptConfigJson -Content $Content
+
+ $Config.MyString | Should Be $ResultString
+ $Config.MyString.GetType() | Should Be ([System.String])
+ }
+
+ It 'shloud be able to parse an integer' {
+
+ $Config = ConvertFrom-ScriptConfigJson -Content $Content
+
+ $Config.MyIntegerPositive | Should Be $ResultIntegerPositive
+ $Config.MyIntegerPositive.GetType() | Should Be ([System.Int32])
+
+ $Config.MyIntegerNegative | Should Be $ResultIntegerNegative
+ $Config.MyIntegerNegative.GetType() | Should Be ([System.Int32])
+ }
+
+ It 'shloud be able to parse an boolean' {
+
+ $Config = ConvertFrom-ScriptConfigJson -Content $Content
+
+ $Config.MyBooleanTrue | Should Be $ResultBooleanTrue
+ $Config.MyBooleanTrue.GetType() | Should Be ([System.Boolean])
+
+ $Config.MyBooleanFalse | Should Be $ResultBooleanFalse
+ $Config.MyBooleanFalse.GetType() | Should Be ([System.Boolean])
+ }
+
+ It 'shloud be able to parse an array' {
+
+ $Config = ConvertFrom-ScriptConfigJson -Content $Content
+
+ $Config.MyArray | Should Not BeNullOrEmpty
+ $Config.MyArray | Should Be $ResultArray
+ $Config.MyArray.GetType() | Should Be ([System.Object[]])
+ }
+
+ It 'shloud be able to parse an hashtable' {
+
+ $Config = ConvertFrom-ScriptConfigJson -Content $Content
+
+ $Config.MyHashtable | Should Not BeNullOrEmpty
+ $Config.MyHashtable.Keys | Should Be $ResultHashtable.Keys
+ $Config.MyHashtable.Values | Should Be $ResultHashtable.Values
+ $Config.MyHashtable.GetType() | Should Be ([System.Collections.Hashtable])
+ }
+ }
+}
diff --git a/Tests/ConvertFrom-ScriptConfigXml.Tests.ps1 b/Tests/ConvertFrom-ScriptConfigXml.Tests.ps1
new file mode 100644
index 0000000..3716426
--- /dev/null
+++ b/Tests/ConvertFrom-ScriptConfigXml.Tests.ps1
@@ -0,0 +1,87 @@
+
+# Load module
+if ($Env:APPVEYOR -eq 'True')
+{
+ $Global:TestRoot = (Get-Module ScriptConfig -ListAvailable).ModuleBase
+
+ Import-Module ScriptConfig -Force
+}
+else
+{
+ $Global:TestRoot = (Split-Path -Parent $MyInvocation.MyCommand.Path | Join-Path -ChildPath '..' | Resolve-Path).Path
+
+ Import-Module "$Global:TestRoot\ScriptConfig.psd1" -Force
+}
+
+# Execute tests
+InModuleScope ScriptConfig {
+
+ Describe 'ConvertFrom-ScriptConfigXml' {
+
+ $ResultString = 'This is a test XML config file!'
+ $ResultIntegerPositive = 42
+ $ResultIntegerNegative = -153
+ $ResultBooleanTrue = $true
+ $ResultBooleanFalse = $false
+ $ResultArray = @( 'Lorem', 'Ipsum' )
+ $ResultHashtable = @{ Foo = 'Bar'; Hello = 'World' }
+
+ $Content = Get-Content -Path "$Global:TestRoot\Examples\XmlConfigDemo.ps1.config"
+
+ It 'should be able to convert the example config file' {
+
+ $Config = ConvertFrom-ScriptConfigXml -Content $Content
+
+ $Config | Should Not BeNullOrEmpty
+ }
+
+ It 'shloud be able to parse a string' {
+
+ $Config = ConvertFrom-ScriptConfigXml -Content $Content
+
+ $Config.MyString | Should Be $ResultString
+ $Config.MyString.GetType() | Should Be ([System.String])
+ }
+
+ It 'shloud be able to parse an integer' {
+
+ $Config = ConvertFrom-ScriptConfigXml -Content $Content
+
+ $Config.MyIntegerPositive | Should Be $ResultIntegerPositive
+ $Config.MyIntegerPositive.GetType() | Should Be ([System.Int32])
+
+ $Config.MyIntegerNegative | Should Be $ResultIntegerNegative
+ $Config.MyIntegerNegative.GetType() | Should Be ([System.Int32])
+ }
+
+ It 'shloud be able to parse an boolean' {
+
+ $Config = ConvertFrom-ScriptConfigXml -Content $Content
+
+ $Config.MyBooleanTrue | Should Be $ResultBooleanTrue
+ $Config.MyBooleanTrue.GetType() | Should Be ([System.Boolean])
+
+ $Config.MyBooleanFalse | Should Be $ResultBooleanFalse
+ $Config.MyBooleanFalse.GetType() | Should Be ([System.Boolean])
+ }
+
+ It 'shloud be able to parse an array' {
+
+ $Config = ConvertFrom-ScriptConfigXml -Content $Content
+
+ $Config.MyArray | Should Not BeNullOrEmpty
+ $Config.MyArray | Should Be $ResultArray
+ $Config.MyArray.GetType() | Should Be ([System.Object[]])
+ }
+
+ It 'shloud be able to parse an hashtable' {
+
+ $Config = ConvertFrom-ScriptConfigXml -Content $Content
+
+ $Config.MyHashtable | Should Not BeNullOrEmpty
+ $Config.MyHashtable.Keys | Should Be $ResultHashtable.Keys
+ $Config.MyHashtable.Values | Should Be $ResultHashtable.Values
+ $Config.MyHashtable.GetType() | Should Be ([System.Collections.Hashtable])
+ }
+ }
+}
diff --git a/Tests/Get-ScriptConfig.Tests.ps1 b/Tests/Get-ScriptConfig.Tests.ps1
new file mode 100644
index 0000000..8a810a7
--- /dev/null
+++ b/Tests/Get-ScriptConfig.Tests.ps1
@@ -0,0 +1,107 @@
+
+# Load module
+if ($Env:APPVEYOR -eq 'True')
+{
+ $Global:TestRoot = (Get-Module ScriptConfig -ListAvailable).ModuleBase
+
+ Import-Module ScriptConfig -Force
+}
+else
+{
+ $Global:TestRoot = (Split-Path -Parent $MyInvocation.MyCommand.Path | Join-Path -ChildPath '..' | Resolve-Path).Path
+
+ Import-Module "$Global:TestRoot\ScriptConfig.psd1" -Force
+}
+
+# Execute tests
+Describe 'Get-ScriptConfig' {
+
+ Context 'Result' {
+
+ $ResultStringIni = 'This is a test INI config file!'
+ $ResultStringJson = 'This is a test JSON config file!'
+ $ResultStringXml = 'This is a test XML config file!'
+ $ResultIntegerPositive = 42
+ $ResultIntegerNegative = -153
+ $ResultBooleanTrue = $true
+ $ResultBooleanFalse = $false
+ $ResultArray = @( 'Lorem', 'Ipsum' )
+ $ResultHashtable = @{ Foo = 'Bar'; Hello = 'World' }
+
+ It 'shloud be able to load a valid INI configuration file' {
+
+ $Config = Get-ScriptConfig -Path "$Global:TestRoot\Examples\IniConfigDemo.ps1.config" -Format INI
+
+ $Config | Should Not BeNullOrEmpty
+
+ $Config.MyString | Should Be $ResultStringIni
+ $Config.MyIntegerPositive | Should Be $ResultIntegerPositive
+ $Config.MyIntegerNegative | Should Be $ResultIntegerNegative
+ $Config.MyBooleanTrue | Should Be $ResultBooleanTrue
+ $Config.MyBooleanFalse | Should Be $ResultBooleanFalse
+ $Config.MyArray | Should Be $ResultArray
+ $Config.MyHashtable.Keys | Should Be $ResultHashtable.Keys
+ $Config.MyHashtable.Values | Should Be $ResultHashtable.Values
+ }
+
+ It 'shloud be able to load a valid JSON configuration file' {
+
+ $Config = Get-ScriptConfig -Path "$Global:TestRoot\Examples\JsonConfigDemo.ps1.config" -Format JSON
+
+ $Config | Should Not BeNullOrEmpty
+
+ $Config.MyString | Should Be $ResultStringJson
+ $Config.MyIntegerPositive | Should Be $ResultIntegerPositive
+ $Config.MyIntegerNegative | Should Be $ResultIntegerNegative
+ $Config.MyBooleanTrue | Should Be $ResultBooleanTrue
+ $Config.MyBooleanFalse | Should Be $ResultBooleanFalse
+ $Config.MyArray | Should Be $ResultArray
+ $Config.MyHashtable.Keys | Should Be $ResultHashtable.Keys
+ $Config.MyHashtable.Values | Should Be $ResultHashtable.Values
+ }
+
+ It 'shloud be able to load a valid XML configuration file' {
+
+ $Config = Get-ScriptConfig -Path "$Global:TestRoot\Examples\XmlConfigDemo.ps1.config" -Format XML
+
+ $Config | Should Not BeNullOrEmpty
+
+ $Config.MyString | Should Be $ResultStringXml
+ $Config.MyIntegerPositive | Should Be $ResultIntegerPositive
+ $Config.MyIntegerNegative | Should Be $ResultIntegerNegative
+ $Config.MyBooleanTrue | Should Be $ResultBooleanTrue
+ $Config.MyBooleanFalse | Should Be $ResultBooleanFalse
+ $Config.MyArray | Should Be $ResultArray
+ $Config.MyHashtable.Keys | Should Be $ResultHashtable.Keys
+ $Config.MyHashtable.Values | Should Be $ResultHashtable.Values
+ }
+ }
+
+ Context 'Format' {
+
+ Mock ConvertFrom-ScriptConfigIni { return @{} } -ModuleName ScriptConfig
+ Mock ConvertFrom-ScriptConfigJson { return @{} } -ModuleName ScriptConfig
+ Mock ConvertFrom-ScriptConfigXml { return @{} } -ModuleName ScriptConfig
+
+ It 'should call the INI function if INI foramt is specified' {
+
+ $Config = Get-ScriptConfig -Path "$Global:TestRoot\Examples\IniConfigDemo.ps1.config" -Format INI
+
+ Assert-MockCalled 'ConvertFrom-ScriptConfigIni' -ModuleName ScriptConfig -Times 1 -Exactly
+ }
+
+ It 'should call the JSON function if JSON foramt is specified' {
+
+ $Config = Get-ScriptConfig -Path "$Global:TestRoot\Examples\JsonConfigDemo.ps1.config" -Format JSON
+
+ Assert-MockCalled 'ConvertFrom-ScriptConfigJson' -ModuleName ScriptConfig -Times 1 -Exactly
+ }
+
+ It 'should call the XML function if XML foramt is specified' {
+
+ $Config = Get-ScriptConfig -Path "$Global:TestRoot\Examples\XmlConfigDemo.ps1.config" -Format XML
+
+ Assert-MockCalled 'ConvertFrom-ScriptConfigXml' -ModuleName ScriptConfig -Times 1 -Exactly
+ }
+ }
+}
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..1022ac5
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,21 @@
+
+# PowerShell 5.0 Image
+os: WMF 5
+
+# Clone Directory
+clone_folder: C:\Projects\ScriptConfig
+
+# Install Pester
+install:
+ - cinst -y pester --version 3.3.14
+
+# Build Number
+version: '{build}'
+
+# Execute build script
+build_script:
+- ps: .\Scripts\build.ps1
+
+# Execute test script
+test_script:
+- ps: .\Scripts\test.ps1