A Fahad A Fahad - 4 months ago 37
PowerShell Question

how to execute a script which reads an .ini file to execute a command from a text file

Basically I have a script, which is trying to read the content of a configuration file called commands.ini which redirects to a text file which contains a command to execute.

Here is the content of my script .ps1 file:

Param(
[Parameter(Mandatory=$true)][string]$config
)

#Function to read *.ini file and populate an hashtable
Function Get-IniFile ($file) {
$ini = @{}

switch -regex -file $file {
"^\[(.+)\]$" {
$section = $matches[1].Trim()
$ini[$section] = @{}
}
"^\s*([^#].+?)\s*=\s*(.*)" {
$name,$value = $matches[1..2]
# skip comments that start with semicolon:
if (!($name.StartsWith(";"))) {
$ini[$section][$name] = $value.Trim()
}
}
}
return $ini
}

# Getting parameters from *.ini file
$ini = Get-IniFile($config)
$commands_file = $ini['COMMANDS']['commands_file']

# In case any of the files containing the commands: EXIT.
if (Test-Path $commands_file) {
[string[]]$commands = Get-Content $commands_file
} else {
Write-Output "# ERROR: cannot read commands_file. Please check configuration. Exiting..."
Break
}

# This is the command I am trying to run among the various other similar command just to read the ini file
# and execute the command from the text file which is directed to from the ini file
invoke-expression $commands_file[0]


I have also changed around a bit and used invoke-command command, but does not work.

Here the content of commands.ini file:

[COMMANDS]
; this is where the file to the list of commands to execute will be mentioned
;
commands_file = C:\test\Test\find\commands.txt


and the content of the commands.txt file:


'Get-Process | Where-Object { $_.Name -like "a*"}'


but I always get the same error no matter how much changes I make, i am sure something is wrong the way my hash tables are called or something but I can't figure out what exactly is causing this error.

Error displayed in PowerShell:
Error

C : The term 'C' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ C
+ ~
+ CategoryInfo : ObjectNotFound: (C:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException


Please advice guys, thanks in advance.

Will be also much appreciated if some one can explain me the "Getting parameters from *.ini file" part in the script in details, I do have the basic PowerShell Knowledge.

Answer

It's this part which is flawed:

invoke-expression $commands_file[0]

$commands_file at this point contains a string, "C:\test\Test\find\commands.txt", so when it uses [0] to index into that it picks the first character (as strings can be accessed by index). The first character is C so it tries to run Invoke-Expression against that and you get the error message.

It is not sufficient to simply remove the index ([0]), all you'll do is open the text file. To use it as it stands you'd need to run:

Invoke-Expression (Get-Content $commands_file -Raw)

You might simply change $commands_file (in the ini) to a .ps1, then you can call it rather than worrying about Invoke-Expression and Get-Content.

The ini file parser is reasonably simple. It reads the ini file one line at a time and loads the content into a nested hashtable (key-value pair). Every time it encounters a value in square brackets ([something]) it creates a "section" hashtable. Every time it encounters a key and value (this = that) it adds a new entry under the section. You end up with this structure:

@{
    'COMMANDS' = @{
        'commands_file' = 'C:\stuff\working\scratch\commands.txt'
    }
}

ini files aren't the nicest things to work with, very old fashioned these days. Json, CSV and XML formats tend to be less troubled by regular expression based parsing.