INI Wert schreiben

Einen Wert in eine INI-Datei schreiben

Dieses Unterfangen stellt sich noch recht einfach dar. Die Funktion WritePrivateProfileString besitzt 4 Argumente:

WritePrivateProfileString
Argument Bedeutung Beispielwerte
lpApplicationName Name der Sektion bzw. des Abschnitts Section 01
lpKeyName Name des Schlüssels Key 01
lpString zu schreibender Wert Testwert
lpFileName Gültiger Pfad zur INI-Datei C:\WINNT\Dummy.ini

Beispiel:

Sub WriteMyINISectionValue()
 
  Dim lRes      As Long
  Dim sINIPath  As String
  Dim sSection  As String
  Dim sKey      As String
  Dim sValue    As String
 
  'Pfad zum Windows-Ordner ermitteln
  sINIPath = API_GetWindowsDir()
  'Backslash prüfen und ggf. hinzufügen
  If Right$(sINIPath, 1) <> "\" Then _
     sINIPath = sINIPath & "\"
  'Unseren INI-Dateinamen anfügen
  sINIPath = sINIPath & "Dummy.ini"
  ' Unseren Schlüssel festlegen
  sSection = "Section 01"
  'Unseren Schlüssel festlegen
  sKey = "Key 01"
  ' Unseren Wert festlegen
  sValue = "Testwert"
 
  ' Jetzt können wir die Funktion aufrufen
  lRes = WritePrivateProfileString(sSection, sKey, sValue, sINIPath)
  ' Erfolgreich?
  If lRes <> 0 Then MsgBox "Alles klar!"
 
End Sub

Und das Ergebnis im Editor:

Eintrag in Dummy.ini

Nach diesem ersten Erfolg erstellen wir für das Schreiben von Schlüsselwerten in INI-Dateien eine Wrapper-Funktion.

Beispiel:

Public Function SaveMySetting(ByVal sIniFilePath As String, _
                              ByVal sSection As String, _
                              ByVal sKey As String, _
                              ByVal sValue As String, _
                              ByRef sError As String) As Boolean
    Dim lResult As Long
    lResult = WritePrivateProfileString(sSection, sKey, sValue, sIniFilePath)
    SaveMySetting = CBool(lResult <> 0 And Err.LastDllError = 0)
    If Not SaveMySetting Then sError = GetDllErrorDescription(Err.LastDllError)
 
End Function

Diese Wrapper-Funktion wurde um die Prüfung des Rückgabewertes erweitert. Dabei wird im Fehlerfall der Wert Err.LastDllError aus dem Error-Objekt abgefragt. Ist dieser <> 0 UND gab die Funktion selbst 0 zurück liegt ein Fehler vor.

Da unsere Wrapper-Funktion SaveMySetting selbst einen Boolean-Wert als Ergebnis zurückgibt, erzeugen wir diesen „typsicher“ über die Konvertierungsfunktion CBool().

Die Funktion ist genau dann erfolgreich (= True), wenn sowohl der API-Funktionsaufruf einen Wert <> 0 zurückgibt UND die VBA-Error-Objekt-Eigenschaft LastDllError keinen Wert (=0) besitzt.

Sollte die VBA-Error-Objekt-Eigenschaft LastDllError jedoch einen Wert (<> 0) beinhalten, haben wir lediglich einen (API)-Fehlercode, der genauso wenig wie VBA-Fehlercodes aussagekräftig ist. Es besteht jedoch die Möglichkeit, vom Betriebssystem den zugehörigen Fehlertext zu ermitteln. Um diesen Fehler also „lesbar“ zu machen, benötigen wir eine weitere API-Funktion:

FormatMessage

Da die Benutzung dieser zusätzlichen API-Funktion nicht gerade simpel ist, habe ich hierfür eine Wrapper-Funktion GetDllErrorDescription erstellt, der man lediglich die API-Fehlernummer übergibt und die entsprechende, lesbare Fehlermeldung zurückerhält. Zunächst muss jedoch auch für diese Funktion eine entsprechende „Deklaration“ erfolgen. Wir müssen also die bisher deklarierten API-Funktionen um folgenden Eintrag erweitern:

Private Declare Function FormatMessage Lib "kernel32" Alias _
                        "FormatMessageA" _
                        (ByVal dwFlags As Long, _
                         lpSource As Any, _
                         ByVal dwMessageId As Long, _
                         ByVal dwLanguageId As Long, _
                         ByVal lpBuffer As String, _
                         ByVal nSize As Long, _
                         Arguments As Long) As Long

Und hier die „Wrapper“-Variante:

Beispiel:

' API-Fehlerbeschreibung
Public Function GetDllErrorDescription(ByVal lErrCode As Long) As String
'// -----------------------------------------------------------------
'// Methode:   | Ermittelt die Beschreibung eines API-Fehlers
'// -----------------------------------------------------------------
'// Parameter: | lErrCode = API-Fehlernummer
'// -----------------------------------------------------------------
'// Rückgabe:  | Beschreibung des API-Fehlers
'// -----------------------------------------------------------------
    Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
    Dim lMsgSize    As Long
    Dim sSysMsg     As String
 
    If lErrCode <> 0 Then
        lMsgSize = 1000
        sSysMsg = Space(lMsgSize)
        lMsgSize = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, _
                                 ByVal 0&, _
                                 lErrCode, _
                                 0, _
                                 sSysMsg, _
                                 lMsgSize, _
                                 ByVal 0&)
        If lMsgSize = 0 Then
              sSysMsg = "System-Fehlercode: " & Str$(lErrCode)
        Else: sSysMsg = Str$(lErrCode) & ": " & Left$(sSysMsg, lMsgSize)
        End If
    Else
        sSysMsg = vbNullString
    End If
    sSysMsg = Trim$(sSysMsg)
    If Right$(sSysMsg, Len(vbCrLf)) = vbCrLf Then
        sSysMsg = Left$(sSysMsg, Len(sSysMsg) - Len(vbCrLf))
    End If
    GetDllErrorDescription = sSysMsg
 
End Function

Das ursprüngliche Beispiel hat sich wie folgt verändert:

Beispiel:

' Wrapper-Funktion
Sub INI_Sample2()
 
    Dim sINIPath    As String
    Dim sError      As String
    Dim lRes        As Long
 
   'Pfad zum Windows-Ordner ermitteln
    sINIPath = API_GetWindowsDir()
   'Backslash prüfen und ggf. hinzufügen
    If Right$(sINIPath, 1) <> "\" Then sINIPath = sINIPath & "\"
   'Unseren INI-Dateinamen anfügen
    sINIPath = sINIPath & "Dummy.ini"
   'Jetzt können wir die Wrapper-Funktion aufrufen
    If SaveMySetting(sINIPath, "Section 01", "Key 01", "Testwert", sError) Then
          MsgBox "Alles klar!"
    Else: MsgBox sError
    End If
 
End Sub