Unterminated String Error 1033

Technical support and scripting issues

Moderators: Dorian (MJT support), JRL

chihuahualand
Junior Coder
Posts: 35
Joined: Thu Jan 12, 2006 9:20 pm
Contact:

Post by chihuahualand » Wed Feb 25, 2009 2:02 pm

in v7.4.009

I get "Error in SubString Command"

User avatar
Marcus Tettmar
Site Admin
Posts: 7395
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Wed Feb 25, 2009 2:04 pm

I'm using complex expressions. For v7 try this instead:

Pos>NullChar,info_2,1,nPos
Let>nPos=nPos-1
MidStr>info_2,1,nPos,Volume_Name
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

chihuahualand
Junior Coder
Posts: 35
Joined: Thu Jan 12, 2006 9:20 pm
Contact:

Post by chihuahualand » Wed Feb 25, 2009 2:09 pm

worked

User avatar
JRL
Automation Wizard
Posts: 3526
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Thu Feb 26, 2009 5:08 am

n regards to v7.4.009 only:
As a separate topic, possibly completely separate, I have to repeat the command for the code to work while step-debugging, as in:

Separate>%info_2%,%NullChar%,var
Separate>%info_2%,%NullChar%,var

There is every indication that nothing happened on the first execution: no %var_1%, etc. in the watch list and a MessageModal>%var_1% produces "%var_1%"

again, this makes me feel dirty, but, I'll live with my dirty little secret.
Thinking about this. There have been MS versions where the watchlist didn't report exactly as you'd like. Maybe v7.4.009 is one of those. Try viewing the var_x list in a message and see if the list is created after one separate> line, but not displayed.

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Thu Feb 26, 2009 10:32 am

Hi Marcus,

I had asked...
jpuziano wrote:The following section from this post: removing trailing ascii(0) made me think it was possible...
mtettmar wrote:0 is a null char. It normally marks the end of a string.

But, you could try:

VBSTART
VBEND
VBEval>CHR(0),NullChar

StringReplace>text,NullChar,,text
...but the Length> command showed the variable length as 255 both before and after doing the above so there was no effect.

Sidenote: Marcus... is the StringReplace> command "supposed" to be able to replace null characters within a variable? If so it doesn't but perhaps its just not possible.
To which you replied...
mtettmar wrote:StringReplace is not supposed to use null chars as delimiters, no.
Thanks for that answer.

We now know that StringReplace> will not work with null characters... however the Help File makes no mention of this.
MS 11.1.04 Help File wrote:StringReplace

StringReplace>sourcestring,find,replace,newstring

Creates a new string, newstring, by searching sourcestring for all ocurrences of find, replacing them with replace.

Abbreviation: RPL

Examples

Let>string=Your name is "Fred"
StringReplace>string,","",vbEscapedString

StringReplace>Good evening,evening,morning,newgreeting
Is a null character not allowed just in the 'find' parameter, or 'replace' and 'sourcestring' as well?

Please let us know what the limitations are... and consider adding a caveat to the Help File so others will not run into this same problem.

Thanks and take care

P.S. You use the word ocurrences in your Help File definition... Firefox spell checker is telling me it should be occurrences... two c's after the o.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
JRL
Automation Wizard
Posts: 3526
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Fri Feb 27, 2009 11:27 pm

jpuziano wrote:Finally, a challenge for the gurus out there - a bounty on null character string cleansing.

2 points goes to the first person who can take the script below and add code to strip out the null characters and any other characters not part of the actual VolumeName data in the info_2 variable... i.e. if the first MDL> shows VolumeName: My_Disk then the info_2 variable should actually be 7 chars long and the second MDL> should show VolumeName Length: 7

- without using the Separate> command
- without resorting to using a command like MidStr> to extract a single character substring and comparing it to a NullChar variable... over and over throughout the string like in the example above
- anything else is allowed, RegEx, StringReplace>, VBscript, etc.
- Marcus, if you have a solution, please wait until the others have had a chance
Two points should go to Kpassaur. I slightly modified his post HERE to provide the script below. This script removes all non-text characters from a provided string. I'm sure it could be modified to remove only the null characters.




Code: Select all

LibFunc>kernel32,GetVolumeInformationA,info,E:\,str REF:0,200,REF:0,REF:0,REF:0,str REF:0,255

VBSTART
Dim sTmp
Dim i
Function StripNonAscii (rvntVal)

For i = 1 To Len(rvntVal)
If Asc(Mid(rvntVal, i, 1)) < 32 Or Asc(Mid(rvntVal, i, 1)) > 126 Then
sTmp = sTmp & ""
Else
sTmp = sTmp & Mid(rvntVal, i, 1)
End If
If Asc(Mid(rvntVal, i, 1)) = 10 Then
sTmp = sTmp & Mid(rvntVal, i, 1)
End If
If Asc(Mid(rvntVal, i, 1)) = 13 Then
sTmp = sTmp & Mid(rvntVal, i, 1)
End If
If Asc(Mid(rvntVal, i, 1)) = 27 Then
sTmp = sTmp & Mid(rvntVal, i, 1)
End If
Next

StripNonAscii = sTmp

End Function
VBEND

VBRun>StripNonAscii,%info_2%
VBEval>sTmp,answer
VBEval>i,count

MDL>%answer%

User avatar
Bob Hansen
Automation Wizard
Posts: 2475
Joined: Tue Sep 24, 2002 3:47 am
Location: Salem, New Hampshire, US
Contact:

Post by Bob Hansen » Sat Feb 28, 2009 1:01 am

Does this work to strip the Null? It does work for alpha chars 97-122.

I am not familiar with the LibFunc used, so you will need to adapt this first variable vString:

Code: Select all

VBSTART
VBEND

Let>vString=%result of LibFunc%
Let>vNull=Chr(0)
VBEval>Replace("%vString%",%vNull%,""),vResult
MessageModal>Answer is %vResult%
Hope this was helpful..................good luck,
Bob
A humble man and PROUD of it!

User avatar
JRL
Automation Wizard
Posts: 3526
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Sat Feb 28, 2009 5:29 am

Hi Bob,

Problem is that if the value of the variable "vString" in the line
VBEval>Replace("%vString%",%vNull%,""),vResult
contains any nul characters, it throws the error mentioned as the Subject of this thread. I couldn't make the VBScript function accept a nul character even within a proper visual basic script. Would certainly have been the obvious and easy thing to do.

Code: Select all

LibFunc>kernel32,GetVolumeInformationA,info,E:\,str REF:0,200,REF:0,REF:0,REF:0,str REF:0,255

VBSTART
VBEND

Let>vString=%info_2%
Let>vNull=Chr(0)
VBEval>Replace("%vString%",%vNull%,""),vResult
MessageModal>Answer is %vResult%
ERROR wrote:Microsoft VBScript compilation error :1033

Unterminated string constant

Line 4, Column 20

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Sat Feb 28, 2009 9:42 pm

JRL wrote:Problem is that if the value of the variable "vString" in the line
VBEval>Replace("%vString%",%vNull%,""),vResult
contains any nul characters, it throws the error mentioned as the Subject of this thread. I couldn't make the VBScript function accept a nul character even within a proper visual basic script. Would certainly have been the obvious and easy thing to do.
Exactly (and easy is good).

We know we can use Separate> and Marcus has shown another method which uses Position> to find where the null character is in the variable (say its the 4th character) then simply uses MidStr> to produce a second string containing only characters 1, 2 and 3.

I guess I should have been more clear with the challenge. What I was looking for was an "easier" way to strip null characters from a variable:
new conditions wrote:1) without having to build code that looks at each character in the variable individualy... comparing to see if that character is a null char

2) without building code where I have to first find at which character position the null char is at... them using additional lines of code to extract substrings to leave the null char behind
I just wanted to know if there was a simple non-code-intensive way to pass a variable containing one or more null characters... to something, a command, a function... and have it return that same variable... only with the null characters gone.

JRL, your modified solution from Kpassaur just takes the stick-handling that Marcus did with Position> and MidStr> in MacroScript... and moves it into VBscript. I am curious if it can be done without having to the build control structures described in 1) and 2) above.

Bounty is still open but let's bump it up... 3 points now. :twisted:

Marcus, is you have a solution, please hold off for a few days.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
JRL
Automation Wizard
Posts: 3526
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Sun Mar 01, 2009 6:22 am

Doesn't Notepad convert nul characters to spaces?

Code: Select all

Let>Drive=E:\

LibFunc>kernel32,GetVolumeInformationA,info,Drive,str REF:0,200,REF:0,REF:0,REF:0,str REF:0,255
IfFileExists>%Temp_Dir%volumeinfo.txt
  DeleteFile>%Temp_Dir%volumeinfo.txt
EndIf
WriteLn>%Temp_Dir%volumeinfo.txt,wres,info_2
//constants
Let>GWL_EXSTYLE=-20
Let>WS_EX_LAYERED=524288
Let>LWA_ALPHA=2

//opacity
Let>byteOpacity=1

//run notepad and get its handle
Let>RP_WINDOWMODE=0
Run>notepad.exe %Temp_Dir%volumeinfo.txt
WaitWindowOpen>volumeinfo*
GetWindowHandle>volumeinfo*,nphwnd

//get style attributes of notepad's window
LibFunc>user32,GetWindowLongA,attribs,nphwnd,GWL_EXSTYLE
Let>attribs={%attribs% OR %WS_EX_LAYERED%}

//make notepad transparent
LibFunc>user32,SetWindowLongA,swl,nphwnd,GWL_EXSTYLE,attribs
LibFunc>user32,SetLayeredWindowAttributes,res,nphwnd,0,byteOpacity,LWA_ALPHA

IfFileExists>%Temp_Dir%volumeinfo.txt
  DeleteFile>%Temp_Dir%volumeinfo.txt
EndIf


SetFocus>volumeinfo.txt*
Press ctrl
send>a
Release ctrl
Press ctrl
send>c
Release ctrl
CloseWindow>volumeinfo*
GetClipBoard>info_2

mdl>info_2

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Sun Mar 01, 2009 11:21 am

Hi JRL,

Well evidently Notepad does do that... :lol: very creative... the 3 points are yours.

Incidentally, the Length command shows the length of info_2 to be 255 right after creation... and after being written to a file, opened with notepad, copy and pasted from notepad into the clipboard, retrieved from the clipboard and finally displayed... after all that... it grew to 257 chars.

Then I realized, it was your WriteLn> command... adding in the extra CRLF. To eliminate that I added the following line prior to the WriteLn>...

Let>WLN_NOCRLF=1
WriteLn>%Temp_Dir%volumeinfo.txt,wres,info_

...and now info_2 stays at 255 characters.

At one point, I had high hopes for RegEx but the following codes fails:

Code: Select all

VBSTART
Function ReplNullChars(strng,replchar)
   Dim regEx
   Set regEx = New RegExp
   regEx.Pattern = "\0"
   regEx.Global = True
   ReplNullChars = regEx.Replace(strng,replchar)
End Function
VBEND

Let>Drive=E:\
LibFunc>kernel32,GetVolumeInformationA,info,Drive,str REF:0,200,REF:0,REF:0,REF:0,str REF:0,255

MDL>info_2
VBEval>ReplNullChars("%info_2%","|"),newval
MDL>newval
And it fails with our favorite error:

Microsoft VBScript compilation error :1033
Unterminated string constant


Marcus, do you or does anyone know how the above code using RegEx with VBscript could be changed to make it work?

If not and VBscript is to blame... then I hope the new upcoming MS RegEx command can handle a replacement involving the null character.

Notepad as a null character filter! JRL how do you come up with this stuff? Enjoy the points and thanks for all your help here on the forums.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
Marcus Tettmar
Site Admin
Posts: 7395
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Mon Mar 02, 2009 10:52 am

First, there's a syntax error in your LibFunc call, which should be:

LibFunc>kernel32,GetVolumeInformationA,info,Drive,str:0,200,REF:0,REF:0,REF:0,str:0,255

Strings are always passed by reference. So you do not need and cannot mix str and ref.

You need to remember that a null char is a "Null Terminator". VBScript is complaining because the string ends prematurely. I don't think you'll be able to pass a string containing a null char into VBScript.

Also, Windows API functions stop when they see the first null char. This is also what's happening with StringReplace. It doesn't see past the null char so it can't replace them (this can't be changed as StringReplace calls system functions)..

The only sensible solution in my view is using MidStr when the null char signifies the end of the data (most cases - it's a null terminator). Or if you need to rid a string of a number of null chars a simple Repeat/Until using MidStr/Position can be used.

However, I have just done a test and, yes, the new RegEx function CAN find the null chars and can replace them:

Code: Select all

Let>Drive=C:\
LibFunc>kernel32,GetVolumeInformationA,info,Drive,str:0,200,REF:0,REF:0,REF:0,str:0,255

RegEx>\0,info_2,0,matches,num,1,,info_2
Length>info_2,len
MessageModal>Vol name: %info_2% Length: len
This code requires 11.1.05 which was released 2nd March 2009.
Last edited by Marcus Tettmar on Mon Mar 02, 2009 6:20 pm, edited 2 times in total.
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Mon Mar 02, 2009 4:41 pm

Hi Marcus,
mtettmar wrote:First, there's a syntax error in your LibFunc call, which should be:

LibFunc>kernel32,GetVolumeInformationA,info,Drive,REF:0,200,REF:0,REF:0,REF:0,REF:0,255
The LibFunc call you suggest doesn't work for me in MS 11.1.04...

Code: Select all

Let>Drive=F:\

//When I use my original LibFunc> call...
LibFunc>kernel32,GetVolumeInformationA,info,Drive,str REF:0,200,REF:0,REF:0,REF:0,str REF:0,255

//...the VolumeName shown is "Vol2" which is correct
MDL>info_2


//When I use the LibFunc> line you suggest...
LibFunc>kernel32,GetVolumeInformationA,info,Drive,REF:0,200,REF:0,REF:0,REF:0,REF:0,255

//...the VolumeName shown is "845967190" which is incorrect
MDL>info_2
Can you reproduce similar results using the above code on XP SP3?

What exactly was wrong with my original LibFunc> call? As the code shows above... it does seem to work...
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
Marcus Tettmar
Site Admin
Posts: 7395
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Mon Mar 02, 2009 6:22 pm

Sorry, I mucked up. I've edited my reply with the correct syntax.

LibFunc>kernel32,GetVolumeInformationA,info,Drive,str:0,200,REF:0,REF:0,REF:0,str:0,255

You shouldn't mix str and ref. Makes no sense and will probably affect the outcome. Strings are always passed by reference. Ref is only needed for numeric variables that must be passed by reference.
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Tue Mar 03, 2009 4:38 am

Hi Marcus,

OK, thanks. The following works for me in MS version 11.1.05 and makes removing or replacing null characters quite easy:

Code: Select all

Let>Drive=C:\

LibFunc>kernel32,GetVolumeInformationA,info,Drive,str:0,200,REF:0,REF:0,REF:0,str:0,255
//Remove null characters in info_2
RegEx>\0,info_2,0,matches,num,1,,info_2
Length>info_2,len
MessageModal>Vol name: %info_2% Length: %len%

LibFunc>kernel32,GetVolumeInformationA,info,Drive,str:0,200,REF:0,REF:0,REF:0,str:0,255
//Replace null characters in info_2 with verticle bar | characters
//and use EasyPatterns
RegEx>[null],info_2,1,matches,num,1,|,info_2
Length>info_2,len
MessageModal>Vol name: %info_2% Length: %len%
Thanks again for the new RegEx command with EasyPatterns... great new functionality.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

Post Reply
cron
Sign up to our newsletter for free automation tips, tricks & discounts