Windows Vista Forums
Vista Forums Home Join Vista Forums Windows 7 Forum Vista Tutorials Tags
Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks.

Go Back   Vista Forums > Misc Newsgroups > VB Script

Vista - search and replace in binary file

Reply
 
Old 11-10-2008   #1 (permalink)
Tony Logan


 
 

search and replace in binary file

I'm trying to do a search and replace in a binary file, which is a
user-specific file used by a web-conferencing application. I'm trying to
preset some config settings that cause errors when the app is started using
the default settings.

I've edited the file manually (in Notepad) to confirm the overall idea
works. The changes I need to make to the file are regular text edits, with
the exception of one character, which I'm not sure if it's a return
character, tab, etc. Looks like I can't attach files here, so best I can do
is describe it: the non-text character looks like an open rectangle.

First I get the name of the logged in user so that data can be used for
building the path to the user-specific file I'm trying to edit.

After that I've tried 2 different approaches: reading through my file a line
at a time, and also splitting it into an array. Both of these return only a
single character, which is one of the funky rectangle characters, which is
the first thing in the file.

Based on what I've read online, there are some possible binary conversion
options, although I'm not at all clear on how these would work.

At any rate, here's the code I have:

Option Explicit

' declare variables
Dim objNetwork, objWMIService, objComputer, objFSO, objTextFile
Dim colComputer
Dim strComputer, strUser, strUserProfilePath, strNextLine, strFileText
Dim arrTokens, aDataFile
Dim nF

' set constants
Const ForReading = 1
Const ForWriting = 2


Set objNetwork = CreateObject("Wscript.Network")

strComputer = "."
Set objNetwork = CreateObject("WScript.Network")
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colComputer = objWMIService.ExecQuery _
("Select * from Win32_ComputerSystem")
' for each logged in user (there should only be 1),
' parse the string (ADMINS\username) to get just the username
For Each objComputer in colComputer
strUser = objComputer.UserName
arrTokens = split(strUser, "\")
strUser = arrTokens(1)
Next

' plug strUser into path to UserProfiles.dat so we can edit the file
strUserProfilePath = "C:\Documents and Settings\" & strUser & "\Application
Data\Web Meeting\"

' check if UserProfiles.dat exists; if it does, open it and read through it
Set objFSO = CreateObject("Scripting.FileSystemObject")
' check if file exists; if it does, open it
If objFSO.FileExists(strUserProfilePath & "UserProfiles.dat") Then
Set objTextFile = objFSO.OpenTextFile(strUserProfilePath &
"UserProfiles.dat", ForReading)
' read the whole file
If Not objTextFile.AtEndOfStream Then
strFileText = objTextFile.ReadAll
' split file into an array
aDataFile = Split(strFileText, vbCrLf)
' loop through each item in array, write out the lines
For nF = 0 To UBound(aDataFile)
WScript.Echo nF & ": " & strFileText
Next
End If

'OPTIONAL METHOD FOR DEALING WITH BINARY FILE,
' BUT GAVE SAME RESULT AS SPLITTING THE ARRAY
' loop through file, read and write it one line at a time
' Do Until objTextFile.AtEndOfStream
' strNextLine = objTextFile.ReadLine
' WScript.Echo strNextLine
' WScript.Echo " "
' Loop
End If ' (if file exists)

WScript.Quit


I'd obviously need to throw in some search/replace functionality, but I have
working code to do that. First hurdle is trying to figure out if there's a
way to deal with the binary file in a way that vbs understands it.


My System SpecsSystem Spec
Old 11-10-2008   #2 (permalink)
Pegasus \(MVP\)


 
 

Re: search and replace in binary file


"Tony Logan" <TonyLogan@xxxxxx> wrote in message
news:6D9CB9E9-DB42-458F-9F9C-1E54D3E2DDDB@xxxxxx
Quote:

> I'm trying to do a search and replace in a binary file, which is a
> user-specific file used by a web-conferencing application. I'm trying to
> preset some config settings that cause errors when the app is started
> using
> the default settings.
>
> I've edited the file manually (in Notepad) to confirm the overall idea
> works. The changes I need to make to the file are regular text edits, with
> the exception of one character, which I'm not sure if it's a return
> character, tab, etc. Looks like I can't attach files here, so best I can
> do
> is describe it: the non-text character looks like an open rectangle.
>
> First I get the name of the logged in user so that data can be used for
> building the path to the user-specific file I'm trying to edit.
>
> After that I've tried 2 different approaches: reading through my file a
> line
> at a time, and also splitting it into an array. Both of these return only
> a
> single character, which is one of the funky rectangle characters, which is
> the first thing in the file.
>
> Based on what I've read online, there are some possible binary conversion
> options, although I'm not at all clear on how these would work.
>
> At any rate, here's the code I have:
>
> Option Explicit
>
> ' declare variables
> Dim objNetwork, objWMIService, objComputer, objFSO, objTextFile
> Dim colComputer
> Dim strComputer, strUser, strUserProfilePath, strNextLine, strFileText
> Dim arrTokens, aDataFile
> Dim nF
>
> ' set constants
> Const ForReading = 1
> Const ForWriting = 2
>
>
> Set objNetwork = CreateObject("Wscript.Network")
>
> strComputer = "."
> Set objNetwork = CreateObject("WScript.Network")
> Set objWMIService = GetObject("winmgmts:" _
> & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
> Set colComputer = objWMIService.ExecQuery _
> ("Select * from Win32_ComputerSystem")
> ' for each logged in user (there should only be 1),
> ' parse the string (ADMINS\username) to get just the username
> For Each objComputer in colComputer
> strUser = objComputer.UserName
> arrTokens = split(strUser, "\")
> strUser = arrTokens(1)
> Next
>
> ' plug strUser into path to UserProfiles.dat so we can edit the file
> strUserProfilePath = "C:\Documents and Settings\" & strUser &
> "\Application
> Data\Web Meeting\"
>
> ' check if UserProfiles.dat exists; if it does, open it and read through
> it
> Set objFSO = CreateObject("Scripting.FileSystemObject")
> ' check if file exists; if it does, open it
> If objFSO.FileExists(strUserProfilePath & "UserProfiles.dat") Then
> Set objTextFile = objFSO.OpenTextFile(strUserProfilePath &
> "UserProfiles.dat", ForReading)
> ' read the whole file
> If Not objTextFile.AtEndOfStream Then
> strFileText = objTextFile.ReadAll
> ' split file into an array
> aDataFile = Split(strFileText, vbCrLf)
> ' loop through each item in array, write out the lines
> For nF = 0 To UBound(aDataFile)
> WScript.Echo nF & ": " & strFileText
> Next
> End If
>
> 'OPTIONAL METHOD FOR DEALING WITH BINARY FILE,
> ' BUT GAVE SAME RESULT AS SPLITTING THE ARRAY
> ' loop through file, read and write it one line at a time
> ' Do Until objTextFile.AtEndOfStream
> ' strNextLine = objTextFile.ReadLine
> ' WScript.Echo strNextLine
> ' WScript.Echo " "
> ' Loop
> End If ' (if file exists)
>
> WScript.Quit
>
>
> I'd obviously need to throw in some search/replace functionality, but I
> have
> working code to do that. First hurdle is trying to figure out if there's a
> way to deal with the binary file in a way that vbs understands it.
>
The File System Object deals inherently with text files. If you're a purist
then you'll have to leave it at that: Searching and Replacing text in text
files is fine with VB Script, in binary files it is not. However, if you do
it just the right way then you can still do it. AFAIK the method is
undocumented and probably unsupported.

However, before you go down this track you should ascertain if your file is
a text or a binary file. Get yourself a proper binary viewer/editor so that
you can examine your file properly! XVI32.exe is one - it's free here:
www.chmaas.handshake.de.


My System SpecsSystem Spec
Old 11-10-2008   #3 (permalink)
mayayana


 
 

Re: search and replace in binary file

It's not difficult to handle "binary files". You just have
to be careful how you handle Chr(0). If you don't have
any null characters (Chr(0)) then you can safely treat
it as a text file. There's really no difference. It's just
that VBS sees a null as the end of a string, so if you
just try to read the whole file out as a textstream you only
get up to the first null.

To handle nulls and binary files in general you can use
this class that uses only VBS and Textstream:

www.jsware.net/jsware/scripts.php5#bints

If you don't have to worry about nulls then you don't
need any special treatment. Non-alphanumeric characters
are not a problem. If you need to figure out a particular
character, like your open rectangle, you can do it with
script. Just write a script like the following and copy/paste
your character in the inputbox to get the ascii value.

r = InputBox("Enter 1 character.", "Asc conversion")
MsgBox Asc(r)

You can then use that value with Replace, Split, etc:

s = Replace(s, Chr(9), "")


My System SpecsSystem Spec
Old 11-10-2008   #4 (permalink)
Pegasus \(MVP\)


 
 

Re: search and replace in binary file


"mayayana" <mayaXXyana@xxxxxx> wrote in message
news:%23FkPz93QJHA.4008@xxxxxx
Quote:

> It's not difficult to handle "binary files". You just have
> to be careful how you handle Chr(0). If you don't have
> any null characters (Chr(0)) then you can safely treat
> it as a text file. There's really no difference. It's just
> that VBS sees a null as the end of a string, so if you
> just try to read the whole file out as a textstream you only
> get up to the first null.
<snip>

I read what you write but I wonder why it is that the following code will
happily read up to the end of the file, regardless of any null characters?
And why it correctly locates the first letter "a" (which I manually
positioned well after the first null)?

const sInputName = "c:\Input.bin"
const sOutputName = "c:\Output.bin"
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oInputFile = oFSO.GetFile(sInputName)
Set oOutputFile = oFSO.OpenTextFile(sOutputName, 2, True)
Set oData = oInputFile.OpenAsTextStream
sString = oData.Read(oInputFile.Size)
wscript.echo "The first null character occurs at position " & instr(sString,
chr(0))
wscript.echo "The first letter ""a"" occurs at position " & instr(sString,
"a")
wscript.echo "Number of bytes processed: " & len(sString)
oOutputFile.Write(sString)
oData.Close
oOutputFile.Close


My System SpecsSystem Spec
Old 11-10-2008   #5 (permalink)
mayayana


 
 

Re: search and replace in binary file


That's what I mean about being careful. If you
use Read(x) it will read x number of characters.
But if you use ReadAll it will only read up to the
first null.
(I didn't know that InStr could read past a null in
VBS.)

My impression is that the whole FSO was a fairly
simple thing written at a time when providing file operations
for script seemed very luxurious, since VBS hadn't
been anything more than a simple IE DOM language
to start with. They weren't trying to block binary
file ops. They just didn't bother to deal with it. They
were making a few basic file IO functions "for dummies",
throwing together a package of odds and ends
(like FSO and COM object usage) to satisfy the growing
interests of admins and others who wanted something
more up-to-date, more GUI-ish, than simple console command-line
functions that dated back to DOS days. And they tacked
those odds and ends onto the existing web scripting
language.

As a result, the "tradition" of identifying the end of a
string with a null character is a partial, willy nilly obstacle
in VBS operations. That's why I wrote a class; to take those
weaknesses of Textstream and VBS out of the picture by
writing all of the basic functions one wants to have with
binary files, in straight VBS, while sidestepping the null
character problems.

Another limitation with FSO is that people using a DBCS (double byte
character set) codepage (Chinese, Japanese and Korean) don't
have a 1-to-1 correspondence between bytes and characters.
Since Textstream is meant to read and write text, that makes
binary ops more challenging in those oriental languages. But for
the other 4-odd billion of us, there are just the minimal obstacles
related to null characters.

Quote:

> I read what you write but I wonder why it is that the following code will
> happily read up to the end of the file, regardless of any null characters?
> And why it correctly locates the first letter "a" (which I manually
> positioned well after the first null)?
>
> const sInputName = "c:\Input.bin"
> const sOutputName = "c:\Output.bin"
> Set oFSO = CreateObject("Scripting.FileSystemObject")
> Set oInputFile = oFSO.GetFile(sInputName)
> Set oOutputFile = oFSO.OpenTextFile(sOutputName, 2, True)
> Set oData = oInputFile.OpenAsTextStream
> sString = oData.Read(oInputFile.Size)
> wscript.echo "The first null character occurs at position " &
instr(sString,
Quote:

> chr(0))
> wscript.echo "The first letter ""a"" occurs at position " & instr(sString,
> "a")
> wscript.echo "Number of bytes processed: " & len(sString)
> oOutputFile.Write(sString)
> oData.Close
> oOutputFile.Close
>
>

My System SpecsSystem Spec
Reply

Thread Tools


Similar Threads
Thread Forum
Binary search and replace General Discussion
Search and Replace text file very slow PowerShell
Replace Start Menu Search with 3rd Party Search General Discussion
Read and search through a binary file PowerShell
Search and replace in a text file? PowerShell


Vista Forums is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media Ltd

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46