Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
Solved

# Batch file to replace lines in an INI file

Posted on 2001-07-19
Medium Priority
901 Views
I want to run a batch file in a login script.  What I want the batch file to do is scan a file called appsrv.ini located in the C:\WINDOWS\Profiles\<username>\Application Data\ICAClient directory and anywhere it finds the line ADDRESS=<any ip address>, I want to replace that line with ADDRESS=<a specific IP address>.  Username is a DOS variable called NWNAME.

The batch file will run on Windows 98 machines.  I would prefer not to install any additional software.
0
Question by:lpenrod
[X]
###### Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

• Help others & share knowledge
• Earn cash & points
• 4
• 3
• 2
• +1

LVL 7

Accepted Solution

rin1010 earned 800 total points
ID: 6300008

lpenrod,

I understand you'd rather not use other software, but there's no good way to do it
using only existing Windows 9.x DOS commands, especially if you need to
scan and edit multiple specific lines. One method is to use FIND to replace a line in a file,
but it would want to replace all the specified lines with only one new line
and either at the end or beginning of the file.
Any batch script written to alter your INI file using such commands
would be tough to maintain and probably prone to error.
For example, this batch script will replace a line in a file with another line:

@echo off
find /v /i "Address=" < appsrv.ini > appsrv.tmp
copy appsrv.tmp appsrv.ini
del appsrv.tmp

That's just for testing and doesn't use the path you mentioned of
C:\WINDOWS\Profiles\%NWNAME%\Application Data\ICAClient\appsrv.ini
so if you test it put the INI and batch file in a temp directory or adjust the paths.

But if you try it you'll see that it removes all lines having Address=
and appends the new line to the end of the file. You can alternatively insert a new line
at the beginning of the file, but the INI then wouldn't be read properly.
This would work if the INI had only one section and Address= reference.
But if you use the above script and attempt to modify each Address= line
occurring in an INI file looking similar to this:

[TCPIPConnection128Encrypt]
TransportDriver=TCP/IP
Compress=On
PersistentCacheEnabled=On

TransportDriver=IPX
Compress=Off
PersistentCacheEnabled=Off

...the result would look like this:

[TCPIPConnection128Encrypt]
TransportDriver=TCP/IP
Compress=On
PersistentCacheEnabled=On

TransportDriver=IPX
Compress=Off
PersistentCacheEnabled=Off

Note that all Address= lines are removed, leaving only one instance of the new line
at the end of the file. Again, it would probably be impractical to maintain a script
to isolate and modify every occurrence.

If nobody comes up with a suitable method here, you may want to consider
using a third-party utility to do it. I can recommend a small one (22k) that works well
and does an assortment of string manipulations. I've tested it under several conditions
and also on the above examples. It's called SED and can be easily obtained,
but I've placed a 16-bit and a 32-bit version on a server where you can get it
and can also read some stuff about it. I'll append the url of the page,
which has documentation and various other material on it... (It's free to use...
The copyright and public domain quotes on my page are from the author.)

Anyway, using the same INI sample as above, here are a couple of examples
of its use which you can place in your script... The appropriate paths have to be provided,
but this will show you the syntax and give some ideas to test.
Again, I did this on a created APPSRV.INI sample file structured like this:

[TCPIPConnection128Encrypt]
TransportDriver=TCP/IP
Compress=On
PersistentCacheEnabled=On

TransportDriver=IPX
Compress=Off
PersistentCacheEnabled=Off

This first example pipes the contents of the APPSRV.INI file through SED
It writes the output to a temporary file, then overwrites the APPSRV.INI file
with the contents of the temp file and then (optionally) deletes the temp file:

@echo off
SED "s/^Address=.*$/Address=10.10.10.10/"< appsrv.ini >appsrv.tmp copy appsrv.tmp appsrv.ini del appsrv.tmp This following method does the same as above but without creating a temporary file... It just pipes the contents of the APPSRV.INI file to SED, alters the appropriate lines and writes the output straight back to the APPSRV.INI file: type appsrv.ini | SED "s/^Address=.*$/Address=10.10.10.10/" >appsrv.ini

Both of the methods above create a new APPSRV.INI file looking like this:

[TCPIPConnection128Encrypt]
TransportDriver=TCP/IP
Compress=On
PersistentCacheEnabled=On

TransportDriver=IPX
Compress=Off
PersistentCacheEnabled=Off

If you want to test it, all that's needed is to change the 10.10.10.10 to your required address.
Not having your exact INI file, I'm unable to test it thoroughly, but I think it should
do what you need and give you other capabilities and options not possible
when using only DOS commands in a batch script. Any such method, if possible,
would still require calling external apps such as FIND and FC, etc...
SED will allow you to do it with only one small app and from the path.

This isn't exactly the call from a login script you're seeking, but hopefully it's helpful...

http://users.aol.com/pasacaca/sed

0

LVL 5

Expert Comment

ID: 6302982
Or, you can use the "for" command with the "If x==x" commands to create a new ini file.....

::-------------- start of bat file -----------
@echo off
cls
setlocal
:: you can change the following 4 env var set statements
set NewIniFile=C:\temp\NewIniFile.tmp
set OldIniFile=C:\WINDOWS\Profiles\%NWNAME%\Application Data\ICAClient\appsrv
:: or you could accept command line arguments rather than hard code the old and new addresses

if exist %NewIniFile% del %NewIniFile%

for /f "delims=~" %%h in (%OldIniFile%.ini) do (
:: keep all other lines
if not %%h==ADDRESS=10.10.10.008 echo %%h >>%NewIniFile%
)

::save off original ini file before replacing it with the new one
copy %OldIniFile%.ini %OldIniFile%.old
copy %NewIniFile% %OldIniFile%.ini

echo Done.

::----------------end of bat file----------------

note.... I've not tested this thouroughly.

0

LVL 5

Expert Comment

ID: 6302990
oops.... I forgot to mention that in the "FOR" command above, it's using a delimiter of "~" in order to get the whole line (including spaces) assigned to the %%h variable.  If you've normally got tildes ("~") in your ini file you may have to come up with another odd character to act as the delimiter.... perhaps the carat  ("^").

Pat

0

LVL 16

Expert Comment

ID: 6304054

This can be done in a number of different ways. These are as follows:

Use the FIND command to filter the IP address
Writing the file
Building the file
Manipulating the file

Writing the file is easiest, but i'm gonna use the build method.

You need the following two data files in the client's target folder:

paul1.txt
paul2.txt

This assumes the client's name is:

paul

Therefore, the client's target folder will be:

c:\windows\profiles\paul\application data\icaclient\

So, whatever the client's name is, the data files, 1 and 2, are named nnn1 and nnn2, where nnn is the client's name

Taking the example file provided by rin1010, paul1.txt contains the following two lines:

[TCPIPConnection128Encrypt]
TransportDriver=TCP/IP

NOTE: Make sure there is a carriage return after at the end of the 2nd line

paul2.txt contains the following eight lines:

Compress=On
PersistentCacheEnabled=On

TransportDriver=IPX
Compress=Off
PersistentCacheEnabled=Off

So, the single appsrv.ini file has been split into two files, paul1.txt and paul2.txt, minus the IP address line.

You also need the two following files somewhere in your path:

changeip.bat

The source for the login.bat file is:

@rem ========================================================================
@rem
@rem Date: 21 July 2001
@rem
@rem Author: Paul Tomasi
@rem
@rem Description: Test file for CHANGEIP.BAT
@rem
@rem Dependencies: CHANGEIP.BAT
@rem ========================================================================
@echo off

call changeip paul 255.255.192.1

:end

Note the single line calling the CHANGEIP.BAT batch file.  Here, I have hard-coded the name and the IP address but you could have equally used:

call changeip %1 %2

The source for CHANGEIP.BAT is as follows:

@rem ========================================================================
@rem Name: CHANGEIP.BAT
@rem
@rem Date: 21 July 2001
@rem
@rem Author: Paul Tomasi
@rem
@rem Description: Change IP address passing name and IP address of user
@rem
@rem Call format: CHANGEIP <name> <ip number>
@rem
@rem Dependencies: Uses drive Z: Change this letter if already used or use full paths
@rem ========================================================================
@echo off

rem ------------------------------------------
rem Validate client name and IP address passed
rem ------------------------------------------
if "%1"=="" goto no_name
if "%2"=="" goto no_ip

rem ------------------------------------------
rem Check the client exists
rem ------------------------------------------
if not exist "c:\windows\profiles\%1\nul" goto no_user

rem ------------------------------------------
rem Check the client folder exists
rem ------------------------------------------
if not exist "c:\windows\profiles\%1\application data\icaclient\nul" goto no_client

rem ------------------------------------------
rem Map the drive for clarity
rem Can be removed but must use full pathnames
rem ------------------------------------------
subst z: "c:\windows\profiles\%1\application data\icaclient"
if not exist z:\nul goto no_map

rem ------------------------------------------
rem Move to mapped drive
rem ------------------------------------------
z:

rem ------------------------------------------
rem Check data files exist
rem ------------------------------------------
if not exist %11.txt goto no_data1
if not exist %12.txt goto no_data2

rem ------------------------------------------
rem Check target file exists
rem ------------------------------------------
if not exist appsrv.ini goto no_ini

rem ------------------------------------------
rem Use bare file attributes
rem Can be removed if not a problem
rem ------------------------------------------
attrib -s -h -r appsrv.ini
attrib -s -h -r appsrv.tmp

rem ------------------------------------------
rem Stash original file
rem ------------------------------------------
copy appsrv.ini appsrv.tmp > nul
if not exist appsrv.ini goto no_tmp

rem ------------------------------------------
rem Build new file
rem ------------------------------------------
copy %11.txt appsrv.ini > nul
copy appsrv.ini+%12.txt appsrv.ini > nul
goto end

rem ------------------------------------------
rem Error messages and tidy up
rem ------------------------------------------
:no_name
echo ERROR: No Name
goto end

:no_ip
goto end

:no_user
echo ERROR: No User [%1]
goto end

:no_client
echo ERROR: No Client [%1]

:no_data1
echo ERROR: No [%11.txt] file
goto end

:no_data2
echo ERROR: No [%12.txt] file
goto end

:no_map
echo ERROR: Unable to map drive to [z]
goto end

:no_ini
echo ERROR: No [appsrv.ini]
goto end

:no_tmp
echo ERROR: Could not create [appsrv.tmp]
goto end

rem ------------------------------------------
rem End.  Remove mapped drive
rem ------------------------------------------
:end
c:
subst /d z:

You can run this batch file stand-alone.  I firmly believe in lots of error-checking (and recovery where possible) so forgive me for slipping some of the easier ones in.

On a final note, you don't need to use SUBST to map a drive folder to a drive name in which case, you'll have to use full path names.  I used SUBST to clarify the source.

If you're interested in the Write method, giz a shout....

0

LVL 16

Expert Comment

ID: 6304067
Oh, btw, if the appsrv.ini is the same for all the clients then you don't need to have data1.txt and data2.txt data files in each client target folder - you could have just one data1.txt file and one data2.txt file when building to any client folder.

for example:

rem ------------------------------------------
rem Build new file
rem ------------------------------------------
copy [wherever]\data1.txt [client]\appsrv.ini > nul
copy [client]\appsrv.ini+[wherever]\data2.txt [client]\appsrv.ini > nul
goto end

Whatever the [client] folder is including the %1 parameter....

This approach means all you actually need is in fact ONLY four files instead of two batch files plus two data files for each client!!!!

0

LVL 3

Author Comment

ID: 6304077
Here is an example of my ini file.  Every users ini file is potentially different.  Sometimes there is even more than one entry for the same server (so you can have multiple sessions).
In this example, I need to change the xxx.xxx.xxx.xxx address to yyy.yyy.yyy.yyy

I have been playing with the SED utility that rin1010 recommended and it is working beautifully.  I am just curious if it can be done without using a third party.

If I read t0t0's code correctly, everyone basically has to have the same ini.  That is where my problem is that not everyone does.

The SED utility scans the whole file and replaces any occurance of xxx.xxx.xxx.xxx with yyy.yyy.yyy.yyy which is exactly what I need.

Here is my ini:

;**********************************************************************
;**
;** APPSRV.INI - Application Server Configuration File.
;**
;** This file contains user settings which define application
;** servers and other preferences.
;**
;**********************************************************************

[WFClient]
Version=2
LogFile=C:\Program Files\Citrix\ICA Client\wfclient.log
LogFileWin16=wfcwin.log
LogFileWin32=C:\WINDOWS\Profiles\lpenrod\Application Data\ICAClient\wfcwin32.log
LogAppend=Off
LogConnect=On
LogErrors=On
LogTransmit=Off
LogKeyboard=Off
Hotkey1Char=F1
Hotkey1Shift=Shift
Hotkey2Char=F3
Hotkey2Shift=Shift
Hotkey3Char=F2
Hotkey3Shift=Shift
Hotkey4Char=F1
Hotkey4Shift=Ctrl
Hotkey5Char=F2
Hotkey5Shift=Ctrl
Hotkey6Char=F2
Hotkey6Shift=Alt
Hotkey7Char=plus
Hotkey7Shift=Alt
Hotkey8Char=minus
Hotkey8Shift=Alt
Hotkey9Char=F3
HotKey9Shift=Ctrl
DisableSound=Off
DisableCtrlAltDel=On
MouseTimer=0
KeyboardTimer=0
ColorMismatchPrompt_Have16_Want256=On
ColorMismatchPrompt_Have64K_Want256=On
ColorMismatchPrompt_Have16M_Want256=On
DosConnectTTY=On
ConnectTTY=Off
ConnectTTYDelay=1000
BrowserRetry=3
BrowserTimeout=1000
LanaNumber=0
ScriptDriver=SCRIPT.DDL
ScriptDriverWin16=SCRIPTW.DLL
ScriptDriverWin32=SCRIPTN.DLL
ScriptFile=
PersistentCacheEnabled=Off
PersistentCacheSize=64414677
PersistentCacheMinBitmap=8192
PersistentCachePath=C:\WINDOWS\Profiles\lpenrod\Application Data\ICAClient\Cache
COMAllowed=On
CPMAllowed=On
VSLAllowed=On
CDMAllowed=On
MaximumCompression=Off
DesiredColor=2
DesiredHRES=640
DesiredVRES=480
PNCacheVersion=1
KeyboardLayout=(User Profile)
KeyboardType=(DEFAULT)
RuntimePrompt=On
AutoReconnect=Off
PersistentCachePercent=0
ApplicationSetManagerIconOff=Off
CustomConnectionsIconOff=Off
FindNewApplicationSetIconOff=Off
DragoutOff=Off
NoSavePwordOption=Off
PNUIShowTB=1
PNUIShowTBText=1
PNUIShowSB=1
PNUIViewType=40028
PNUINoAutoSearch=On
PNUIHPos=285
PNUIVPos=41
PNUIWidth=769
PNUIHeight=328
ICASOCKSProtocolVersion=0
ICASOCKSProxyPortNumber=0
DefaultSoundType=0
ClientAudio=Off
EncryptionLevel=0
DesiredWinType=0
ScreenPercent=0
TWIMode=Off
Hotkey10Shift=Ctrl
Hotkey10Char=F4
PNDefault=PRO_PAY Farm

[Smartcard]
;=========================================================================================
;== When SmartcardRequired=yes, connecting to a remote application will
;   require a smartcard provided that no other remote applications are currently executing.
;   N.B. When enabled with the 32-bit DOS client this also prevents the use of insecure
;   command line options including /iniappsrv.
;== Omitted entry defaults to 'Off'.
;=========================================================================================
SmartcardRequired=no
;=========================================================================================
;== Setting a bypass switch to yes tells the system to get its User information from the
;   commandline or appsrv.ini file instead of the smartcard.
;== Omitted entries default to 'No'.
;=========================================================================================
BypassSmartcardDomain=no
;=========================================================================================
;== Supported Smartcards
;== MPCOS       - cards by Gemplus
;== TB-1000     - cards by Microcard
;-----------------------------------------------------------------------------------------
;== Supported values for CardReader key
;== GCR410      - Gemplus GCR410 Smartcard reader
;=========================================================================================
Timeout=1000    ; given in milli-seconds

[Common Default Information]
ProgramGroup=Citrix ICA Client

[ApplicationServers]
Citrix Server=
Citrix Server 2=
Citrix Server 3=
PNFII=
John=

[Citrix Server]
TransportDriver=TCP/IP
BrowserProtocol=UDP
ScreenPercent=95
DoNotUseDefaultCSL=Off
Description=Citrix Server
IconPath=C:\PROGRAM FILES\CITRIX\ICA CLIENT\PN.EXE
IconIndex=1
ConnectType=1
MaximumCompression=Off
Compress=On
PersistentCacheEnabled=Off
MouseTimer=0
KeyboardTimer=0
AudioBandwidthLimit=1
UseDefaultSound=On
DefaultSoundType=1
UseDefaultEncryption=On
EncryptionLevel=0
UseDefaultWinColor=On
UseDefaultWinSize=Off
DesiredWinType=6
TWIMode=Off
ZLKeyboardMode=0
ZLMouseMode=2

[Citrix Server 2]
TransportDriver=TCP/IP
ScreenPercent=95
Description=Citrix Server 2
IconPath=C:\PROGRAM FILES\CITRIX\ICA CLIENT\PN.EXE
IconIndex=1
ConnectType=1
MaximumCompression=Off
Compress=On
PersistentCacheEnabled=Off
MouseTimer=0
KeyboardTimer=0
AudioBandwidthLimit=1
UseDefaultSound=On
DefaultSoundType=1
UseDefaultEncryption=On
EncryptionLevel=1
UseDefaultWinColor=On
UseDefaultWinSize=Off
DesiredWinType=6
TWIMode=Off
ICASOCKSProtocolVersion=-1
ICASOCKSProxyPortNumber=1080

[Citrix Server 3]
TransportDriver=TCP/IP
ScreenPercent=95
Description=Citrix Server 2
IconPath=C:\PROGRAM FILES\CITRIX\ICA CLIENT\PN.EXE
IconIndex=1
ConnectType=1
MaximumCompression=Off
Compress=On
PersistentCacheEnabled=Off
MouseTimer=0
KeyboardTimer=0
AudioBandwidthLimit=1
UseDefaultSound=On
DefaultSoundType=1
UseDefaultEncryption=On
EncryptionLevel=1
UseDefaultWinColor=On
UseDefaultWinSize=Off
DesiredWinType=6
TWIMode=Off
ICASOCKSProtocolVersion=-1
ICASOCKSProxyPortNumber=1080

[PNFII]
TransportDriver=TCP/IP
ScreenPercent=0
Description=PNFII
IconPath=C:\PROGRAM FILES\CITRIX\ICA CLIENT\PN.EXE
IconIndex=1
ConnectType=1
MaximumCompression=Off
Compress=On
PersistentCacheEnabled=Off
MouseTimer=0
KeyboardTimer=0
AudioBandwidthLimit=1
UseDefaultSound=On
DefaultSoundType=1
UseDefaultEncryption=On
EncryptionLevel=1
UseDefaultWinColor=On
UseDefaultWinSize=Off
DesiredWinType=2
TWIMode=Off
ICASOCKSProtocolVersion=-1
ICASOCKSProxyPortNumber=1080
DesiredHRES=800
DesiredVRES=600

[John]
TransportDriver=TCP/IP
BrowserProtocol=UDP
ScreenPercent=95
DoNotUseDefaultCSL=Off
Description=John
IconPath=C:\PROGRAM FILES\CITRIX\ICA CLIENT\PN.EXE
IconIndex=1
ConnectType=1
MaximumCompression=Off
Compress=On
PersistentCacheEnabled=Off
MouseTimer=0
KeyboardTimer=0
AudioBandwidthLimit=1
UseDefaultSound=On
DefaultSoundType=1
UseDefaultEncryption=On
EncryptionLevel=0
UseDefaultWinColor=On
UseDefaultWinSize=Off
DesiredWinType=6
TWIMode=Off
ZLKeyboardMode=0
ZLMouseMode=2
Domain=mis

0

LVL 16

Expert Comment

ID: 6304134
I note the text "address" appears in the following sections of your file:

[WFClient]

[Citrix Server]

[Citrix Server 2]

[Citrix Server 3]

[PNFII]

[John]

Can you answer the following questions?

(1) Apart from TcpBrowserAddress=xxx.xxx.xxx.xxx in [WFClient], are there likely to be other entries in this file that are NOT just 'Address=xxx.xxx.xxx.xxx' and which will also require changing?

(2) In section [PNFII], is this supposed to read 'Address=xxx.xxx.xxx.xxx' as well?

(3) In section [John], is 'Address=209.184.158.5' supposed to be changed too?

(5) Where is yyy.yyy.yyy.yyy coming from.  Can it be passed as a parameter?

This is a little bit tougher, but I'm looking at possible solutions and I think I have an answer brewing up....

Wow! This one's a nice one....

Oh, by the way, please read rin1010's comment as I think he stated that SED would replace anything after 'Address=' with a supplied IP number.

See section [WFCient].  The two entries:

would also become:

Be careful!!!!

0

LVL 3

Author Comment

ID: 6305093
1) TcpBrowserAddress and Address are the only two things that require changing.

2) No, it is a different server.

3) I messed up the [John] section, it is a third address.

4) They are not zero padded.  I do not believe that zero padding will hurt though.

5) Each entry ([Citrix Server], [Citrix Server 2], [Citrix Server 3], [PNFII], [John]) can be the same address, different addresses or a combination.  Basically each users appsrv.ini has the potential to have different entries.  The addresses are to servers both inside and outside our network.  What they have just depends upon their job function, and even then, they can be different.

Actually, I have been testing SED and it works great.  Here is my one line batch file that does the job:
type c:\windows\profiles\%NWNAME%\applic~1\icacli~1\appsrv.ini | SED "s/xxx.xxx.xxx.xxx/yyy.yyy.yyy.yyy/" >c:\windows\profiles\%NWNAME%\applic~1\icacli~1\appsrv.ini

What that does is anywhere it finds xxx.xxx.xxx.xxx it replaces it with yyy.yyy.yyy.yyy.  That is exactly what I want it to do.  Only one of my servers is changing addresses, so I just need to update that servers address (xxx.xxx.xxx.xxx) while leaving the other servers addresses alone.

To run this on all 250 machines, I either have to install SED on each machine or place it somewhere that each machine has access.  This is not really a problem, but I was courious if I could accomplish the same thing using DOS commands and not installing SED.
0

LVL 3

Author Comment

ID: 6314724
SED worked like a charm!

I can see that is going to be a usefull utility.

Thanks.
0

LVL 3

Author Comment

ID: 6359957
I have run into some files that I want to modify using SED that are not text files.

For example, I want to modify some registry entries.  The file gets all messed up.  I am guessing that it has something to do with using the TYPE command.

I would gladly give more points to get me straightened out.
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

YESTERDAY YESTERDAY.BAT is inspired by a previous article I wrote entitled: TOMORROW.BAT (http://www.experts-exchange.com/OS/Microsoft_Operating_Systems/MS_DOS/A_4196-Advanced-Batch-File-Programming-TOMORROW-BAT.html). The crux of this batch f…
Being a system administrator some time we require to do things remotely, one of them is installing software. Here I am going to tell you how to install software through wmic (Windows management instrument console). I am not at all saying that this i…
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…