Die Community zu .NET und Classic VB.
Menü

VB 5/6-Tipp 0108: INI-Dateien Werte und Felder, erstellen und lesen

 von 

Beschreibung 

Optionen eines Programms können zum Beispiel in der Registry gespeichert und beim nächsten Start wieder ausgelesen werden. Um diese eh schon recht überladene Datenbank etwas zu schonen, sollte man die zu sichernden Werte in einer 'Konfigurationsdatei', sprich INI Datei abgelegen. Die Windos-API bietet dafür einige recht komfortable Funktionen, die das Abspeichern und natürlich auch das Laden sowie das Löschen von Schlüsseln und Feldern ermöglichen.

Schwierigkeitsgrad:

Schwierigkeitsgrad 2

Verwendete API-Aufrufe:

GetPrivateProfileSectionA (GetPrivateProfileSection), GetPrivateProfileStringA (GetPrivateProfileString), WritePrivateProfileSectionA (WritePrivateProfileSection), WritePrivateProfileStringA (WritePrivateProfileString)

Download:

Download des Beispielprojektes [3,27 KB]

'Dieser Quellcode stammt von http://www.activevb.de
'und kann frei verwendet werden. Für eventuelle Schäden
'wird nicht gehaftet.

'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
'Ansonsten viel Spaß und Erfolg mit diesem Source!

'------------- Anfang Projektdatei Project1.vbp -------------
'--------- Anfang Formular "Form1" alias Form1.frm  ---------
' Steuerelement: Rahmensteuerelement "Frame1"
' Steuerelement: Schaltfläche "Command4" auf Frame1
' Steuerelement: Schaltfläche "Command3" auf Frame1
' Steuerelement: Textfeld "Text8" auf Frame1
' Steuerelement: Textfeld "Text7" auf Frame1
' Steuerelement: Schaltfläche "Command1" auf Frame1
' Steuerelement: Textfeld "Text1" auf Frame1
' Steuerelement: Textfeld "Text2" auf Frame1
' Steuerelement: Schaltfläche "Command2" auf Frame1
' Steuerelement: Textfeld "Text3" auf Frame1
' Steuerelement: Textfeld "Text4" auf Frame1
' Steuerelement: Textfeld "Text5" auf Frame1
' Steuerelement: Textfeld "Text6" auf Frame1
' Steuerelement: Listen-Steuerelement "List1" auf Frame1
' Steuerelement: Listen-Steuerelement "List2" auf Frame1
' Steuerelement: Beschriftungsfeld "Label3" auf Frame1
' Steuerelement: Beschriftungsfeld "Label4" auf Frame1
' Steuerelement: Beschriftungsfeld "Label5" auf Frame1

Option Explicit

Private Declare Function WritePrivateProfileString Lib _
        "kernel32" Alias "WritePrivateProfileStringA" _
        (ByVal lpApplicationName As String, ByVal _
        lpKeyName As Any, ByVal lpString As Any, ByVal _
        lpFileName As String) As Long
        
Private Declare Function GetPrivateProfileString Lib _
        "kernel32" Alias "GetPrivateProfileStringA" _
        (ByVal lpApplicationName As String, ByVal _
        lpKeyName As Any, ByVal lpDefault As String, _
        ByVal lpReturnedString As String, ByVal nSize _
        As Long, ByVal lpFileName As String) As Long

Private Declare Function WritePrivateProfileSection Lib _
        "kernel32" Alias "WritePrivateProfileSectionA" _
        (ByVal lpAppName As String, ByVal lpString As _
        String, ByVal lpFileName As String) As Long
        
Private Declare Function GetPrivateProfileSection Lib _
        "kernel32" Alias "GetPrivateProfileSectionA" _
        (ByVal lpAppName As String, ByVal lpReturnedString _
        As String, ByVal nSize As Long, ByVal lpFileName _
        As String) As Long
        
Dim File$, Field() As String

Private Sub Form_Load()
  Dim X%
    'Pfad der neuen ini-Datei
    File = App.Path & "\Test.ini"
    Frame1.Caption = File
    
    'Textfelder vordefinieren: Schreiben
    Text1.Text = "Section1"
    Text2.Text = "Key1"
    Text3.Text = "Hallo wie gehts?"
    
    'Textfelder vordefinieren: Lesen
    Text5.Text = "Section1"
    Text6.Text = "Key1"
    Text7.Text = ""
    
    Text8.Text = "Section2"
    
    'Feld zuweisen und ausgeben
    Text4.Text = "Section2"
    ReDim Field(0 To 5)
    Field(0) = "Bananen"
    Field(1) = "Gurken"
    Field(2) = "Erdbeeren"
    Field(3) = "Bohnen"
    Field(4) = "Äpfel"
    Field(5) = "Kartoffeln"
    
    For X = 0 To UBound(Field)
      List1.AddItem Field(X)
    Next X
    
    List2.Clear
End Sub

Private Sub Command1_Click()
  'Wert "Key1" schreiben
  Call INISetValue(File, Text1.Text, Text2.Text, Text3.Text)
  
  'Feld schreiben
  Call INISetArray(File, Text4.Text, Field)
End Sub

Private Sub Command2_Click()
  Dim X%, xArray$()
    'Wert "Key1" lesen
    Text7.Text = INIGetValue(File, Text5.Text, Text6.Text)
    
    'Feld lesen
    ReDim xArray(0)
    Call INIGetArray(File, Text8.Text, xArray)
    
    'Feld ausgeben
    List2.Clear
    If UBound(xArray) > 0 Then
      For X = 0 To UBound(xArray) - 1
        List2.AddItem xArray(X)
      Next X
    End If
End Sub

Private Sub Command3_Click()
  Call INIDeleteKey(File, Text5.Text, Text6.Text)
  Call Command2_Click
End Sub

Private Sub Command4_Click()
  Call INIDeleteSection(File, Text5.Text)
  Call INIDeleteSection(File, Text8.Text)
  Call Command2_Click
End Sub

Private Sub INISetValue(ByVal Path$, ByVal Sect$, ByVal Key$, _
                        ByVal Value$)
  Dim Result&
    'Wert schreiben
    Result = WritePrivateProfileString(Sect, Key, Value, Path)
End Sub

Private Function INIGetValue(ByVal Path$, ByVal Sect$, ByVal Key$) _
                             As String
  Dim Result&, Buffer$
    'Wert lesen
    Buffer = Space$(32)
    Result = GetPrivateProfileString(Sect, Key, vbNullString, _
                                     Buffer, Len(Buffer), Path)
    INIGetValue = Left$(Buffer, Result)
End Function

Private Function INISetArray(ByVal Path$, ByVal Sect$, xArray() _
                             As String)
  Dim X%, Buffer$, Result&
    'Feld in einen String mit Trennzeichen Chr$(0) umwandeln
    For X = LBound(xArray) To UBound(xArray)
      Buffer = Buffer & xArray(X) & Chr$(0)
    Next X
    
    'String schreiben
    Buffer = Left$(Buffer, Len(Buffer) - 1)
    Result = WritePrivateProfileSection(Sect, Buffer, Path)
End Function

Private Sub INIGetArray(ByVal Path$, ByVal Sect$, xArray() As String)
  Dim Result&, Buffer$
  Dim l%, p%, z%
    'String lesen
    Buffer = Space(32767)
    Result = GetPrivateProfileSection(Sect, Buffer, Len(Buffer), Path)
    
    Buffer = Left$(Buffer, Result)
    
    If Buffer <> "" Then
      'String mit Trennzeichen Chr$(0) in ein Feld umwandeln
      l = 1
      ReDim xArray(0)
      Do While l < Result
        p = InStr(l, Buffer, Chr$(0))
        If p = 0 Then Exit Do
        
        xArray(z) = Mid$(Buffer, l, p - l)
        z = z + 1
        ReDim Preserve xArray(0 To z)
        l = p + 1
      Loop
    End If
End Sub

Private Sub INIDeleteKey(ByVal Path$, ByVal Sect$, ByVal Key$)
  Call WritePrivateProfileString(Sect, Key, 0&, Path)
End Sub
 
Private Sub INIDeleteSection(ByVal Path$, ByVal Sect$)
  Call WritePrivateProfileString(Sect, 0&, 0&, Path)
End Sub
'---------- Ende Formular "Form1" alias Form1.frm  ----------
'-------------- Ende Projektdatei Project1.vbp --------------

Tipp-Kompatibilität:

Windows/VB-VersionWin32sWin95Win98WinMEWinNT4Win2000WinXP
VB4
VB5
VB6

Hat dieser Tipp auf Ihrem Betriebsystem und mit Ihrer VB-Version funktioniert?

Ja, funktioniert!

Nein, funktioniert nicht bei mir!

VB-Version:

Windows-Version:

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.

Measure Row - Asgard 07.08.12 11:20 5 Antworten

Archivierte Nutzerkommentare 

Klicken Sie diesen Text an, wenn Sie die 21 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.

Kommentar von Ralf am 04.04.2009 um 22:47

32 als Wert in Space ist zu klein es muss MAX_PATH rein!
Der Tipp sollte dahingehend optimiert werden, weil längere
Werte werden sonst einfach abgeschnitten.

Private Const MAX_PATH&=255

Private Function INIGetValue(ByVal Path$, ByVal Sect$, ByVal Key$) _
As String
Dim Result&, Buffer$
'Wert lesen
Buffer = Space$(MAX_PATH) 'Der Wert 32 ist zu klein
Result = GetPrivateProfileString(Sect, Key, vbNullString, _
Buffer, Len(Buffer), Path)
INIGetValue = Left$(Buffer, Result)
End Function

Kommentar von Robert am 26.02.2009 um 17:11

Wie kann ich das mit einer ProgressBar machen?
Das heißt:
Ich habe ein Programm und während ich in dem Programm arbeite, ändere ich die ProgressBar! Und die letzte Einstellung möchte ich dann speichern, also die, die ich als letztes gemacht habe.
Meinetwegen ist die ProgressBar beim ersten starten auf 2 und beim zweiten Programmstart auf 20. Wie fasse ich das in eine INI-Datei?

Kommentar von Reinhold am 17.04.2008 um 07:13

Hallo, der Tip ist super. Leider habe ich einen etwas Probleme damit. Wenn ich eine Sektion mit einem Unterstrich erstelle, schreibt er diesen in die Ini Datei. Ich kann sie aber nicht mehr lesen.

Beispiel:
[Test_78]

Kann mir hier wer helfen?

Kommentar von Harald am 06.06.2006 um 12:21

@Sven

cmdCall.Text = INIGetValue(file, "Options", "Call" ) ' Soll Wert von Call lesen: Hansi    
frmRegister.Text2.Text = INIGetValue(file, "Options", "Name") ' Soll Wert von Name lesen: Hans Wurst
Version = INIGetValue(file, "Options","Version") ' Soll Wert von Version auslesen: V 1.01
cmdCode.Text = INIGetValue(file, "Options", "Code") ' Soll Wert von Code aus lesen: 123456789

Kommentar von Sven am 04.06.2006 um 17:09

Hallo,

ich wollte auch eine INI-Datei auslesen, die ich vorher angelegt hatte.

INHALT TEST.INI:

[Options]
Call=Hansi
Name=Hans Wurst
Version=V 1.01
Code=123546789
[Land]
Afrika
Amerika
Australien
Asien

Das Programm gibt mir aber nur das Call und die Länder aus.
Den Rest in Options ignoriert es einfach.
Bin ich zu doof oder habe ich da was übersehen?

Der Code dafür lautet bei mir:

Private Sub Form_Load()

Dim OptiKey$
OptiKey$ = ""

Dim file
'Pfad der neuen ini-Datei
file = App.Path & "\CQ.ini"

Dim X%, xArray$()
'Wert "Options" lesen
OptiKey$ = INIGetValue(file, "Call", cmdCall.Text) ' Soll Wert von Call lesen: Hansi
OptiKey$ = INIGetValue(file, "Name", frmRegister.Text2.Text) ' Soll Wert von Name lesen: Hans Wurst
OptiKey$ = INIGetValue(file, "Version", Version) ' Soll Wert von Version auslesen: V 1.01
OptiKey$ = INIGetValue(file, "Code", cmdCode.Text) ' Soll Wert von Code aus lesen: 123456789

'Feld lesen für Länderauswahl
ReDim xArray(0)
Call INIGetArray(file, cmdLand.Text, xArray)

'Feld ausgeben
cmdLand.Clear
If UBound(xArray) > 0 Then
For X = 0 To UBound(xArray) - 1
cmdLand.AddItem xArray(X)
Next X
End If

End Sub

Kommentar von shadowcrow am 17.10.2005 um 11:20

Hallo,
ich möchte ein Programm schreiben, dass eine ini-Datei öffnet und in einer von mir vordefinierten Section bei einem bestimmten Key, den Wert ändert und danach die ini umbenennt.
Kann mir da jemand helfen?
Wäre sehr dankbar.

Kommentar von Jonathan Haas am 14.06.2005 um 20:45

Die Bufferlänge von 32 Zeichen ist spätestens wenn man Pfadangaben oder sonstige lange Strings speichern will, viel zu klein bemessen.

128 sollte es IMHO _mindestens_ sein. Im Zweifelsfalle mehr.

Kommentar von Michael Weiner am 11.11.2003 um 16:40

Hab vorher falschen Code gepostet:

Hier der richtige:

Private Declare Function WritePrivateProfileString Lib _
"kernel32" Alias "WritePrivateProfileStringA" _
(ByVal lpApplicationName As String, ByVal _
lpKeyName As String, ByVal lpString As String, ByVal _
lpFileName As String) As Integer

Kommentar von Michael Weiner am 11.11.2003 um 16:30

Bei VB.NET ist statt Long der Datentyp Integer bei den API-Aufrufen zu verwenden.

Bsp:


Private Declare Function WritePrivateProfileString Lib _
"kernel32" Alias "WritePrivateProfileStringA" _
(ByVal lpApplicationName As String, ByVal _
lpKeyName As Any, ByVal lpString As Any, ByVal _
lpFileName As String) As Long

Kommentar von Sebastian Aspermaier am 09.08.2003 um 16:09

@Matthias Lohr:

Ich habe da eien ActiveX-DLL zu geschrieben "INITools"
Sie wird einfach über die Verweise eingebunden und funktioniert dann so:

Man erstellt einen neuen Objektverweis auf die CReader Klasse. Diese beinhaltet 2 Funktionen zum Lesen und Schreiben.
Zum Lesen einfach die Funktion ReadIniFile mit dem vollständigen Pfad und Dateinamen der gewünschten Ini angeben. Die Funktion liefert eine Auflistung mit allen Tags ([]). On ein Tag ([]) subtags (=) enthält kan man mit IsObject feststellen.

Das Handling ist durch die Auflistung denkbat einfach und reduziert den Code wesentlich. Interesse?

Meld dich mal per Email und dem Betreff INITools, dann weis ich worum es geht.


Sebastian

Kommentar von Holi am 25.06.2003 um 16:33

Achtung die Dateien können nicht grösser als 64k werden!

Kommentar von Matthias Lohr am 06.06.2003 um 12:40

Ist es nicht möglich, ein eigenes Modul zum lesen zu schreiben? Es gibt doch Merkmale wie = oder [ für die einzelnen Sachen

Kommentar von St.Marx am 03.06.2003 um 21:14

Hallo

Ich möchte aus eine ini Datei alle Sektionsbezeichnungen einlesen. Dabei sind die Namen der Sektionen nicht bekannt. Wie komme ich zum erfolg ?

Kommentar von Christoph Ungersböck am 01.08.2002 um 07:20

Hier ist ein Fehler in der Prozedur INIGetArray!!
Wenn das Array während der Schleife so erweitert wird, ist am Ende immer ein Element zu viel im Array!!
Sollte so ausschaun:
z = 0
Do While l

Kommentar von Lestat am 13.07.2002 um 12:35

Läuft bei mir nicht mit einem Novell-Client!!!

Kommentar von Sascha Hierold am 08.04.2002 um 08:30

Wenn ich als Reference in meinem VB 6 Programm die Visual C++ Referencen eingestellt habe funktioniert die hier vorgestellte Methode nicht mehr. Gibt es dafür eine Lösung???

Kommentar von Jürgen Bähr am 23.01.2002 um 11:56

Ich würde gerne einen Text in eine Datei schreiben, ohne jedoch die OPEN ClOSE
Anweisung zu verwenden, da diese erst nachdem der Befehl CLOSE gesetzt wird den Text aus dem Buffer auf die Platte schreibt. Stürtzt das Programm ab, bevor die CLOSE Anweisung kommt, so sind die Daten im Buffer verloren. Mit WriteProfileString funktioniert dass direkte Schreiben zwar, jedoch stehen in der Datei noch weitere Daten die eigentlich nur für eine INI Datei relevant sind. Diese kann ich nicht gebrauchen. Kann mir jemand sagen wie ich nur den eigentlichen Text in die Datei bekomme?
Über eine Antwort wäre ich sehr erfreut.
M.F.G.
Jürgen Bähr

Kommentar von Uwe am 17.12.2001 um 10:19

Wieso macht ihr das nicht mit normalen Dateihandling? Die Such und LöschFunktionen werden natürlich etwas umfangreicher, dafür brauch man sich aber nich mit kernel32 rumschlagen.

Kommentar von tobi am 26.11.2001 um 19:02

Funktioniert das ganze auch unter win xp? Wenn nein was gibt es noch für möglichkeiten außer ner api .ini Dateien auszulesen?

Kommentar von M. Grass am 21.10.2001 um 14:52

Danke,
Tip 108 (ini-Dateien erstellen ) ist super, genau was ich gesucht habe.
Euer ganzes Angebot ist Toll !! Werde euch weiter emfpehlen.
Wie wäre es , wenn ihr alle Tipps (oder 1-100,101-200,etc...) zum Download anbietet ?

Kommentar von wolfgang petzke am 26.06.2001 um 22:57

die Datei, die mit WritePrivateProfileString beschrieben wird,
wird im Speicher gehalten und erst beim Beenden des Programms auf die Platte geschrieben. Wenn man aber die Datei kopieren möchte, nachdem man einige Einträge gemacht hat, müßte man vorher das auf Platte schreiben erzwingen. Wie kann das gemacht werden?