PowerShell to Read single value from simple .ini file
Asked Answered
O

6

21

Everything I've found looks way over complex. It's almost like I just need to read a text file.

ADAP.ini contains this, nothing else:

http://xxx.104.xxx.226
APP=2.3.6
DLL=2.3.6

Using Powershell, how can I read what APP=value is? and or what DLL=value is?

I would store the value in a variable and use it later in Powershell script.

Olmstead answered 28/4, 2017 at 23:51 Comment(0)
U
27

This looks like a good use case for ConvertFrom-StringData which by default looks for key value pairs separated by the equals symbol.

Because the first line of your .ini file doesn't have an equals we would need to skip it to avoid an error. This can be done simply with Select -Skip 1.

Here's the code:

$ADAP = Get-Content 'ADAP.ini' | Select -Skip 1 | ConvertFrom-StringData

You can then get the values of APP and DLL by accessing them as named properties of the $ADAP object, as follows:

$ADAP.APP
$ADAP.DLL
Ulent answered 29/4, 2017 at 7:22 Comment(3)
This kind of works, but on Powershell 4, this returns an array of hashtables, per configuration value instead of a single hashtable. EDIT: Figured it out. $configData = Get-Content -Path 'refresh.ini' -Raw | ConvertFrom-StringDataChante
I have seen many solutions for this kind of problem, but no one has put forward a solution this elegant. Thank, thank thank you very much!Lew
With Powershell 5.1 this method is very resilient. Blank lines and comments all seem to be properly ignored. In my experience | Select -Skip 1 is not required. Instead of named properties, you may find you can just reference values by name like this: $ADAP["APP"] or $ADAP['DLL']Toogood
F
18

You can quite easily write a PowerShell function that allows you to read ini files:

function Get-IniFile 
{  
    param(  
        [parameter(Mandatory = $true)] [string] $filePath  
    )  
    
    $anonymous = "NoSection"
  
    $ini = @{}  
    switch -regex -file $filePath  
    {  
        "^\[(.+)\]$" # Section  
        {  
            $section = $matches[1]  
            $ini[$section] = @{}  
            $CommentCount = 0  
        }  

        "^(;.*)$" # Comment  
        {  
            if (!($section))  
            {  
                $section = $anonymous  
                $ini[$section] = @{}  
            }  
            $value = $matches[1]  
            $CommentCount = $CommentCount + 1  
            $name = "Comment" + $CommentCount  
            $ini[$section][$name] = $value  
        }   

        "(.+?)\s*=\s*(.*)" # Key  
        {  
            if (!($section))  
            {  
                $section = $anonymous  
                $ini[$section] = @{}  
            }  
            $name,$value = $matches[1..2]  
            $ini[$section][$name] = $value  
        }  
    }  

    return $ini  
}  

$iniFile = Get-IniFile .\ADAP.ini
$app = $iniFile.NoSection.APP
$dll = $iniFile.NoSection.DLL

For this sample ini file saved as Test.ini:

; last modified 1 April 2001 by John Doe
[owner]
name=John Doe
organization=Acme Widgets Inc.

[database]
; use IP address in case network name resolution is not working
server=192.0.2.62     
port=143
file="payroll.dat"

Doing this:

$testIni = Get-IniFile .\Test.ini

Allows you to retrieve values like this:

$server = $testIni.database.server
$organization = $testIni.owner.organization

That code was inspired by an article available here.

Forrer answered 29/4, 2017 at 16:12 Comment(1)
This one is pretty useful. I have improved it a bit, and published the result here: gist.github.com/beruic/1be71ae570646bca40734280ea357e3c. I also included an INI writer.Bryson
L
6

You do "just need to read a text file" .. and then find which line begins with APP and then extract the value from it.

# read text file                        # find line beginning APP=
$AppLine = Get-Content -Path test.ini | Where-Object { $_ -match 'APP=' }

# split on = symbol and take second item
$AppVersion = $AppLine.Split('=')[1]

And you might benefit from [version]$AppVersion to make it into a proper sortable, comparable version number instead of a string.

And there's plenty of variation of ways you could do the reading and matching and extracting of a value (Get-Content, switch -file, Select-String, ForEach-Object, -match 'APP=(.*)', etc. in various combinations).

But Mark Wragg's answer is nicer, overall.

Lasonyalasorella answered 1/5, 2017 at 2:41 Comment(0)
A
6

A slightly modified version of Mark Wragg's answer, with a simple check to make sure each line is valid before passing it to the cmdlet for processing.

$Config = Get-Content "C:\scripts\config.ini" |
    Where-Object {$_ -match "="} | ConvertFrom-StringData

Just adding it as I landed here myself and ended up using this solution to handle configuration files with multiple categories and comment lines.

Edit:

A few years later, I'm back with a bit more polish as I keep landing back on this page myself when I forget how I used to do this:

$Config = Get-Content $PSScriptRoot\config.txt |
    Where-Object { $_ -Match "=" } |
        ForEach-Object { $_ -Replace "#.*", "" } |
            ForEach-Object { $_ -Replace "\\", "\\" } |
                ConvertFrom-StringData
If ($Config.Target -Eq "Bob") { "The target is Bob." }
    Else { "The target is not Bob." }

config.txt:

# target = fred
target = Bob # this is the real target
you know, joe
Ambulatory answered 3/2, 2020 at 15:5 Comment(1)
Your edit is appreciated -- it shows you're genuinely invested 😇Magnesium
I
2

There are a ton of great answers here! I came here looking for the same answer you were. While looking at the answers, I thought "There should be a super simple way of completing this while looking nice." There for I done a ton of research and believe I have came up with the simplest, cleanest, and easiest to understand.

Setting up

First, we will want to create the INI file and a PowerShell script in a test folder.

SQLConfig.ini

[SQL Info]
SQLHost =SERVER\SQL
SQLDB =Database
SQLUser =User
SQLPass =Password123

Getting the information

Now that we have the INI file, we want to get the information from this file. To achieve this, we will use the Get-Content function.

Get-Content

$SQLFile = Get-Content SQLConfig.ini

Loop through the file

This will not tell the script to read the INI file. Now that we are reading the file, we need to get the contents of that file. To achieve this, we will use a foreach loop.

Foreach loop

foreach($line in $SQLFile) {
     #To be added
}

Setting the variables

Now that we are looping through each line of the INI file, we want to set variables based on the variable in the INI file and set the value. To do this, we will add an IF statement for each variable we want to retrieve.

Using the IF statement, we can say, if that line contains "The INI Variable Name" then Split that line and set the PowerShell Variable to whatever is after the =

Note: If you have a space between the "=" and the value in the INI file, that space will also be in the Powershell variable.

Adding to foreach

foreach($line in $SQLFile) {
    if($line -match "SQLHost"){$SQLHost = $line.Split('=')[1]}
    if($line -match "SQLDB"){$SQLDB = $line.Split('=')[1]}
    if($line -match "SQLUser"){$SQLUser = $line.Split('=')[1]}
    if($line -match "SQLPass"){$SQLPass = $line.Split('=')[1]}
}

Testing

Now that we have it setup, we will test the code to ensure that it works correctly. We will add the following to the end of the script to print out the variable so that we can see if they were set correctly.

Print out variables

$SQLHost
$SQLDB
$SQLUser
$SQLPass

Output

SERVER\SQL
Database
User
Password123

Success!

Whole PowerShell Script

$SQLFile = Get-Content SQLConfig.ini

foreach($line in $SQLFile) {
    if($line -match "SQLHost"){$SQLHost = $line.Split('=')[1]}
    if($line -match "SQLDB"){$SQLDB = $line.Split('=')[1]}
    if($line -match "SQLUser"){$SQLUser = $line.Split('=')[1]}
    if($line -match "SQLPass"){$SQLPass = $line.Split('=')[1]}
}

$SQLHost
$SQLDB
$SQLUser
$SQLPass

Futhermore

I like to have a space on both sides of my "=" sign in the INI file. (In my opinion, it looks cleaner.) I tried to add a space in the split but that just caused it to output nothing. If you know of a way to fix that while still being simple and clean, please feel free to edit or add. Thank you!

Improbable answered 16/8, 2023 at 14:25 Comment(1)
Your approach is straight-forward and very simple, but also quite inflexible. But I'm upvoting for the great tutorial-like format you set this up with, really simple to follow along and understand 👏Magnesium
M
0
$content = Get-Content ADAP.ini

$app = $content[1].Substring($content[1].IndexOf("=") + 1)
$dll = $content[2].Substring($content[2].IndexOf("=") + 1)

You can get the content by calling cmdlet Get-Content and assigning it to variable. By accessing to rows like indexes in arrays you can call methods for working with strings.

note: the code is ugly, I know.

Mousy answered 29/4, 2017 at 0:31 Comment(1)
Be cautious about assuming that the values will be at fixed lines! Rather sls insteadSubequatorial

© 2022 - 2025 — McMap. All rights reserved.