見出し画像

【VB.NET】INIファイルから文字列を取得する42歳(´'ω'`)

※投稿時点の年齢

現在、今晩はな時間帯にこれを書いているあらきです。

今回はINIファイルを取り扱う際にまずやるであろう「セクション・キーを指定してその値を取得する」処理を書こうかと思います。
ところがどっこい、そもそも「INIファイルの記述はどんな感じ?」について書かないと行けない気がするんですが後回しにしますorz


主に使う関数:GetPrivateProfileString
参照するAPI:kernel32.dll

■概要
INIファイルから値を取得する際、「WIN32API」の処理を呼び出して値取得を行います。
しかし取得に使う「GetPrivateProfileString」は引数4に値が入ってそこから砂金を取り出すかの如き作業を経て値を取得するようになっています。
※INIファイルがらみは大抵こんな感じ
そこで、たいていの場合は直接APIを呼び出さずに「取得用の関数」を用意して取扱いを簡単にします。

■前提:
OS:Windows 8以降(下記の.NET Frameworkが入ってれば動くはず)
使用する言語:VB.NET
.NET Framework:4.6.2

■APIの定義

'WIN32API:INIファイルから文字列を取得する
'[引数]
'   1:lpApplicationName String          セクション名
'   2:lpKeyName         String          キー名
'   3:lpDefault         String          デフォルト値(取得失敗時に返される値)
'   4:lpReturenString   StringBuilder   バッファ:取得した文字列が格納される ※今回はSystem.Text.StringBuilderにて
'   5:nSize             UInt32          取得したバッファのサイズ
'   6:lpFileName        String          対象のファイル名
'[返値]
'   UInt32  取得した文字列長
Private Declare Function GetPrivateProfileString Lib "kernel32.dll" Alias "GetPrivateProfileStringA" (
        ByVal lpApplicationName As String,
        ByVal lpKeyName As String,
        ByVal lpDefault As String,
        ByVal lpReturenString As System.Text.StringBuilder,
        ByVal nSize As UInt32,
        ByVal lpFileName As String
    ) As UInt32

※コメントに引数・返値を記載します。
まず、WIN32APIの関数を呼び出す定義を記述します。
引数5、返値の数値型が「UInt32」になっているのはそれぞれ「符号無し32ビット整数型」にて取り扱うからです。
※出来た頃はLong型にて記述されていた

ここで通常の関数と違う点として「引数4:lpReturenString」がByValと言いつつ実際はここ(厳密にはこいつのポインタ)に値が格納される点です。
そのため、実際は「戻り値の情報を使ってバッファから取得した文字列を取り出す」ような処理になります。

これではやってられないので値取得用の関数(Functionプロシージャ)を作成し使用しています。

■取得用の関数

'INIファイルから値を取得する
'[引数]
'   1:apathTarget       String  対象ファイルのパス
'   2:astrSection       String  セクション名
'   3:astrKey           String  キー名
'   4:astrDefault       String  デフォルト値(取得失敗時に返される値)
'   5:aintBufferSize    String  バッファサイズ(設定したい場合)
'[返値]
'   String  取得したキー値
Friend Function KeyValueReadString(ByVal apathTarget As String, ByVal astrSection As String, ByVal astrKey As String, Optional ByVal astrDefault As String = "", Optional ByVal aintBufferSize As Integer = 4096) As String

    Dim retOutput As String = astrDefault           '戻値:取得値

    Dim strbGetValue As System.Text.StringBuilder   'INIファイルから取得した値
    Dim intReturn As UInt32                         '関数戻値


    'バッファを指定サイズにて初期化
    strbGetValue = New System.Text.StringBuilder(aintBufferSize)

    Try
        '■API実行はここ!
        intReturn = GetPrivateProfileString(astrSection, astrKey, astrDefault, strbGetValue, strbGetValue.Capacity, apathTarget)

        '実行結果判定
        If intReturn >= 0 Then
            retOutput = strbGetValue.ToString   '値取りだし

        End If

    Catch
        'デフォルト値に設定(取得値の破綻対策)
        retOutput = astrDefault

    End Try

    Return retOutput

End Function

そして定義したAPI関数を使用して値を取得する関数です。
バッファサイズなどの設定は(必要な場合を除き)設定しないようにすべくオプション引数にしています。
また、.NETのクラス「System.Text.StringBuilder」を使用して値を取得し、
返値に「取得された文字列長」が帰ってきますが、クラスを使用する事でそのまま取り出す事が出来ます。

ここで、API関数を実行する前に「バッファ初期化」を行っていますが、バッファとして「少なくとも値が入る分の空白」を作ることで頭から取得した値分の文字列が「書き換わる」点がポイントとなります。
→これが「バッファに格納したキー値を取り出す」理由

■自分はこうしてる
自分の場合、「INIファイル取扱い」をクラスにまとめて各処理を一カ所にまとめる、ファイルのパスを登録した後に存在判定を噛ませて無かったら実行しないようにしています。

■いかがでしたか?(〆の挨拶)
こんな感じで現時点で自分が得られているノウハウをぶっ込みつつ極力「本題に関係無い処理」を入れない形で書いていきたいのでお付き合い頂けると泣いて喜びます。
※関係無い処理:フォームを作成とかリストを作成とか、これやっちゃうとどこが本題か分からなくなるんだよね・・・


この記事が気に入ったらサポートをしてみませんか?