Oakrey.Applications.FileParsing.Ini 1.0.1

dotnet add package Oakrey.Applications.FileParsing.Ini --version 1.0.1
                    
NuGet\Install-Package Oakrey.Applications.FileParsing.Ini -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Oakrey.Applications.FileParsing.Ini" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Oakrey.Applications.FileParsing.Ini" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Oakrey.Applications.FileParsing.Ini" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Oakrey.Applications.FileParsing.Ini --version 1.0.1
                    
#r "nuget: Oakrey.Applications.FileParsing.Ini, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Oakrey.Applications.FileParsing.Ini@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Oakrey.Applications.FileParsing.Ini&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Oakrey.Applications.FileParsing.Ini&version=1.0.1
                    
Install as a Cake Tool

Oakrey.Applications.FileParsing.Ini

A specialized file parsing library for INI configuration files, built on the FileParsing framework. Provides automatic parsing, reactive updates, and seamless integration with file browsing services for managing INI files in .NET applications.

Features

INI File Parsing

  • Automatic Parsing: Parses INI files using Oakrey.Files library
  • Section Support: Handles INI sections, keys, and values
  • Comment Preservation: Supports standard INI file format
  • Error Handling: Built-in error dialogs for parse failures

File Parsing Framework

  • Reactive Updates: Observable pattern for file change notifications
  • Auto-Load Support: Optionally load INI files at application startup
  • File Selection Integration: Automatically reparse when file selection changes
  • Current Instance Access: Always have access to the currently parsed INI file

Settings Integration

  • Persistent Configuration: Settings automatically saved and restored
  • Auto-Load Control: Enable/disable automatic file loading
  • File Browsing: Integrated with FileBrowsing service for file selection

Built on FileParsing

  • Extends FileParsingServiceBase<IniFile>
  • Inherits all file parsing framework features
  • Consistent API with other file parsers

Installation

You can install the package via NuGet Package Manager, Package Manager Console or the .NET CLI.

NuGet Package Manager

  1. Open your project in Visual Studio.
  2. Navigate to Tools > NuGet Package Manager > Manage NuGet Packages for Solution....
  3. Search for Oakrey.Applications.FileParsing.Ini and click Install.

.NET CLI

Run the following command in your terminal:

dotnet add package Oakrey.Applications.FileParsing.Ini

Package Manager Console

Run the following command in your Package Manager Console:

Install-Package Oakrey.Applications.FileParsing.Ini

Prerequisites

This package requires:

  • Oakrey.Applications.FileParsing - Base file parsing framework
  • Oakrey.Files - INI file reading and writing (includes IniReader)

Usage Examples

Basic Dependency Injection Setup

using Microsoft.Extensions.DependencyInjection;
using Oakrey.Applications.FileBrowsing;
using Oakrey.Applications.FileParsing.Ini;
using Oakrey.Applications.UserPrompts.Windows;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Register user prompts (required)
        services.AddUserPromptsService();
        
        // Register file browsing for INI files
        services.AddSingleton<IFileBrowsingServiceSettings, IniFileBrowsingSettings>();
        services.AddSingleton<IFileBrowsingService, FileBrowsingService>();
        
        // Register INI parsing service settings
        services.AddSingleton<ISettingsService<IniServiceSettings>, 
                             SettingsService<IniServiceSettings>>();
        services.AddSingleton<IIniServiceSettings, IniServiceSettings>();
        
        // Register INI parsing service
        services.AddSingleton<IIniService, IniService>();
    }
}

Creating INI File Browsing Settings

using Oakrey.Applications.FileBrowsing;
using Oakrey.Applications.Settings;

public class IniFileBrowsingSettings : FileBrowsingServiceSettingsBase
{
    public IniFileBrowsingSettings(
        ISettingsService<IniFileBrowsingSettings> settingsService)
        : base(settingsService)
    {
    }

    public override string FileExtension => "ini";
    public override string SearchPattern => "*.ini";
}

Using the INI Service

using Oakrey.Applications.FileParsing.Ini;
using Oakrey.Files.Ini;

public class ConfigurationManager
{
    private readonly IIniService _iniService;

    public ConfigurationManager(IIniService iniService)
    {
        _iniService = iniService;
        
        // Subscribe to INI file changes
        _iniService.FileParsed.Subscribe(OnIniFileParsed);
    }

    private void OnIniFileParsed(IniFile? iniFile)
    {
        if (iniFile != null)
        {
            Console.WriteLine($"INI file loaded: {_iniService.FilePath}");
            Console.WriteLine($"Sections: {iniFile.Sections.Count}");
            
            // Process the INI file
            ProcessConfiguration(iniFile);
        }
        else
        {
            Console.WriteLine("No INI file loaded");
        }
    }

    public void ProcessConfiguration(IniFile iniFile)
    {
        // Access INI sections and keys
        foreach (var section in iniFile.Sections)
        {
            Console.WriteLine($"[{section.Key}]");
            
            foreach (var entry in section.Value)
            {
                Console.WriteLine($"  {entry.Key} = {entry.Value}");
            }
        }
    }
}

Reading INI Values

public class ApplicationSettings
{
    private readonly IIniService _iniService;

    public ApplicationSettings(IIniService iniService)
    {
        _iniService = iniService;
    }

    public string? GetValue(string section, string key)
    {
        if (_iniService.Instance == null)
        {
            return null;
        }

        var iniFile = _iniService.Instance;
        
        // Check if section exists
        if (!iniFile.Sections.ContainsKey(section))
        {
            return null;
        }

        // Check if key exists in section
        var sectionData = iniFile.Sections[section];
        if (!sectionData.ContainsKey(key))
        {
            return null;
        }

        return sectionData[key];
    }

    public int GetIntValue(string section, string key, int defaultValue = 0)
    {
        var value = GetValue(section, key);
        
        if (string.IsNullOrEmpty(value))
        {
            return defaultValue;
        }

        return int.TryParse(value, out var result) ? result : defaultValue;
    }

    public bool GetBoolValue(string section, string key, bool defaultValue = false)
    {
        var value = GetValue(section, key);
        
        if (string.IsNullOrEmpty(value))
        {
            return defaultValue;
        }

        return bool.TryParse(value, out var result) ? result : defaultValue;
    }
}

Example: Application Configuration

public class AppConfig
{
    private readonly IIniService _iniService;

    public AppConfig(IIniService iniService)
    {
        _iniService = iniService;
        
        // Subscribe to file changes
        _iniService.FileParsed.Subscribe(OnConfigChanged);
        
        // Load initial configuration
        LoadConfiguration();
    }

    private void OnConfigChanged(IniFile? iniFile)
    {
        LoadConfiguration();
    }

    private void LoadConfiguration()
    {
        if (_iniService.Instance == null)
        {
            return;
        }

        var ini = _iniService.Instance;

        // Read application settings
        if (ini.Sections.ContainsKey("Application"))
        {
            var appSection = ini.Sections["Application"];
            
            if (appSection.ContainsKey("Title"))
            {
                ApplicationTitle = appSection["Title"];
            }
            
            if (appSection.ContainsKey("Version"))
            {
                Version = appSection["Version"];
            }
        }

        // Read database settings
        if (ini.Sections.ContainsKey("Database"))
        {
            var dbSection = ini.Sections["Database"];
            
            if (dbSection.ContainsKey("ConnectionString"))
            {
                ConnectionString = dbSection["ConnectionString"];
            }
            
            if (dbSection.ContainsKey("Timeout"))
            {
                if (int.TryParse(dbSection["Timeout"], out var timeout))
                {
                    DatabaseTimeout = timeout;
                }
            }
        }

        // Read UI settings
        if (ini.Sections.ContainsKey("UI"))
        {
            var uiSection = ini.Sections["UI"];
            
            if (uiSection.ContainsKey("Theme"))
            {
                Theme = uiSection["Theme"];
            }
            
            if (uiSection.ContainsKey("Language"))
            {
                Language = uiSection["Language"];
            }
        }
    }

    public string? ApplicationTitle { get; private set; }
    public string? Version { get; private set; }
    public string? ConnectionString { get; private set; }
    public int DatabaseTimeout { get; private set; } = 30;
    public string? Theme { get; private set; }
    public string? Language { get; private set; }
}

WPF ViewModel Integration

using Oakrey.Applications.FileParsing.Ini;
using System.ComponentModel;
using System.Windows.Input;
using CommunityToolkit.Mvvm.Input;

public class IniEditorViewModel : INotifyPropertyChanged
{
    private readonly IIniService _iniService;
    private IniFile? _currentIniFile;

    public IniEditorViewModel(IIniService iniService)
    {
        _iniService = iniService;
        
        // Subscribe to file changes
        _iniService.FileParsed.Subscribe(OnIniFileParsed);
        
        // Initialize with current file
        _currentIniFile = _iniService.Instance;
        
        LoadFileCommand = new AsyncRelayCommand<string>(LoadFileAsync);
        RefreshCommand = new RelayCommand(Refresh);
    }

    public IniFile? CurrentIniFile
    {
        get => _currentIniFile;
        set
        {
            if (_currentIniFile != value)
            {
                _currentIniFile = value;
                OnPropertyChanged(nameof(CurrentIniFile));
                OnPropertyChanged(nameof(IsFileLoaded));
                OnPropertyChanged(nameof(SectionCount));
            }
        }
    }

    public bool IsFileLoaded => _iniService.IsFilePathCorrect;
    
    public string CurrentFilePath => _iniService.FilePath;
    
    public int SectionCount => CurrentIniFile?.Sections.Count ?? 0;

    public IAsyncRelayCommand<string> LoadFileCommand { get; }
    public ICommand RefreshCommand { get; }

    private void OnIniFileParsed(IniFile? iniFile)
    {
        CurrentIniFile = iniFile;
        OnPropertyChanged(nameof(CurrentFilePath));
    }

    private async Task LoadFileAsync(string? filePath)
    {
        if (!string.IsNullOrEmpty(filePath))
        {
            var fileInfo = new FileInfo(filePath);
            await _iniService.LoadFile(fileInfo);
        }
    }

    private void Refresh()
    {
        CurrentIniFile = _iniService.Instance;
    }

    public event PropertyChangedEventHandler? PropertyChanged;
    
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Manual File Loading

public class IniFileLoader
{
    private readonly IIniService _iniService;

    public IniFileLoader(IIniService iniService)
    {
        _iniService = iniService;
    }

    public async Task<IniFile?> LoadConfigFileAsync(string filePath)
    {
        var fileInfo = new FileInfo(filePath);
        
        if (!fileInfo.Exists)
        {
            Console.WriteLine($"File not found: {filePath}");
            return null;
        }

        // Manually load the file
        var iniFile = await _iniService.LoadFile(fileInfo);
        
        if (iniFile != null)
        {
            Console.WriteLine($"Loaded INI file: {filePath}");
            Console.WriteLine($"Sections: {iniFile.Sections.Count}");
            return iniFile;
        }

        return null;
    }

    public async Task<IniFile?> LoadConfigWithCancellationAsync(
        string filePath, 
        CancellationToken cancellationToken)
    {
        var fileInfo = new FileInfo(filePath);
        
        try
        {
            var iniFile = await _iniService.LoadFile(fileInfo, cancellationToken);
            
            if (iniFile != null && !cancellationToken.IsCancellationRequested)
            {
                return iniFile;
            }
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Load operation cancelled");
        }

        return null;
    }
}

Pre-Loading at Application Startup

using Oakrey.Applications;

public class ApplicationStartup
{
    private readonly IIniService _iniService;

    public ApplicationStartup(IIniService iniService)
    {
        _iniService = iniService;
    }

    public async Task InitializeAsync(CancellationToken cancellationToken)
    {
        // Pre-load INI file if AutoLoad is enabled
        if (_iniService is IPreLoadable preLoadable)
        {
            await preLoadable.Preload(cancellationToken);
            
            if (_iniService.Instance != null)
            {
                Console.WriteLine("INI configuration pre-loaded successfully");
                Console.WriteLine($"File: {_iniService.FilePath}");
            }
        }
    }
}

Example INI File Format

# Application Configuration
[Application]
Title=My Application
Version=1.0.0
Author=Oakrey

# Database Configuration
[Database]
ConnectionString=Server=localhost;Database=mydb;
Timeout=30
MaxConnections=100

# UI Settings
[UI]
Theme=Dark
Language=en-US
StartMaximized=true

# Logging
[Logging]
Level=Information
OutputPath=C:\Logs
EnableFileLogging=true

Complete Application Example

using System.Windows;
using Microsoft.Extensions.DependencyInjection;
using Oakrey.Applications.FileBrowsing;
using Oakrey.Applications.FileParsing.Ini;
using Oakrey.Applications.UserPrompts.Windows;

public partial class App : Application
{
    private IServiceProvider _serviceProvider;

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        var services = new ServiceCollection();
        
        // Register user prompts
        services.AddUserPromptsService();
        
        // Register file browsing for INI files
        services.AddSingleton<ISettingsService<IniFileBrowsingSettings>, 
                             SettingsService<IniFileBrowsingSettings>>();
        services.AddSingleton<IFileBrowsingServiceSettings, IniFileBrowsingSettings>();
        services.AddSingleton<IFileBrowsingService, FileBrowsingService>();
        
        // Register INI parsing service
        services.AddSingleton<ISettingsService<IniServiceSettings>, 
                             SettingsService<IniServiceSettings>>();
        services.AddSingleton<IIniServiceSettings, IniServiceSettings>();
        services.AddSingleton<IIniService, IniService>();
        
        // Register application services
        services.AddTransient<AppConfig>();
        services.AddTransient<MainViewModel>();
        
        _serviceProvider = services.BuildServiceProvider();
        
        // Pre-load INI file
        var iniService = _serviceProvider.GetRequiredService<IIniService>();
        if (iniService is IPreLoadable preLoadable)
        {
            Task.Run(() => preLoadable.Preload(CancellationToken.None)).Wait();
        }
        
        var mainWindow = new MainWindow
        {
            DataContext = _serviceProvider.GetRequiredService<MainViewModel>()
        };
        
        mainWindow.Show();
    }
}

API Reference

IIniService

Extends IFileParsingService<IniFile>:

Property Type Description
Instance IniFile? Currently parsed INI file
FileParsed IObservable<IniFile?> Observable for file parse events
FilePath string Path of the currently selected file
IsFilePathCorrect bool True if file was parsed successfully

IniFile Structure

From Oakrey.Files.Ini:

Property Type Description
Sections Dictionary<string, Dictionary<string, string>> INI sections with key-value pairs

IIniServiceSettings

Extends IAutoLoadServiceSettings:

Property Type Description
AutoLoad bool Enable automatic loading on startup

Features in Detail

Automatic Parsing

  • Uses IniReader.Load() from Oakrey.Files
  • Synchronous parsing (fast for typical INI files)
  • Supports standard INI format with sections, keys, values, and comments

Error Handling

  • File not found errors shown to user
  • Parse errors displayed with user-friendly messages
  • Graceful handling of malformed INI files

Reactive Updates

  • Subscribe to FileParsed observable
  • Get notified when files are parsed or selection changes
  • Always have access to current instance

Integration

  • Works seamlessly with FileBrowsing service
  • Automatic reparsing on file selection change
  • Persistent settings for last selected file

When to Use

Use FileParsing.Ini when:

  • You need to parse and monitor INI configuration files
  • You want automatic reloading when files change
  • You need reactive updates for configuration changes
  • You want persistent file selection across sessions
  • You need integration with file browsing UI

Use Oakrey.Files directly when:

  • You only need one-time INI file reading
  • You don't need change tracking or observables
  • You're working with non-UI scenarios

Requirements

  • .NET 10 or higher
  • Oakrey.Applications.FileParsing
  • Oakrey.Files (includes IniReader)

Project Information

Contributing

Contributions are welcome! Feel free to open issues or submit pull requests to improve the package.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Product Compatible and additional computed target framework versions.
.NET net10.0-windows7.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 82 3/13/2026
1.0.0 83 3/11/2026