Ini File Handler for VBScript
by dwarfsoft on Feb.27, 2009, under Scripting, Work
I was recently working on an issue to do with managing .ini files in VBScript. I know what you are all going to say now: Why would you use an INI file when the registry is available for use?! Well, there is one instance that you may wish to use another form of configuration or information passing. In this instance we have an initiation of the Ghost Store method for the System Volume. To achieve a store on the system volume we require the PC to be rebooted and it then boots up into a BartPE environment to run the Ghost Store, and perform a few custom tasks. Therefore, the System Volumes Registry is not present (or requires mounting then reading, which has proven somewhat unreliable for me in the past).
So, the reason it came to developing the Ini file handler class is due to the need to provide some more controlled smarts into the store/restore system. Clusters, such as the one I work within, can be more proactive in their maintenance, and therefore require more advanced features than the corporate stock-standard release is likely to contain. As such the area in which I work is constantly involved in working towards a very automated maintenance process. My skills, lying within scripting, programming, and automation in particular, come in handy in this regard. I regularly disassemble the corporate releases to ensure that they will not break when released out into the wild of our corporate machines.
The store/restore process was one that I had previously tackled and modified due to the limitations of the corporate model. Unfortunately this modification was temporary, as the updated software that was released from corporate changed the model under which the store/restore process was to operate, and caused the modifications we had made locally to break.
The easiest way of reading Ini files in Windows is to use the Word.Application Object (as gathered quickly for demonstration from here):
Set objWord = CreateObject("Word.application") WinDir = objWord.System.PrivateProfileString(FileName , Section , Key) |
This, however, does not work in BartPE. Instead, I have developed a class that can be added into a VBScript and used very easily. It utilizes Dictionaries to keep the settings organised. This means that if it reads two settings in the same section with the same name, the value will reflect the last one (the one closest to the end of the file).
The full source of the IniFile handler are as follows:
Class IniFile Private mIniFile ' '----------------------- Sub Load ------------------------------- Public Sub Load(Filename) LoadIni FileName,False End Sub '-------------------- End of Sub Load --------------------------- Public Sub LoadIni(Filename,JustDefaults) Dim objFSO, objDictionary, objSubDictionary, file, ini, arr, line, splitline, tmpsplit Set objFSO = CreateObject("Scripting.FileSystemObject") Set objDictionary = mIniFile Set objDictionary = CreateObject("Scripting.Dictionary") Set objSubDictionary = Nothing Set mIniFile = objDictionary If JustDefaults Then Read = False Else Read = True End If If objFSO.FileExists(Filename) Then Set file = objFSO.OpenTextFile(Filename) ini = file.ReadAll() file.Close arr = Split(ini,vbCrLf) For Each line in arr If line = "##STARTDEFAULT" Then Read = True End If If Read Then If Left(Trim(Line),1) = "[" And Right(Trim(Line),1) = "]" Then line = replace(replace(line,"[",""),"]","") If Not IsEmpty(objDictionary.Item(line)) Then Set objSubDictionary = objDictionary.Item(line) Else Set objSubDictionary = CreateObject("Scripting.Dictionary") 'objDictionary.Add line, objSubDictionary set objDictionary.Item(line) = objSubDictionary End If Else If TypeName(objSubDictionary) = "Nothing" or IsEmpty(objSubDictionary) Then Set objSubDictionary = CreateObject("Scripting.Dictionary") objDictionary.Add "[]",objSubDictionary Set objDictionary.Item("[]") = objSubDictionary End If If Left(Trim(line),1) = "#" Then objSubDictionary.Item( "[" & objSubDictionary.Count & "]") = Trim(line) Else splitline = split(Trim(line),"=") If TypeName(splitline) <> "Nothing" Then If UBound(splitline) = 1 Then tmpsplit = split(splitline(1), "#") ' Resolve a <value>=<blank> error If UBound(tmpsplit) >= 0 Then objSubDictionary.Item(Trim(splitline(0))) = Trim(tmpsplit(0)) Else objSubDictionary.Item(Trim(splitline(0))) = "" End If Else 'Error End If End If End If End If If line = "##ENDDEFAULT" And JustDefaults Then MsgBox "End Default" Read = False Exit Sub End If End If Next Else Exit Sub End If End Sub '------------------- End of Sub LoadIni ------------------------- '----------------------- Function GetValue ------------------------------- Public Function GetValue(Section, Value) Set objDictionary = mIniFile If IsSection(Section) Then Set objSubDictionary = objDictionary.Item(Section) If IsEmpty(objSubDictionary.Item(Value)) Then objSubDictionary.Remove(Value) Else GetValue = objSubDictionary.Item(Value) End If End If End Function '-------------------- End of Function GetValue --------------------------- '----------------------- Function IsSection ------------------------------ Public Function IsSection(Section) Set objDictionary = mIniFile If IsEmpty(objDictionary.Item(Section)) Then objDictionary.Remove(Section) IsSection = False Else IsSection = True End If End Function '-------------------- End of Function IsSection -------------------------- '----------------------- Function IsSection ------------------------------ Public Function Save(FileName) Set objDictionary = mIniFile Set objFSO = CreateObject("Scripting.FileSystemObject") Set Outfile = objFSO.CreateTextFile(FileName) If TypeName(objDictionary) <> "Nothing" Then If Not IsEmpty(objDictionary.Keys) Then For Each Key in objDictionary.Keys If Key = "[]" Then ElseIf Key = "" Then Else Outfile.WriteLine("[" & Key & "]") End If Set objSubDictionary = Nothing If Not IsEmpty(objDictionary.Item(Key)) Then Set objSubDictionary = objDictionary.Item(Key) End If If TypeName(objSubDictionary) <> "Nothing" Then If Not IsEmpty(objSubDictionary.Keys) Then For Each subKey in objSubDictionary.Keys If Left(subKey,1) = "[" Then OutFile.WriteLine(objSubDictionary.Item(subKey)) Else OutFile.WriteLine(subKey & "=" & objSubDictionary.Item(subKey)) End If Next End If End If OutFile.WriteLine Next End If End If End Function '-------------------- End of Function IsSection -------------------------- '--------------------- Function AddNextNumeric --------------------------- Public Function AddNextNumeric(Section,Value) Set objDictionary = mIniFile If IsEmpty(objDictionary.Item(Section)) Then Set objSubDictionary = CreateObject("Scripting.Dictionary") Set objDictionary.Item(Section) = objSubDictionary objSubDictionary.Item("1") = Value AddNextNumeric = 1 Else Set objSubDictionary = objDictionary.Item(Section) Number = 1 Do While IsEmpty(objSubDictionary.Item("" & Number)) Number = Number + 1 Loop objSubDictionary.Item("" & Number) = Value AddNextNumeric = Number End If End Function '------------------ End of Function AddNextNumeric ----------------------- '--------------------------- CONSTRUCTOR --------------------------------- Private Sub Class_Initialize ' Calss Constructor ' Initialization goes here Set mIniFile = Nothing ' MsgBox TypeName(mIniFile) End Sub '------------------------- END CONSTRUCTOR ------------------------------- '---------------------------- DESTRUCTOR --------------------------------- Private Sub Class_Terminate ' Calss Destructor ' Cleanup goes here ' MsgBox TypeName(mIniFile) Set mIniFile = Nothing End Sub '-------------------------- END DESTRUCTOR ------------------------------- End Class |
Usage of the class for reading Ini files is as follows:
set ifile = New IniFile ifile.Load("filename.ini") Variable = ifile.GetValue("Section","Variable") |
There are obviously functions in the class that allow for writing out the Ini File and modifying the values. Feel free to play with the code, but please remember to link back to here. I do love my popularity, so any of you who want to link here, please do so.
Cheers, Chris.
Thanks, Chris. This has saved me a lot of trouble.
I have added a few methods GetSections and GetKeys(Section) that should be self explanatory.
I have also renamed LoadIni to LoadIniOptionalComments and added an additional boolean parameter to control whether Comments are included.
LoadIni now call LoadIniOptionalComments with IncludeComments = True for backward compatibility.
Another new method LoadWithoutComments(Filename) calls LoadIniOptionalComments with IncludeComments = False.
Sample Code to use the new class:
And the modified Class:
Oops
That lost all my Rich Text and Indentation.
If you are interested – I can email the code in more readable format.
Thanks for the updates. I didn’t need to worry too much about the comments, which left me with a code that really only worked for the machine readable part of things.
The formatting should be fine now. The indents were still there, just needed the appropriate pre tags around it all 😉
It’s good to know that people out there are still using this kind of thing years after I first wrote it 😀
Cheers, Chris
[…] under Uncategorized Print This Post As you may know, I posted a while ago about how to handle INI files using VBScript if you can’t use the Word.Application object System.PrivateProfileString […]