How can I introduce a config file to Powershell scripts?
Asked Answered
H

4

29

Assume that I have a Powershell script called Foo.ps1

I would like to introduce an XML configuration file called Foo.ps1.config

where I can specify my environment settings something like:

<FunctionsDirectory>
     $ScriptDirectory\Functions
</FunctionsDirectory>
<ModulesDirectory>
     $ScriptDirectory\Modules
</ModulesDirectory>

And then I would like to load this configuration in the begining of Foo.ps1 so that I can import my modules and dot notate to the Functions directory.

How can I achieve this in Powershell?

Herbarium answered 4/12, 2012 at 7:41 Comment(3)
I found this on the web, which looks sensible to me: bjd145.org/2008/01/powershell-and-xml-configuration-files.htmlHerbarium
Or this one: rkeithhill.wordpress.com/2006/06/01/…Herbarium
I've used Keith's solution before, works a treat.Perplexed
F
21

Probably an easier solution.... Assuming your configuration file is names "Confix.xml", try this:

PS Testing> [xml]$configFile= get-content .\Config=.xml
PS Testing> $configFile
xml                                  configuration
---                                  -------------
version="1.0"                        configuration

Reading data out of your new variable:

PS Testing> $configFile.configuration.appsettings
#comment                             add
--------                             ---
Vars                                 {add, add}

PS Testing> $configFile.configuration.appsettings.add
key                                  value
---                                  -----
var1                                 variableValue1
var2                                 variableValue2

PS Testing> $configFile.configuration.appsettings.add[0].value
variableValue2

Long story short: Cast your variable as XML, and do a get-content.

In this case, the Config.xml looks like this:

<?xml version="1.0"?>
<configuration>
  <startup>
  </startup>
  <appSettings>
    <!--Vars -->
    <add key="var1" value="variableValue1"/>
    <add key="var2" value="variableValue2"/>
  </appSettings>
</configuration>
Falls answered 1/2, 2014 at 23:58 Comment(2)
Looking at this solution 8 years later. Is it possible in Powershell to access i.e. the value of var1 by key name instead of saying $configFile.configuration.appsettings.add[0].value??Fenwick
@Fenwick you can use (Select-Xml -Xml $configfile -XPath '//add[@key="var1"]').node.value or $configfile.selectnodes('//add[@key="var1"]').valueTrembly
A
20

For an alternative to XML configuration, if you are flexible to use other type of configuration. I suggest using a global PS configuration file and here is how:

Create a Powershell configuration file ( E.g. Config.ps1 ), then put all configuration as global variable and init it as a first step so that configuration values should be available in your script context.

Benefit of this approach is that various type of data structure such as scalar variable, collections and hashes can be used in Config.ps1 PS file and referenced easily in the PS code.

the following is an example in action:

enter image description here

Here is the C:\Config\Config.ps1 file:

$global:config = @{   
    Var1 = "Value1"

    varCollection = @{       
        item0     = "colValue0"
        item1   = "colValue1"
        item2  = "colValue2"
    }       
}

Then load the functions/variables from Config.ps1 file in this module C:\Module\PSModule.psm1, like so:

$scriptFiles = Get-ChildItem "$PSScriptRoot\Config\*.ps1" -Recurse

foreach ($script in $scriptFiles)
{
    try
    {       
        . $script.FullName 
    }
    catch [System.Exception]
    {
        throw
    }
}

Lastly, initialization script contains this one line below: ( C:\Init.ps1 ).

Import-Module $PSScriptRoot\Module\PSModule.psm1 -Force

After running the Init.ps1. global:config variable will be available in your script context. Here is the output:
enter image description here

Annadiana answered 6/4, 2015 at 23:59 Comment(0)
P
11

Based on Keith's solution... Code to load XML:

   $configFile = "c:\Path2Config"
    if(Test-Path $configFile) {
        Try {
            #Load config appsettings
            $global:appSettings = @{}
            $config = [xml](get-content $configFile)
            foreach ($addNode in $config.configuration.appsettings.add) {
                if ($addNode.Value.Contains(‘,’)) {
                    # Array case
                    $value = $addNode.Value.Split(‘,’)
                        for ($i = 0; $i -lt $value.length; $i++) { 
                            $value[$i] = $value[$i].Trim() 
                        }
                }
                else {
                    # Scalar case
                    $value = $addNode.Value
                }
            $global:appSettings[$addNode.Key] = $value
            }
        }
        Catch [system.exception]{
        }
    }

To populate variables from the XML values:

            $variable1 = $appSettings["var1"]
            $variable2 = $appSettings["var2"]

And the associated XML:

<?xml version="1.0"?>
<configuration>
  <startup>
  </startup>
  <appSettings>
<!--Vars -->
    <add key="var1" value="variableValue1"/>
    <add key="var2" value="variableValue2"/>
  </appSettings>
</configuration>
Perplexed answered 4/12, 2012 at 8:46 Comment(0)
G
6

Another solution (similar to @yantaq's) is just have a separate script and load that.

So config.ps1 contains:

$Environment = $Environment.ToUpper()
$GDriveUNC = "\\servername.domain.net\Data"
$BinLocation = "$pwd\bin-$Environment"

Note that in this case $Environment is an argument to the main script, and you can do any manipulation you want.

Then in main script, just run this 'config' script, like so:

. $PSScriptRoot\config.ps1
Guenna answered 11/8, 2020 at 12:33 Comment(3)
I think it is a simple solution and setupAntifebrile
This simple and great. But I'm worried if distributing such a config file with a public script could pose some security concerns, like someone sending a malicious "config" file with script that manipulates the system.Fiann
Your worried that distributing a script with your script increases the risk? The security risk is already there in your main script that someone could change/replace. If this is a legit concern, then you I think you want to go the executable route and not a script.Guenna

© 2022 - 2024 — McMap. All rights reserved.