MAKEMSI quickly and reliably creates MSI files in a non-programmatic way
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
[Bottom][Contents][Prev]: Unversioned files[Next]: ZIP Images for Directory Trees
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
\->Tips and Tricks->File and Directory->Update Hosts File

Update Hosts File

This example shows how you can easily add and remove blocks of text from a text file. It adds a start and end marker to make identification of the inserted block easy.

It could easily be enhanced to have some soort of commit and rollback.

#define MarksStart    [MyMsi.MM: AUTO-INSERTED-START]   ;;Marks start of block in the hosts file
#define MarksEnd      [MyMsi.MM: AUTO-INSERTED-END]     ;;Marks end   of block in the hosts file
#define MarksNewLine  {NL}
#(  '<$MarksNewLine>'
    #define HostFileChanges

    <$MarksNewLine><$MarksNewLine><$MarksNewLine>
    <?Hash>##################<$MarksStart>################
    <?Hash>
    <?Hash> Do not insert new host entries in this block or alter records (update MSI source to correct faults)
    <?Hash> Inserted at <?CompileTime>

    <$MarksNewLine><$MarksNewLine><$MarksNewLine>
    1.2.3.4     SillyHostName1
    1.2.3.5     SillyHostName2
    <?Hash>##################<$MarksEnd>##################
#)
<$VbsCa Binary="UpdateTcpipHostsFile.vbs">
    const MaxNumberOfBlankLines = 5

    <$VbsCaEntry "AddToHostsFile">
         RemoveExisting()
         AddAdditions()
    <$/VbsCaEntry>

    <$VbsCaEntry "RemoveFromHostsFile">
         RemoveExisting()
    <$/VbsCaEntry>

<?NewLine><?NewLine>
    '===========================================================================
    sub RemoveExisting()
    '===========================================================================
        CaDebug 2, "Removing any previously added entries from the hosts file..."
        VbsCaLogInc 1
        dim HostsFile  : HostsFile = VbsCaPropertyGet("SystemFolder", "c:\winnt\system32\", "") & "Drivers\Etc\Hosts"
        dim oFS        : set oFS   = CaMkObject("Scripting.FileSystemObject")
        if  not oFS.FileExists(HostsFile) then
            ;--- Nothing to undo --------------------------------------------
            CaDebug 2, "No hosts file to remove entries from"
        else
            ;--- Open Files -------------------------------------------------
            CaDebug 2, "Hosts file exists, opening files"
            dim TmpFile : TmpFile   = CaGetEnv("TEMP", true) & "\NewHostsFile(RemoveExisting).txt"
            CaDebug 2, "Temporary file: " & TmpFile
            dim ReadStream  : set ReadStream  = oFS.OpenTextFile(HostsFile, ForReading)
            dim WriteStream : set WriteStream = oFS.CreateTextFile(TmpFile, true)
            dim CopyLines   : CopyLines       = true
            dim DidRemove   : DidRemove       = false
            dim BlankLineCnt: BlankLineCnt    = 0
            CaDebug 0, "Reading File"
            VbsCaLogInc 1
            do  while ReadStream.AtEndOfStream <> true
                ;--- Read the line ------------------------------------------
                dim ReadLine : ReadLine =  ReadStream.ReadLine()
                CaDebug 0, "LINE> " & ReadLine
                VbsCaLogInc 1

                ;--- Copy all lines except those in previously copied block ---
                if  CopyLines then
                    ;--- Not in a block, so see if we found the start -------
                    if  instr(ReadLine, "<$MarksStart>") <> 0 then
                        ;--- Found the start of the block -------------------
                        CaDebug 0, "Found the start of the block"
                        CopyLines = false
                        DidRemove = true
                    else
                        ;--- Copy the line ----------------------------------
                        if  ReadLine = "" then
                            ;--- Have a blank line, just count (will drop trailing blank lines) ---
                            BlankLineCnt = BlankLineCnt + 1
                        else
                            ;--- Output any queued up blank lines? ----------
                            dim i
                            for i = 1 to min(BlankLineCnt, MaxNumberOfBlankLines)
                                WriteStream.writeline("")
                            next

                            ;--- Output the actual line ---------------------
                            WriteStream.writeline(ReadLine)
                        end if
                    end if
                else
                    ;--- In a block, so see if we found the end -------------
                    if  instr(ReadLine, "<$MarksEnd>") <> 0 then
                        ;--- Found the start of the block -------------------
                        CaDebug 0, "Found the end of the block"
                        CopyLines = true
                    end if
                end if

                ;--- Restore indent -----------------------------------------
                VbsCaLogInc -1
            loop
            VbsCaLogInc -1

            ;--- Finished Extraction ----------------------------------------
            ReadStream.Close()
            WriteStream.Close()
            set ReadStream  = Nothing
            set WriteStream  = Nothing

            ;--- Update Hosts File ------------------------------------------
            if  not DidRemove then
                CaDebug 0, "Finished creating new host file, no changes so no need to copy over: " & HostsFile
            else
                CaDebug 0, "Finished creating new host file, so update: " & HostsFile
                oFS.CopyFile TmpFile,  HostsFile, true
            end if
            CaDebug 0, "Removal completed"
        end if
        VbsCaLogInc -1
        set oFS = Nothing
    end sub


    <?NewLine><?NewLine>
    '===========================================================================
    function Min(x, y)
    '===========================================================================
        dim Tmp
        if x < y then Tmp = x else Tmp = y
        Min = Tmp
    end function


    <?NewLine><?NewLine>
    '===========================================================================
    sub AddAdditions()
    '===========================================================================
        CaDebug 2, "Adding new entries to the hosts file..."
        VbsCaLogInc 1
        dim Additions : Additions = replace("<$HostFileChanges>", "<$MarksNewLine>", vbCRLF)
        dim HostsFile : HostsFile = VbsCaPropertyGet("SystemFolder", "c:\winnt\system32\", "") & "Drivers\Etc\Hosts"
        dim oFS       : set oFS   = CaMkObject("Scripting.FileSystemObject")
        if  not oFS.FileExists(HostsFile) then
            ;--- Nothing to undo --------------------------------------------
            CaDebug 2, "No hosts file, will create"
        end if
        CaDebug 2, "Append new host file lines"
        dim Stream : set Stream = oFS.OpenTextFile(HostsFile, ForAppending, true)
        Stream.WriteLine vBCRLF & Additions
        Stream.close()
        set Stream = Nothing
        CaDebug 2, "Finished adding new host lines"
        set oFS = Nothing
        VbsCaLogInc -1
   end sub
<$/VbsCa>
<$VbsCaSetup Binary="UpdateTcpipHostsFile.vbs" Entry="AddToHostsFile" Seq="InstallValidate-" CONDITION=^<$CONDITION_EXCEPT_UNINSTALL>^ Type="IMMEDIATE">

Note that the above works for 32 bit OS (to also handle 64 bit replace "SystemFolder" with "SYSTEM32").


Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006, 2007, 2008 & 2009 for the Windows SDK (Windows Installer) area.Please email me any feedback, additional information or corrections.
See this page online (look for updates)

[Top][Contents][Prev]: Unversioned files[Next]: ZIP Images for Directory Trees


MAKEMSI© is (C)opyright Dennis Bareis 2003-2008 (All rights reserved).
Sunday August 13 2017 at 2:39pm
Visit MAKEMSI's Home Page
Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006, 2007, 2008 & 2009 for the Windows SDK (Windows Installer) area.