Link to home
Start Free TrialLog in
Avatar of exelna
exelna

asked on

Updating ini text file

I have an INI file for the ERP application Macola Progression that I need to update on everyone's PC's so the INI has another line of settings added that currently doesn't exist.

Each users INI file is different, so I cannot change one and put it on a network share and overwrite what each user has currently. They must be individually edited.

Currently the first 5 rows of that INI file looks like this:
[Windows-Info]
Dos-Spacing=Yes
Duplicate-Tasks=No
Custom-Reports=No
Font-Name=MS Sans Serif


We want to change it to look like this adding the 2nd row in bold:
[Windows-Info]
Check-For-Notes=Yes
Dos-Spacing=Yes
Duplicate-Tasks=No
Custom-Reports=No
Font-Name=MS Sans Serif


I have searched online and found a VBscript but I am having issues getting it working...

I am basically looking for the first line of text: [Windows-Info]
Then replacing it with: [Windows-Info] *carriage return* Check-For-Notes=Yes

I have tried tweaking this a bunch of different ways but I keep getting errors.

Const ForReading = 1
Const ForWriting = 2

Set var1="[Windows-Info]"
Set var2="Check-For-Notes=Yes"
Set var=var1 & VbCr & var2

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\ProgramData\Progression\Settings\MACOLA7.INI", ForReading)

strText = objFile.ReadAll
objFile.Close
strNewText = Replace(strText, var1, var)

Set objFile = objFSO.OpenTextFile("C:\ProgramData\Progression\Settings\MACOLA7.INI", ForWriting)
objFile.WriteLine strNewText
objFile.Close

Open in new window


If anyone has any ideas what I am doing wrong or a simpler way I would appreciate it. Thank you in advance.
Avatar of Darrell Porter
Darrell Porter
Flag of United States of America image

Am just curious, but is there a reason you are not simply replacing the file in situ via the login script as opposed to inserting the line into the existing file?

What errors are you receiving when you run the script?
Also, consider changing

objFile.WriteLine strNewText

to

objFile.Write strNewText
ASKER CERTIFIED SOLUTION
Avatar of ChloesDad
ChloesDad
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of exelna
exelna

ASKER

Walkabouttiger, each users ini file is different depending on personal settings. I would be wiping them out by replacing the file from a common file on a network share.

I will try your other recommendation as well as Chloesdad. Thank you.
Hi!

There are a couple of changes that will help.
:-)

First is that you don't have to "Set" variables, only Objects.

I converted the text string that contains the contents of the file into an array using "Split"
I then stepped through each line and wrote it to the new file
I used an If to test if the line I had just written was the trigger is strVar1
If yes, I then wrote strVar2

During development of this I wiped out the contents of the file a couple of times so I added a re-name of the old file to macola7.old

This meant that the openfile need a "True" at the end to tell it to create a file if it does not exist.

Last, I added a test to see if the INI file already contains strVar2 to avoid the ini file getting bigger and bigger.

Cheers!

TRM



Const ForReading = 1
Const ForWriting = 2

strVar1 = "[Windows-Info]"
strVar2 = "Check-For-Notes=Yes"


Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\ProgramData\Progression\Settings\MACOLA7.INI", ForReading)

strText = objFile.ReadAll
objFile.Close
WScript.Echo InStr(strvar1,strtext)
If InStr(strvar1,strtext)=0 Then

	
	arrLines=Split(strtext,vbCrLf)
	
	objFSO.MoveFile "C:\ProgramData\Progression\Settings\MACOLA7.INI" , "C:\ProgramData\Progression\Settings\MACOLA7.OLD"
	Set objFile = objFSO.OpenTextFile("C:\ProgramData\Progression\Settings\MACOLA7.INI", ForWriting,true)
	
	For Each strline In arrlines
		objFile.WriteLine strline
		If strline = strVar1 Then
			objfile.WriteLine strVar2
		End If	
		
	Next
	objFile.Close
	
End If

Open in new window

Try this:
strVar1 = "Windows-Info"
strVar2 = "Check-For-Notes"
strVar3 = "Yes"
strSettingsFile = "C:\ProgramData\Progression\Settings\MACOLA7.INI"

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell") 

If objFSO.FileExists(strSettingsFile) = True Then
  If ReadIni(strSettingsFile,strVar1,strVar2) = strVar3 Then
    MsgBox "Already Exists"
  Else
    WriteIni strSettingsFile,strVar1,strVar2,strVar3
  End If
End If

'--------------------------------------------------------------------------------------------

Function ReadIni( myFilePath, mySection, myKey )
  ' This function returns a value read from an INI file
  '
  ' Arguments:
  ' myFilePath  [string]  the (path and) file name of the INI file
  ' mySection   [string]  the section in the INI file to be searched
  ' myKey       [string]  the key whose value is to be returned
  '
  ' Returns:
  ' the [string] value for the specified key in the specified section
  '
  ' CAVEAT:     Will return a space if key exists but value is blank
  '
  ' Written by Keith Lacelle
  ' Modified by Denis St-Pierre and Rob van der Woude
  
  Const ForReading   = 1
  Const ForWriting   = 2
  Const ForAppending = 8
  
  Dim intEqualPos
  Dim objFSO, objIniFile
  Dim strFilePath, strKey, strLeftString, strLine, strSection
  
  Set objFSO = CreateObject( "Scripting.FileSystemObject" )
  
  ReadIni     = ""
  strFilePath = Trim( myFilePath )
  strSection  = Trim( mySection )
  strKey      = Trim( myKey )
  
  If objFSO.FileExists( strFilePath ) Then
    Set objIniFile = objFSO.OpenTextFile( strFilePath, ForReading, False )
    Do While objIniFile.AtEndOfStream = False
      strLine = Trim( objIniFile.ReadLine )
      
      ' Check if section is found in the current line
      If LCase( strLine ) = "[" & LCase( strSection ) & "]" Then
        strLine = Trim( objIniFile.ReadLine )
        
        ' Parse lines until the next section is reached
        Do While Left( strLine, 1 ) <> "["
          ' Find position of equal sign in the line
          intEqualPos = InStr( 1, strLine, "=", 1 )
          If intEqualPos > 0 Then
            strLeftString = Trim( Left( strLine, intEqualPos - 1 ) )
            ' Check if item is found in the current line
            If LCase( strLeftString ) = LCase( strKey ) Then
              ReadIni = Trim( Mid( strLine, intEqualPos + 1 ) )
              ' In case the item exists but value is blank
              If ReadIni = "" Then
                ReadIni = " "
              End If
              ' Abort loop when item is found
              Exit Do
            End If
          End If
          
          ' Abort if the end of the INI file is reached
          If objIniFile.AtEndOfStream Then Exit Do
          
          ' Continue with next line
          strLine = Trim( objIniFile.ReadLine )
        Loop
        Exit Do
      End If
    Loop
    objIniFile.Close
  Else
    WScript.Echo strFilePath & " doesn't exists. Exiting..."
    WScript.Quit 1
  End If
End Function

Sub WriteIni( myFilePath, mySection, myKey, myValue )
  ' This subroutine writes a value to an INI file
  '
  ' Arguments:
  ' myFilePath  [string]  the (path and) file name of the INI file
  ' mySection   [string]  the section in the INI file to be searched
  ' myKey       [string]  the key whose value is to be written
  ' myValue     [string]  the value to be written (myKey will be
  '                       deleted if myValue is <DELETE_THIS_VALUE>)
  '
  ' Returns:
  ' N/A
  '
  ' CAVEAT:     WriteIni function needs ReadIni function to run
  '
  ' Written by Keith Lacelle
  ' Modified by Denis St-Pierre, Johan Pol and Rob van der Woude
  
  Const ForReading   = 1
  Const ForWriting   = 2
  Const ForAppending = 8
  
  Dim blnInSection, blnKeyExists, blnSectionExists, blnWritten
  Dim intEqualPos
  Dim objFSO, objNewIni, objOrgIni, wshShell
  Dim strFilePath, strFolderPath, strKey, strLeftString
  Dim strLine, strSection, strTempDir, strTempFile, strValue
  
  strFilePath = Trim( myFilePath )
  strSection  = Trim( mySection )
  strKey      = Trim( myKey )
  strValue    = Trim( myValue )
  
  Set objFSO   = CreateObject( "Scripting.FileSystemObject" )
  Set wshShell = CreateObject( "WScript.Shell" )
  
  strTempDir  = wshShell.ExpandEnvironmentStrings( "%TEMP%" )
  strTempFile = objFSO.BuildPath( strTempDir, objFSO.GetTempName )
  
  Set objOrgIni = objFSO.OpenTextFile( strFilePath, ForReading, True )
  Set objNewIni = objFSO.CreateTextFile( strTempFile, False, False )
  
  blnInSection     = False
  blnSectionExists = False
  ' Check if the specified key already exists
  blnKeyExists     = ( ReadIni( strFilePath, strSection, strKey ) <> "" )
  blnWritten       = False
  
  ' Check if path to INI file exists, quit if not
  strFolderPath = Mid( strFilePath, 1, InStrRev( strFilePath, "\" ) )
  If Not objFSO.FolderExists ( strFolderPath ) Then
    WScript.Echo "Error: WriteIni failed, folder path (" _
    & strFolderPath & ") to ini file " _
    & strFilePath & " not found!"
    Set objOrgIni = Nothing
    Set objNewIni = Nothing
    Set objFSO    = Nothing
    WScript.Quit 1
  End If
  
  While objOrgIni.AtEndOfStream = False
    strLine = Trim( objOrgIni.ReadLine )
    If blnWritten = False Then
      If LCase( strLine ) = "[" & LCase( strSection ) & "]" Then
        blnSectionExists = True
        blnInSection = True
      ElseIf InStr( strLine, "[" ) = 1 Then
        blnInSection = False
      End If
    End If
    
    If blnInSection Then
      If blnKeyExists Then
        intEqualPos = InStr( 1, strLine, "=", vbTextCompare )
        If intEqualPos > 0 Then
          strLeftString = Trim( Left( strLine, intEqualPos - 1 ) )
          If LCase( strLeftString ) = LCase( strKey ) Then
            ' Only write the key if the value isn't empty
            ' Modification by Johan Pol
            If strValue <> "<DELETE_THIS_VALUE>" Then
              objNewIni.WriteLine strKey & "=" & strValue
            End If
            blnWritten   = True
            blnInSection = False
          End If
        End If
        If Not blnWritten Then
          objNewIni.WriteLine strLine
        End If
      Else
        objNewIni.WriteLine strLine
        ' Only write the key if the value isn't empty
        ' Modification by Johan Pol
        If strValue <> "<DELETE_THIS_VALUE>" Then
          objNewIni.WriteLine strKey & "=" & strValue
        End If
        blnWritten   = True
        blnInSection = False
      End If
    Else
      objNewIni.WriteLine strLine
    End If
  Wend
  
  If blnSectionExists = False Then ' section doesn't exist
    objNewIni.WriteLine
    objNewIni.WriteLine "[" & strSection & "]"
    ' Only write the key if the value isn't empty
    ' Modification by Johan Pol
    If strValue <> "<DELETE_THIS_VALUE>" Then
      objNewIni.WriteLine strKey & "=" & strValue
    End If
  End If
  
  objOrgIni.Close
  objNewIni.Close
  
  ' Delete old INI file
  objFSO.DeleteFile strFilePath, True
  ' Rename new INI file
  objFSO.MoveFile strTempFile, strFilePath
  
  Set objOrgIni = Nothing
  Set objNewIni = Nothing
  Set objFSO    = Nothing
  Set wshShell  = Nothing
End Sub

Open in new window


Props to http://www.robvanderwoude.com/vbstech_files_ini.php for the sub/functions.
You can remove the msgbox, just used for testing.

IV
Avatar of exelna

ASKER

That was exactly what i needed, both suggestions. Thank you very much.
I do have a set of VBS routines for reading and updating INI files.  If you don't have a useful solution from the above I can share an approach using them.

Here is an example of that approach:

https://www.experts-exchange.com/questions/26661747/VBScript-to-read-text-file-and-write-to-another.html?anchorAnswerId=34357417#a34357417

~bp