Рейтинг@Mail.ru
Программирование

Программирование (16)

Раздел посвящён разработке программ, языкам программирования и инструментам для разработки.

Работа с *.INI файлами в VB.NET

by

Как правило, настраиваемые параметры приложения хранятся во внешних по отношению к программе расположениях. Имеется множество способов вынести настройки программы вне кода самой программы. Распространёнными способами являются: хранение параметров приложения в реестре Windows, в базах данных, в конфигурационных XML файлах, в файлах *.config или *.cfg, в специфических двоичных форматах и, конечно же, в *.ini файлах. Эти файлы мы сейчас и рассмотрим.

1Что такое INI-файлы

Что такое INI-файлы известно, наверное, каждому более-менее опытному пользователю операционной системы Windows. Зачастую файл с расширением *.INI – это самый быстрый и удобный способ вынести настраиваемые параметры приложения вне кода программы. Эти файлы имеют свою, довольно простую, структуру и, как правило, отличаются малыми размерами. Это обычные текстовые файлы, которые открываются даже в «Блокноте».

Вообще, INI-файл может иметь некоторые отступления от общепринятых норм, каждый разработчик определяет структуру и синтаксис файла для себя. Но есть некоторые общепринятые соглашения. Собственно, вот как выглядит структура INI-файла в общем виде:

; комментарий
# комментарий в стиле Unix

[Section1]
; комментарий 
key1=value_1
key2=value_2
  
[Section2]
;другой комментарий
key3=value_3 
;ещё один комментарий
key4=value_4

Видно, что *.INI файл может содержать:

  • комментарии;
  • заголовки разделов (секций);
  • параметры в виде пары «ключ-значение»;
  • пустые строки.

Пример INI-файла:

;;;;;;;;;;;;;;;;;;;;;;;;;;
; Copyright Soltau.ru ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;

[Settings]
height=600
width=800
lang=RU

2Создание разделов и ключей INI-файлас помощью Visual Basic .NET и kernel32.dll

Можно изобретать велосипед и создать свой разборщик и генератор для INI-файлов. Но мы поступим более рационально и приземлённо и воспользуемся готовым решением из самой ОС Windows.

Дело в том, что в поставку любой операционной системы семейства Windows входит динамическая библиотека kernel32.dll. Эта библиотека расположена в системном каталоге Windows/system32. Она имеет множество функций для доступа к API Windows. В том числе и для работы с INI-файлами. Описывать все его возможности нет смысла, т.к. их великое множество (вот, например, описание kernel32 на 500+ страниц). Посмотреть все методы библиотеки можно с помощью наших старых знакомых DllExportViewer или DependencyWalker.

Нас здесь интересуют всего два метода: GetPrivateProfileString() для чтения ключей и разделов INI-файлов и WritePrivateProfileString() для записи.

Напишем класс-обёртку для упрощённого доступа к функциям работы с файлами *.INI, предоставляемым библиотекой kernel32:

Код класса IniFile.vb для работы с INI-файлами (разворачивается)
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Text

Namespace Ini

    Public Class IniFile

#Region "ИМПОРТ DLL"

        ''' <summary>
        ''' Записывает ключ в заданный раздел INI-файла.
        ''' </summary>
        ''' <param name="section">Имя раздела.</param>
        ''' <param name="key">Имя ключа.</param>
        ''' <param name="value">Значение ключа.</param>
        ''' <param name="filePath">Путь к INI-файлу.</param>
        <DllImport("kernel32")>
        Private Shared Function WritePrivateProfileString(ByVal section As String, ByVal key As String, ByVal value As String, ByVal filePath As String) As Long
        End Function

        ''' <summary>
        ''' Считывает ключ заданного раздела INI-файла.
        ''' </summary>
        ''' <param name="section">Имя раздела.</param>
        ''' <param name="key">Имя ключа.</param>
        ''' <param name="[default]"></param>
        ''' <param name="retVal"></param>
        ''' <param name="size"></param>
        ''' <param name="filePath">Путь к INI-файлу.</param>
        ''' <remarks>С помощью конструктора записываем путь до файла и его имя. </remarks>
        <DllImport("kernel32")>
        Private Shared Function GetPrivateProfileString(ByVal section As String, ByVal key As String, ByVal [default] As String, ByVal retVal As StringBuilder, ByVal size As Integer, ByVal filePath As String) As Integer
        End Function

#End Region '/ИМПОРТ DLL

#Region "КОНСТРУКТОР"

        ''' <summary>
        ''' Имя файла.
        ''' </summary>
        Private IniPath As String

        ''' <summary>
        ''' Читаем ini-файл и возвращаем значение указного ключа из заданной секции. 
        ''' </summary>
        ''' <param name="iniPath"></param>
        Public Sub New(ByVal iniPath As String)
            Me.IniPath = New FileInfo(iniPath).FullName.ToString
        End Sub

#End Region '/КОНСТРУКТОР

#Region "МЕТОДЫ РАБОТЫ С INI-ФАЙЛАМИ"

        ''' <summary>
        ''' Проверяет, что заданный ключ существует в INI-файле.
        ''' </summary>
        ''' <param name="section">Имя раздела.</param>
        ''' <param name="key">Имя ключа.</param>
        Public Function KeyExists(ByVal section As String, ByVal key As String) As Boolean
            Return (Me.ReadKey(section, key).Length > 0)
        End Function

        ''' <summary>
        ''' Читает значение заданного ключа в заданном разделе INI-файла.
        ''' </summary>
        ''' <param name="section">Имя раздела.</param>
        ''' <param name="key">Имя ключа.</param>
        Public Function ReadKey(ByVal section As String, ByVal key As String) As String
            Dim retVal As New StringBuilder(&HFF)
            IniFile.GetPrivateProfileString(section, key, "", retVal, &HFF, Me.IniPath)
            Return retVal.ToString()
        End Function

        ''' <summary>
        ''' Создаёт заданный ключ в заданном разделе. Если раздел не существует, он будет создан.
        ''' </summary>
        ''' <param name="section">Имя раздела.</param>
        ''' <param name="key">Имя ключа.</param>
        ''' <param name="value">Значение ключа. Если NULL, то ключ будет удалён. Если String.Empty, то присвоится пустое значение.</param>
        Public Sub WriteKey(ByVal section As String, ByVal key As String, ByVal value As String)
            IniFile.WritePrivateProfileString(section, key, value, Me.IniPath)
        End Sub

        ''' <summary>
        ''' Удаляет заданный ключ из заданного раздела INI-файла.
        ''' </summary>
        ''' <param name="section">Имя раздела.</param>
        ''' <param name="key">Имя ключа.</param>
        Public Sub DeleteKey(ByVal section As String, ByVal key As String)
            Me.WriteKey(section, key, Nothing)
        End Sub

        ''' <summary>
        ''' Удаляет заданный раздел INI-файла.
        ''' </summary>
        ''' <param name="section">Имя раздела.</param>
        Public Sub DeleteSection(ByVal section As String)
            Me.WriteKey(section, Nothing, Nothing)
        End Sub

#End Region '/МЕТОДЫ РАБОТЫ С INI-ФАЙЛАМИ

    End Class  

End Namespace

Использовать класс IniFile можно, например, так:

Dim iniFile as New IniFile("config.ini")
iniFile.WriteKey("SECTION1", "KEY1", "12345")
If iniFile.KeyExists("SECTION1", "KEY1")
    MessageBox.Show("Ключ создан!")
    iniFile.DeleteKey("SECTION1", "KEY1")
    MessageBox.Show("Ключ удалён!")
End If
Подробнее ...

Кодер и декодер кода Хэмминга на VB.NET

by

Коды Хемминга позволяют закодировать исходное сообщение таким образом, чтобы после передачи его по зашумлённым каналам связи (например, по радиоканалу) и искажениям в принятой информации, можно было восстановить исходное сообщение.

Подробнее ...

Можно ли использовать константы условной компиляции в XAML

by

Мы рассматривали такое мощное средство Visual Studio как константы условной компиляции. Это средство позволяет, в зависимости от значения заданной константы, включать и исключать из исполняемого файла те или иные участки кода. А существует ли аналогичная возможность для разметки XAML?

Подробнее ...

Как в Visual Studio создать повторно используемый фрагмент кода (snippet)

by

Рассмотрим процесс создания повторно используемого фрагмента кода (сниппета) в Visual Studio 2017 на примере. Создадим сниппет на языке VB.NET, который объявляет объект типа BackgroundWorker() и создаёт для него методы DoWork(), ProcessChanged() и RunWorkerCompleted().

Подробнее ...

Как посчитать контрольную сумму CRC32, CRC16, CRC8

by

В интернете существует большое количество вариантов расчёта контрольной суммы CRC. Но что же собственно такое контрольная сумма и почему она рассчитывается именно так? Давайте разберёмся. А заодно напишем программу, которая будет рассчитывать CRC с заданными параметрами.

Подробнее ...

Драйвер для работы с LPT портом (интегрированным или в виде платы PCI)

by

Лет 10-15 назад параллельный порт был довольно востребованным интерфейсом для связи между устройствами. Сегодня производители различных устройств отдают предпочтение последовательным интерфейсам. Тем не менее, и сегодня LPT порт всё ещё можно встретить. А некоторые разработчики ещё пишут под него программы (или поддерживают написанные во времена расцвета параллельных интерфейсов). Но в компьютерах сейчас LPT порт – достаточно большая редкость. Существуют, конечно, платы расширения для компьютера, которые реализуют интерфейс LPT. Они в основном представляют собой платы на шине PCI. К сожалению, далеко не весь софт, который был написан для интегрированных в материнскую плату LPT портов, будет работать с LPT-PCI-платами.

Предлагается решение этой проблемы: программный класс, написанный под .NET, и динамическую библиотеку, которая работает с LPT. Данная реализация проверена на 32- и 64-разрядных Windows XP, Windows 7, 8 и 10 как со встроенными LPT портами, так и реализованными в виде плат расширения на шине PCI или PCI-Express. Скачать драйвер для LPT порта можно по ссылке внизу после статьи.

Подробнее ...
Подписаться на этот канал RSS