VERSION 2.00 Begin Form Form1 BackColor = &H00C0C0C0& BorderStyle = 1 'Fixed Single Caption = "INIBAK" ClientHeight = 3060 ClientLeft = 510 ClientTop = 1350 ClientWidth = 4935 Height = 3990 Icon = INIBAK.FRX:0000 Left = 450 LinkTopic = "Form1" MaxButton = 0 'False ScaleHeight = 3060 ScaleWidth = 4935 Top = 480 Width = 5055 Begin FileListBox File1 Height = 225 Left = 360 TabIndex = 1 Top = 2280 Visible = 0 'False Width = 1815 End Begin CommonDialog CMDialog1 CancelError = -1 'True DefaultExt = "INI" DialogTitle = "Select INI File" Filter = "INI Files|*.INI" Left = 3960 Top = 1320 End Begin ListBox INIList BackColor = &H00C0C0C0& Height = 1980 HelpContextID = 9 Left = 240 Sorted = -1 'True TabIndex = 0 Top = 840 Width = 4455 End Begin Shape Shape1 BackColor = &H00000000& BorderColor = &H00808080& Height = 2820 Index = 1 Left = 120 Top = 120 Width = 4695 End Begin Shape Shape1 BackColor = &H00000000& BorderColor = &H00FFFFFF& Height = 2820 Index = 0 Left = 135 Top = 135 Width = 4695 End Begin Label Label1 BackColor = &H00C0C0C0& Caption = "Protected INI Files:" FontBold = -1 'True FontItalic = 0 'False FontName = "MS Sans Serif" FontSize = 15 FontStrikethru = 0 'False FontUnderline = 0 'False ForeColor = &H00000000& Height = 375 Left = 240 TabIndex = 2 Top = 240 Width = 4455 End Begin Menu mnu_Main Caption = "&File" HelpContextID = 2 Index = 0 WindowList = -1 'True Begin Menu mnu_File Caption = "&Add INI File to List" HelpContextID = 4 Index = 0 End Begin Menu mnu_File Caption = "&Delete INI File from List" HelpContextID = 5 Index = 1 End Begin Menu mnu_File Caption = "&Restore INI File from Backup" HelpContextID = 6 Index = 2 End Begin Menu mnu_File Caption = "&Check INI Files Now" HelpContextID = 7 Index = 3 End Begin Menu mnu_File Caption = "-" Index = 4 End Begin Menu mnu_File Caption = "E&xit" HelpContextID = 2 Index = 5 End End Begin Menu mnu_Main Caption = "&Levels" HelpContextID = 3 Index = 1 Begin Menu mnu_Level Caption = "&3" HelpContextID = 3 Index = 0 End Begin Menu mnu_Level Caption = "&4" HelpContextID = 3 Index = 1 End Begin Menu mnu_Level Caption = "&5" HelpContextID = 3 Index = 2 End Begin Menu mnu_Level Caption = "&6" HelpContextID = 3 Index = 3 End Begin Menu mnu_Level Caption = "&7" HelpContextID = 3 Index = 4 End Begin Menu mnu_Level Caption = "&8" HelpContextID = 3 Index = 5 End Begin Menu mnu_Level Caption = "&9" HelpContextID = 3 Index = 6 End Begin Menu mnu_Level Caption = "1&0" HelpContextID = 3 Index = 7 End Begin Menu mnu_Level Caption = "1&1" HelpContextID = 3 Index = 8 End Begin Menu mnu_Level Caption = "1&2" HelpContextID = 3 Index = 9 End End Begin Menu mnu_Main Caption = "&Help" HelpContextID = 8 Index = 2 Begin Menu mnu_Help Caption = "&Contents" HelpContextID = 8 Index = 0 End Begin Menu mnu_Help Caption = "&Search for Help On..." HelpContextID = 8 Index = 1 End Begin Menu mnu_Help Caption = "&How to Use Help" HelpContextID = 8 Index = 2 End Begin Menu mnu_Help Caption = "-" Index = 3 End Begin Menu mnu_Help Caption = "&About INIBAK..." HelpContextID = 8 Index = 4 End End End Option Explicit ' INI files don't care about capitalization, so neither does INIBAK. ' The next line causes comparisons to default to Text mode. Option Compare Text Function AddFirstBackup% (ByVal FullPath$) ' Add a new INI file to the list of files protected, and make an ' initial backup copy of that file. Dim Path$, fName$, fExt$ FileSplit FullPath, Path, fName, fExt ' Clear out any leftover backups - these SHOULD not exist File1.Pattern = fName + ".0*" File1.Refresh If File1.ListCount > 0 Then Dim Result%, Msg$, MsgType% Msg = "Old backups of " + fName + ".INI exist. Delete?" MsgType = MB_ICONQUESTION Or MB_YESNOCANCEL Result = MsgBox(Msg, MsgType, MsgTitle) Select Case Result Case IDCANCEL ' Cancel means cancel the whole add file operation AddFirstBackup = False Exit Function Case IDYES ' Yes, delete the old backup files Dim N% For N = 0 To File1.ListCount - 1 KillSafe IniBakDir + File1.List(N) Next N Case IDNO ' No, leave the old files, put new copy in the .000 slot MakeRoom fName End Select End If FileCopy FullPath, IniBakDir + fName + ".000" AddFirstBackup = True End Function Sub FileSplit (ByVal FullPath$, fPath$, fName$, fExt$) ' Given a full pathname in FullPath, e.g. d:\path\filename.ext, ' FileSplit puts path (d:\path) in fPath, name (filename) in fName, ' and extension (ext) in fExt Dim Start%, P, Posn% Start = 1 P = Start Do Until P = 0 P = InStr(Start, FullPath, "\") If P <> 0 Then Posn = P Start = Posn + 1 Loop fPath$ = Left$(FullPath, Posn) fName = Mid$(FullPath, Len(fPath) + 1) Posn = InStr(fName, ".") If Posn = 0 Then fExt = "" Else fExt = Mid$(fName, Posn + 1) fName = Left(fName, Posn - 1) End If End Sub Sub Form_Load () ' Get the Windows directory and backup directory WindowsDir = String$(145, 0) Dim Success% Success = GetWindowsDirectory(WindowsDir, 144) WindowsDir = Left$(WindowsDir, InStr(WindowsDir, Chr$(0)) - 1) ' Allow for possibility that WindowsDir might be a root directory If Right$(WindowsDir, 1) = "\" Then IniBakDir = WindowsDir Else IniBakDir = WindowsDir + "\" End If ' ANSI Character 162 is the cent sign: "INIBAK˘˘.˘˘˘" IniBakDir = IniBakDir + "INIBAK" + String$(2, 162) + "." + String$(3, 162) ' Create the INI backup directory, if it doesn't already exist. On Error Resume Next MkDir IniBakDir On Error GoTo 0 IniBakDir = IniBakDir + "\" ' Get and verify the number of levels NumLevels = GetPrivateProfileInt("Levels", "Levels", 5, "INIBAK.INI") If NumLevels < MinLevels Then NumLevels = MinLevels If NumLevels > MaxLevels Then NumLevels = MaxLevels mnu_Level(NumLevels - MinLevels).Checked = True ' Initialize the common dialog to start in the Windows directory CmDialog1.InitDir = WindowsDir CmDialog1.Flags = OFN_PATHMUSTEXIST Or OFN_NOCHANGEDIR ' Initialize the invisible file list to stay in the backup directory File1.Path = IniBakDir ' Read up to ten INI names from INIBAK.INI Dim N%, OneIni$ For N = 1 To 10 ' GPPS is a "wrapper" for GetPrivateProfileString Success = GPPS("INI Files", "File" + Str$(N), "", OneIni, 144, "INIBAK.INI") If OneIni <> "" Then IniList.AddItem OneIni Next N Form1.Show If GlobalFindAtom(IniBakDir) = 0 Then Dim TheAtom% TheAtom = GlobalAddAtom(IniBakDir) menuCheck End If If IniList.ListCount > 0 Then IniList.ListIndex = 0 End Sub Function GPPS% (ByVal lpAppName$, ByVal lpKeyName$, ByVal lpDefault$, lpRetString$, ByVal nSize%, ByVal lpFileName$) ' A "wrapper" for GetPrivateProfileString. It handles pre-allocating ' the buffer string and chopping off the extra 0 bytes afterward. Use ' *only* for getting one key, NOT for getting all keys in a section. lpRetString = String$(nSize + 1, 0) GPPS = GetPrivateProfileString(lpAppName, lpKeyName, lpDefault, lpRetString, nSize, lpFileName) lpRetString = Left$(lpRetString, InStr(lpRetString, Chr$(0)) - 1) End Function Function IniChanged% (ByVal OrigName$) ' Compare the INI file named in the OrigName parameter with its most ' recent backup. Dim xPath$, xName$, xExt$ FileSplit OrigName, xPath, xName, xExt ' In case the user has deleted one or more of the backup files, the ' TakeUpSlack function renames them in order to *.000, *.001, etc. TakeUpSlack xName ' If the user has *deleted* all backups for this file, *make* a ' backup and get out. Dim BakName$ BakName = xName + ".000" If File1.ListCount = 0 Then Msg = "No backup exists for " + OrigName + ". Creating backup." MsgType = MB_ICONINFORMATION MsgBox Msg, MsgType, MsgTitle FileCopy OrigName, IniBakDir + BakName Exit Function End If ' The Normalize subroutine puts an INI file's lines in order, so it ' can be easily compared with another INI file. Dim NowNorm$, BakNorm$ NowNorm = IniBakDir + "TEMP_NOW.$$$" BakNorm = IniBakDir + "TEMP_BAK.$$$" Normalize OrigName, NowNorm Normalize IniBakDir + BakName, BakNorm Dim FNumNow%, FNumBak% FNumNow = FreeFile Open NowNorm For Input Access Read Shared As FNumNow FNumBak = FreeFile Open BakNorm For Input Access Read Shared As FNumBak Dim nowLine$, bakLine$, NoLine$, Comp% nowLine = "" bakLine = "" NoLine = Chr$(253) ' greater than any possible string in the file. ' The two list boxes in Form2 serve to hold lines that DIFFER between ' the two normalized files. List1 holds files that are in the ' current version but not in the backup (added lines) and List2 holds ' lines that are in the backup but not in the current version ' (deleted lines). If the value of a key is CHANGED, the old line ' appears as deleted and the new line as added. Form2.List1.Clear Form2.List2.Clear Do While (bakLine <> NoLine) Or (nowLine <> NoLine) Comp = StrComp(nowLine, bakLine, 1) Select Case Comp Case Is < 0 ' line in current file is < line in bak file - added Form2.List1.AddItem nowLine ' get another line from current file nowLine = NoLine If Not EOF(FNumNow) Then Line Input #FNumNow, nowLine Case 0 ' get another line from both files nowLine = NoLine If Not EOF(FNumNow) Then Line Input #FNumNow, nowLine bakLine = NoLine If Not EOF(FNumBak) Then Line Input #FNumBak, bakLine Case Is > 0 ' line in current file is > line in bak file - deleted Form2.List2.AddItem bakLine ' get another line from bak file bakLine = NoLine If Not EOF(FNumBak) Then Line Input #FNumBak, bakLine End Select Loop Close FNumBak, FNumNow KillSafe NowNorm KillSafe BakNorm IniChanged = Form2.List1.ListCount + Form2.List2.ListCount > 0 End Function Sub KillSafe (ByVal FileName$) ' If a file has been deleted by another process before INIBAK gets ' around to deleting it, KILL alone would cause an error. On Error Resume Next Kill FileName$ On Error GoTo 0 End Sub Sub MakeRoom (ByVal fName$) TakeUpSlack fName ' Make room for new .000 file by pushing others down the stack. File1.Pattern = fName + ".0*" File1.Refresh ' If there are too many, delete until there's room for one more. ' Since the file list is sorted by name, the last item in the list ' is the one with the greatest (i.e. oldest) extension. Dim N% For N = NumLevels - 1 To File1.ListCount - 1 KillSafe IniBakDir + File1.List(N) Next N File1.Pattern = fName + ".0*" File1.Refresh ' Now rename them to one number higher Dim OldName$, NewName$ ' variables to keep line from getting too long For N = File1.ListCount - 1 To 0 Step -1 OldName = IniBakDir + File1.List(N) NewName = IniBakDir + fName + "." NewName = NewName + Right$("000" + Format$(N + 1), 3) Name OldName As NewName Next N End Sub Function MatchFileNum% (ByVal fName$) ' Given an INI file name, return the number of the "File#=" key ' holding that name. Returns 11 if not found. Pass an empty ' string and it returns the first unused file number. Dim N%, Success%, IniName$ N = 0 ' Start IniName with a value that CAN'T be a filename IniName = fName + "./." Do Until (IniName = fName) Or (N > 10) N = N + 1 ' GPPS is a "wrapper" for GetPrivateProfileString Success = GPPS("INI Files", "File" + Str$(N), "", IniName, 144, "INIBAK.INI") Loop MatchFileNum = N End Function Sub menuAdd () ' Add a new INI file to the list of those protected. ' Because CmDialog1 has its CancelError field set to TRUE, it will ' generate an error if the user picks Cancel. This allows the ' subroutine to skip to the end if the user cancels. On Error GoTo Cancelled CmDialog1.Action = 1 ' this displays the Open File dialog If CmDialog1.Flags And OFN_EXTENSIONDIFFERENT Then Msg = CmDialog1.Filename + " is the wrong file type. " Msg = Msg + "INIBAK protects INI files only." MsgType = MB_ICONSTOP MsgBox Msg, MsgType, MsgTitle Exit Sub End If ' Make sure file isn't already under our protection If MatchFileNum(CmDialog1.Filename) < 11 Then Msg = "File " + CmDialog1.Filename + " is already protected " Msg = Msg + "by INIBAK." MsgType = MB_ICONINFORMATION MsgBox Msg, MsgType, MsgTitle Exit Sub End If Dim N% ' Find a vacant slot in INIBAK.INI N = MatchFileNum("") If N > 10 Then Msg = "INIBAK is already protecting ten files. Please delete " Msg = Msg + "one before adding another." MsgType = MB_ICONSTOP MsgBox Msg, MsgType, MsgTitle Exit Sub End If ' Add the first backup, add the file to the list, and write the ' file's full pathname to INIBAK.INI If AddFirstBackup(CmDialog1.Filename) Then IniList.AddItem CmDialog1.Filename Dim Success% Success = WritePrivateProfileString("INI Files", "File" + Str$(N), CmDialog1.Filename, "INIBAK.INI") End If Exit Sub Cancelled: Exit Sub End Sub Sub menuCheck () ' Compare each protected INI file with its most recent backup. If ' changed, display differences and offer to store the new version, ' restore the old, or do nothing. Called from menu choice *or* ' called automatically the FIRST time INIBAK runs during a given ' Windows session Load Form2 DoEvents Dim N% Screen.MousePointer = 11 ' hourglass cursor For N = 0 To IniList.ListCount - 1 ' Visibly select the Nth item on-screen IniList.ListIndex = N Label1.ForeColor = QBColor(15) ' white Label1.BackColor = QBColor(4) ' red Dim xPath$, xName$, xExt$ FileSplit IniList.List(N), xPath, xName, xExt Label1.Caption = "Checking " + xName + "." + xExt + "..." Label1.Refresh ' The IniChanged procedure stores added and deleted lines in ' list boxes belonging to Form2. That makes it easy to display ' the changes for the user. If IniChanged(IniList.List(N)) Then ' Restore the arrow cursor for use with Warning form Screen.MousePointer = 0 Form2.Label1.Caption = IniList.List(N) If Form2.List1.ListCount > 0 Then Form2.List1.ListIndex = 0 If Form2.List2.ListCount > 0 Then Form2.List2.ListIndex = 0 Form2.Tag = 0 Form2.Show MODAL Select Case Form2.Tag Case R_SAVENEW MakeRoom xName FileCopy IniList.List(N), IniBakDir + xName + ".000" Case R_OVERWRITE TakeUpSlack xName FileCopy IniList.List(N), IniBakDir + xName + ".000" Case R_RESTORE menuRestore IniList.List(N) Case R_IGNORE ' do nothing End Select ' Call DoEvents to allow main form to redisplay DoEvents Screen.MousePointer = 11 End If Next N Unload Form2 Label1.Caption = "Protected INI Files:" Label1.ForeColor = 0 Label1.BackColor = &HC0C0C0 Screen.MousePointer = 0 End Sub Sub menuDelete (ByVal FileName$) ' Delete the selected file from the list of those protected Msg = "Are you sure you want to remove INIBAK's protection from " Msg = Msg + FileName + "?" MsgType = MB_ICONQUESTION Or MB_YESNO If MsgBox(Msg, MsgType, MsgTitle) = IDNO Then Exit Sub End If Dim IniName$, N%, Success% ' Locate the INIBAK.INI entry for this file N = MatchFileNum(FileName) If N > 10 Then Msg = "The file " + FileName + " is not present in INIBAK.INI. " Msg = Msg + "INIBAK.INI has been deleted or modified. Please do " Msg = Msg + "not make changes to INIBAK.INI." MsgBox Msg, MB_ICONINFORMATION, MsgTitle Else Success = WritePrivateProfileString("INI Files", "File" + Str$(N), "", "INIBAK.INI") End If ' Delete associated backup files Dim xPath$, xName$, xExt$ FileSplit FileName, xPath$, xName$, xExt$ File1.Pattern = xName + ".0*" If File1.ListCount > 0 Then For N = File1.ListCount - 1 To 0 Step -1 KillSafe IniBakDir + File1.List(N) Next N End If Dim NewIndex% NewIndex = IniList.ListIndex IniList.RemoveItem IniList.ListIndex If NewIndex > IniList.ListCount - 1 Then NewIndex = NewIndex - 1 IniList.ListIndex = NewIndex End Sub Sub menuRestore (ByVal OrigName$) ' Form3 displays the list of backups for the selected file. The user ' can choose to copy one of them over the file. Load Form3 Form3.File1.Path = IniBakDir Dim xPath$, xName$, xExt$ FileSplit OrigName, xPath, xName, xExt Form3.Label1.Caption = "Restoring " + OrigName + " from backup" Form3.File1.Pattern = xName + ".0*" Form3.Tag = 0 Form3.Show MODAL If Form3.Tag = R_RESTORE Then Dim BakName$ BakName = IniBakDir + Form3.File1.FileName FileSplit BakName, xPath, xName, xExt FileCopy BakName, OrigName ' If the selected backup was not the most recent, "promote" it ' into the 000 spot. If xExt <> "000" Then ' Get rid of the temporary file with $$$ extension, if it exists KillSafe xPath + xName + ".$$$" ' Rename the selected backup to the temporary $$$ extension Name BakName As xPath + xName + ".$$$" ' Make room for new 000 file MakeRoom xName ' Rename the selected backup to the 000 extension. Name xPath + xName + ".$$$" As xPath + xName + ".000" End If Msg = "Changes to INI files do not always take effect until you " Msg = Msg + "restart Windows. Restart Windows now?" MsgType = MB_ICONQUESTION Or MB_YESNO If MsgBox(Msg, MsgType, MsgTitle) = IDYES Then Dim Success% Success = ExitWindows(EW_RESTARTWINDOWS, 0) End If End If Unload Form3 End Sub Sub mnu_File_Click (Index As Integer) Msg = "First, select an INI file from the list" MsgType = MB_ICONINFORMATION Select Case Index Case 0 menuAdd Case 1 If IniList.ListIndex >= 0 Then menuDelete IniList.Text Else MsgBox Msg, MsgType, MsgTitle End If Case 2 If IniList.ListIndex >= 0 Then menuRestore IniList.Text 'IniList.List(IniList.ListIndex) Else MsgBox Msg, MsgType, MsgTitle End If Case 3 menuCheck Case 5 Unload Form1 End Select End Sub Sub mnu_Help_Click (Index As Integer) ' WinHelp and WinHelpByNum are declared in INIBAK.BAS. VB programs ' have automatic context-sensitive help, but they need these API ' functions for menu-selected help. Dim Success% Select Case Index Case 0 Success = WinHelpByNum(Form1.hWnd, App.HelpFile, HELP_CONTENTS, 0) Case 1 Success = WinHelp(Form1.hWnd, App.HelpFile, HELP_PARTIALKEY, "") Case 2 Success = WinHelpByNum(Form1.hWnd, App.HelpFile, HELP_HELPONHELP, 0) Case 4 ' The generic About Box is implemented in the files ABOUTBOX.TXT ' and ABOUTBOX.BAS. Function DisplayAboutBox handles it all. DisplayAboutBox Form1, "INIBAK", 1#, 1994, "Neil J. Rubenking", "First Published in PC Magazine", "May 17, 1994, U.S. Edition", 0, False, 0, &HC0C0C0 End Select End Sub Sub mnu_Level_Click (Index As Integer) ' Change the number of levels of backup Dim NuLevel% NuLevel = Index + 3 ' Clicked the SAME number? Do nothing! If NuLevel = NumLevels Then Exit Sub ' Check the existing backups for any beyond the new level File1.Pattern = "*.0*" File1.Refresh Dim N%, OldCount% OldCount = 0 For N = File1.ListCount - 1 To 0 Step -1 If Right(File1.List(N), 3) >= NuLevel Then OldCount = OldCount + 1 Next N If OldCount > 0 Then Dim Msg$, MsgType% Msg = "Delete existing backups older than " + Str$(NuLevel) Msg = Msg + " levels?" MsgType = MB_ICONQUESTION Or MB_YESNOCANCEL Select Case MsgBox(Msg, MsgType, MsgTitle) Case IDYES For N = File1.ListCount - 1 To 0 Step -1 If Right(File1.List(N), 3) >= NuLevel Then KillSafe IniBakDir + File1.List(N) End If Next N Case IDNO ' do nothing; old backups will get eliminated as used Case IDCANCEL ' Exit, DON'T change level Exit Sub End Select End If ' Un-check the old menu item, checkmark the new mnu_Level(NumLevels - MinLevels).Checked = False NumLevels = NuLevel mnu_Level(NumLevels - MinLevels).Checked = True ' Write the new level value to INIBAK.INI Dim Success% Success = WritePrivateProfileString("Levels", "Levels", Str$(NumLevels), "INIBAK.INI") End Sub Sub Normalize (ByVal InName$, ByVal OutName$) ' An INI file is composed of sections and keys. A section heading is ' enclosed in [] square brackets, and a key takes the form ' keyname=value. Each key belongs to the section whose heading is ' above it. The order of the sections and the order of keys within ' sections does not matter. This procedure takes an INI file and ' generates a "normalized" file in which each line has the form ' "[section]key", and the lines are in sorted order. Dim FNumIn%, FNumOut% FNumIn = FreeFile Open InName For Input Access Read Shared As FNumIn FNumOut = FreeFile Open OutName For Output Access Write As FNumOut Dim aLine$, Locn& ' Get the section headings and store them in List1. The list has ' the sorted property, so they're automatically sorted. Along with ' each section heading, store its *location* in the INI file. Form2.List1.Clear Do While Not EOF(FNumIn) Locn = Seek(FNumIn) Line Input #FNumIn, aLine aLine = Trim$(aLine) If (Left$(aLine, 1) = "[") And (Right$(aLine, 1) = "]") Then Form2.List1.AddItem aLine + Str$(Locn) End If Loop Dim N%, M%, bLine$ ' Stepping through List1 in order, seek to the start of each section ' heading and store the keys from that section into List2. Again ' the list is automatically sorted. Comments and blank lines are ' ignored. For N = 0 To Form2.List1.ListCount - 1 aLine = Form2.List1.List(N) Form2.List2.Clear Locn = Val(Mid$(aLine, InStr(aLine, "]") + 1)) Seek FNumIn, Locn ' Re-read the section title line Line Input #FNumIn, aLine aLine = Trim$(aLine) Do If EOF(FNumIn) Then Exit Do Line Input #FNumIn, bLine bLine = Trim$(bLine) ' If we've reached the next section header, exit the loop If Left$(bLine, 1) = "[" Then Exit Do If (Left$(bLine, 1) <> ";") And (bLine <> "") Then Form2.List2.AddItem bLine End If Loop ' Write out the sorted list of keys, prefixing each with the ' section name. For M% = 0 To Form2.List2.ListCount - 1 Print #FNumOut, aLine; " "; Form2.List2.List(M) Next M Next N Close FNumIn, FNumOut End Sub Sub SaveLevel () ' Save the new value of NumLevels to INIBAK.INI Dim Success% Success% = WritePrivateProfileString("Levels", "Levels", Str$(NumLevels), "INIBAK.INI") End Sub Sub TakeUpSlack (ByVal fName$) ' It's possible that the user has deleted one or more of the backup ' files. Here we get a list of them in order and check that the ' extensions are 000, 001, and so on. If not, we rename them so ' they are. Dim N%, NextName$ File1.Pattern = fName + ".0*" File1.Refresh For N = 0 To File1.ListCount - 1 NextName = fName + "." + Right$("000" + Format$(N), 3) If StrComp(File1.List(N), NextName, 1) <> 0 Then Name IniBakDir + File1.List(N) As IniBakDir + NextName End If Next N End Sub