Introducing the IniManager module

Some time ago I wanted to find a DSC resource which would help me in configuring ini files. I did not really find any resource which was dynamic enough for my needs so I ended up writing my own. Since I want my DSC resources to contain as little code as possible I prefer to create cmdlets outside of the resource which I can call from within the resource. In this way I can also use the cmdlets in scripts and the console which is a nice bonus.

I also wanted to be able to use both strings and hash tables as input depending on my needs. In this way I would be able to create very dynamic resources and if I need more static resources I can always create composite resources. I ended up with a module which contains seven cmdlets to create, modify and verify ini files.

The IniManager module contains the following cmdlets:
  • Get-Ini
  • New-Ini
  • Remove-IniKey
  • Rename-IniKey
  • Set-IniFromHash
  • Set-IniKey
  • Test-Ini
Note that comments in ini files are not handled. If you use this module to create or modify an ini file any comments in that file will be removed. The only case in which a comment is kept is if it contains "=" on that row. The functions check for "=" on each row to separate between key and value.

The File.Ini object

For all the cmdlets in this module I created a custom object which has the type name File.Ini. This object type contains one property per section with the same naming convention as in ini files. This means that the property names have brackets around them. The object also contains one property for each key/value pair which does not belong to a section. These properties will not have brackets around them.

The section properties (with brackets) are of the type File.Ini.Config which in turn contains a collection of properties. One property per key/value in that section.

It's probably easier to explain the object with an example. In this example I use Get-Ini to read the content from an ini file and pipe that to Get-Member. The ini file looks like this:
ImportPath=c:\import
ExportPath=c:\export

[logging]
Path=c:\log
LogLevel=Error

[drivers]
wave=mmdrv.dll
timer=timer.drv
Running the command in the console will output an object which looks like this:
PS C:\> Get-Ini -Path C:\temp\myconfig.ini | Get-Member

   TypeName: File.ini

Name        MemberType   Definition                                                   
----        ----------   ----------                                                   
Equals      Method       bool Equals(System.Object obj)                               
GetHashCode Method       int GetHashCode()                                            
GetType     Method       type GetType()                                               
ToString    Method       string ToString()                                            
ExportPath  NoteProperty string ExportPath=c:\export                                  
ImportPath  NoteProperty string ImportPath=c:\import                                  
[drivers]   NoteProperty File.ini.Section [drivers]=@{wave=mmdrv.dll; timer=timer.drv}
[logging]   NoteProperty File.Ini.Config [logging]=@{LogLevel=Error; Path=c:\log}
That's the object we are dealing with. Now, let's look at the cmdlets available in the module.

Get-Ini

When I do this kind of thing I usually start with the basics. This cmdlet reads an ini file from disk and outputs the custom object. Its used by most of the other cmdlets so it makes the basics for the entire module. Here is an example:
Get-Ini -Path "C:\config.ini"

New-Ini

This cmdlet, as the name suggests, creates an ini file on disk. It requires a File.Ini object so the easiest thing to do is to create a File.Ini object first and them pipe that to this cmdlet. One way to do that is to use Get-Ini. You could modify the object before sending it to New-Ini, but in this example I will just create the object from an existing ini file and create it in a new path.
get-ini -Path "C:\config.ini" | new-ini -Path c:\config_new.ini -Encoding UTF8

Set-IniKey

So now we have covered the basics. If we would want to change certain configuration values in an ini file there are several options on how to do that. One easy way is to use Set-IniKey, which is used to change a value in an ini file. In this example we are changing the key "LogLevel" to "Debug". The LogLevel is placed in the Logging section of the ini file so we also have to select the section. As an extra feature we also set the file encoding to UTF8 just for the hell of it.
Set-IniKey -Path "C:\config.ini" -Key LoggingLevel -Value Debug -Section Logging -Encoding UTF8

Remove-IniKey

So we have tried to read an ini file, create a new one and modified a value. Now it's time for removing values in the ini file. This cmdlet works just as easy as the others. You simply use parameters to select the key and optionally you select the file encoding (the file have to be written after all). In this example we will remove a key (or configuration entry) which is called Proxy in the "[system]" section of the ini file. Again, the file encoding can be set as well.
Remove-IniKey -Path "c:\config.ini" -Key [system]Proxy -Encoding ASCII

Rename-IniKey

There are occasions where a key needs to be renamed. One reason to change the name of a key could simply be to add a hash before it so that it becomes a comment and not read by the system. It could also be if a key was misspelled. In this example we will rename a key called "Prixy" to "Proxy" in the "system" section.
Rename-IniKey -Path c:\config.ini -Key Prixy -NewKey Proxy -Section system -Encoding UTF8

Set-IniFromHash

Now we are getting into the interesting parts. What if you know exactly what you need to change in an ini file and you want to change all of it at once? This is the cmdlet you need for that. You simply create a hash table with the configuration you want and pass it in. In this example we will use a hash table to add two key/value pairs, one in a section and one without section. This works really well in DSC resources.
$hash = @{
    'DebugLog'          ='false'
    '[settings]Hostname'='localhost'
}

Set-IniFromHash -Path c:\config.ini -Values $hash -Encoding UTF8

Test-Ini

So now we have all the cmdlets to modify our ini files. What if we want to make sure that an ini file is set up in the correct way? This is the cmdlet for that. Simply pass in a hash table with your configuration and this cmdlet will output True or False. Test-Ini works really well in a DSC configuration as well. This example is uses the same hash table as Set-IniFromHash to check if the ini file has the correct settings.
$hash = @{
    'DebugLog'          ='false'
    '[settings]Hostname'='localhost'
}

Test-Ini -Path "C:\config.ini" -Values $hash

Where to download

This module is available in the PowerShell Gallery and Microsoft Script Center. If you would like to see more examples, report a bug or contribute with more features, you can visit my GitHub repository.

No comments

Post a Comment